18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * drxd_hard.c: DVB-T Demodulator Micronas DRX3975D-A2,DRX397xD-B1 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2003-2007 Micronas 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/kernel.h> 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 118c2ecf20Sopenharmony_ci#include <linux/init.h> 128c2ecf20Sopenharmony_ci#include <linux/delay.h> 138c2ecf20Sopenharmony_ci#include <linux/firmware.h> 148c2ecf20Sopenharmony_ci#include <linux/i2c.h> 158c2ecf20Sopenharmony_ci#include <asm/div64.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <media/dvb_frontend.h> 188c2ecf20Sopenharmony_ci#include "drxd.h" 198c2ecf20Sopenharmony_ci#include "drxd_firm.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define DRX_FW_FILENAME_A2 "drxd-a2-1.1.fw" 228c2ecf20Sopenharmony_ci#define DRX_FW_FILENAME_B1 "drxd-b1-1.1.fw" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define CHUNK_SIZE 48 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define DRX_I2C_RMW 0x10 278c2ecf20Sopenharmony_ci#define DRX_I2C_BROADCAST 0x20 288c2ecf20Sopenharmony_ci#define DRX_I2C_CLEARCRC 0x80 298c2ecf20Sopenharmony_ci#define DRX_I2C_SINGLE_MASTER 0xC0 308c2ecf20Sopenharmony_ci#define DRX_I2C_MODEFLAGS 0xC0 318c2ecf20Sopenharmony_ci#define DRX_I2C_FLAGS 0xF0 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define DEFAULT_LOCK_TIMEOUT 1100 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define DRX_CHANNEL_AUTO 0 368c2ecf20Sopenharmony_ci#define DRX_CHANNEL_HIGH 1 378c2ecf20Sopenharmony_ci#define DRX_CHANNEL_LOW 2 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define DRX_LOCK_MPEG 1 408c2ecf20Sopenharmony_ci#define DRX_LOCK_FEC 2 418c2ecf20Sopenharmony_ci#define DRX_LOCK_DEMOD 4 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/****************************************************************************/ 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cienum CSCDState { 468c2ecf20Sopenharmony_ci CSCD_INIT = 0, 478c2ecf20Sopenharmony_ci CSCD_SET, 488c2ecf20Sopenharmony_ci CSCD_SAVED 498c2ecf20Sopenharmony_ci}; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cienum CDrxdState { 528c2ecf20Sopenharmony_ci DRXD_UNINITIALIZED = 0, 538c2ecf20Sopenharmony_ci DRXD_STOPPED, 548c2ecf20Sopenharmony_ci DRXD_STARTED 558c2ecf20Sopenharmony_ci}; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cienum AGC_CTRL_MODE { 588c2ecf20Sopenharmony_ci AGC_CTRL_AUTO = 0, 598c2ecf20Sopenharmony_ci AGC_CTRL_USER, 608c2ecf20Sopenharmony_ci AGC_CTRL_OFF 618c2ecf20Sopenharmony_ci}; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cienum OperationMode { 648c2ecf20Sopenharmony_ci OM_Default, 658c2ecf20Sopenharmony_ci OM_DVBT_Diversity_Front, 668c2ecf20Sopenharmony_ci OM_DVBT_Diversity_End 678c2ecf20Sopenharmony_ci}; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistruct SCfgAgc { 708c2ecf20Sopenharmony_ci enum AGC_CTRL_MODE ctrlMode; 718c2ecf20Sopenharmony_ci u16 outputLevel; /* range [0, ... , 1023], 1/n of fullscale range */ 728c2ecf20Sopenharmony_ci u16 settleLevel; /* range [0, ... , 1023], 1/n of fullscale range */ 738c2ecf20Sopenharmony_ci u16 minOutputLevel; /* range [0, ... , 1023], 1/n of fullscale range */ 748c2ecf20Sopenharmony_ci u16 maxOutputLevel; /* range [0, ... , 1023], 1/n of fullscale range */ 758c2ecf20Sopenharmony_ci u16 speed; /* range [0, ... , 1023], 1/n of fullscale range */ 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci u16 R1; 788c2ecf20Sopenharmony_ci u16 R2; 798c2ecf20Sopenharmony_ci u16 R3; 808c2ecf20Sopenharmony_ci}; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistruct SNoiseCal { 838c2ecf20Sopenharmony_ci int cpOpt; 848c2ecf20Sopenharmony_ci short cpNexpOfs; 858c2ecf20Sopenharmony_ci short tdCal2k; 868c2ecf20Sopenharmony_ci short tdCal8k; 878c2ecf20Sopenharmony_ci}; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cienum app_env { 908c2ecf20Sopenharmony_ci APPENV_STATIC = 0, 918c2ecf20Sopenharmony_ci APPENV_PORTABLE = 1, 928c2ecf20Sopenharmony_ci APPENV_MOBILE = 2 938c2ecf20Sopenharmony_ci}; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cienum EIFFilter { 968c2ecf20Sopenharmony_ci IFFILTER_SAW = 0, 978c2ecf20Sopenharmony_ci IFFILTER_DISCRETE = 1 988c2ecf20Sopenharmony_ci}; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistruct drxd_state { 1018c2ecf20Sopenharmony_ci struct dvb_frontend frontend; 1028c2ecf20Sopenharmony_ci struct dvb_frontend_ops ops; 1038c2ecf20Sopenharmony_ci struct dtv_frontend_properties props; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci const struct firmware *fw; 1068c2ecf20Sopenharmony_ci struct device *dev; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci struct i2c_adapter *i2c; 1098c2ecf20Sopenharmony_ci void *priv; 1108c2ecf20Sopenharmony_ci struct drxd_config config; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci int i2c_access; 1138c2ecf20Sopenharmony_ci int init_done; 1148c2ecf20Sopenharmony_ci struct mutex mutex; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci u8 chip_adr; 1178c2ecf20Sopenharmony_ci u16 hi_cfg_timing_div; 1188c2ecf20Sopenharmony_ci u16 hi_cfg_bridge_delay; 1198c2ecf20Sopenharmony_ci u16 hi_cfg_wakeup_key; 1208c2ecf20Sopenharmony_ci u16 hi_cfg_ctrl; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci u16 intermediate_freq; 1238c2ecf20Sopenharmony_ci u16 osc_clock_freq; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci enum CSCDState cscd_state; 1268c2ecf20Sopenharmony_ci enum CDrxdState drxd_state; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci u16 sys_clock_freq; 1298c2ecf20Sopenharmony_ci s16 osc_clock_deviation; 1308c2ecf20Sopenharmony_ci u16 expected_sys_clock_freq; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci u16 insert_rs_byte; 1338c2ecf20Sopenharmony_ci u16 enable_parallel; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci int operation_mode; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci struct SCfgAgc if_agc_cfg; 1388c2ecf20Sopenharmony_ci struct SCfgAgc rf_agc_cfg; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci struct SNoiseCal noise_cal; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci u32 fe_fs_add_incr; 1438c2ecf20Sopenharmony_ci u32 org_fe_fs_add_incr; 1448c2ecf20Sopenharmony_ci u16 current_fe_if_incr; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci u16 m_FeAgRegAgPwd; 1478c2ecf20Sopenharmony_ci u16 m_FeAgRegAgAgcSio; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci u16 m_EcOcRegOcModeLop; 1508c2ecf20Sopenharmony_ci u16 m_EcOcRegSncSncLvl; 1518c2ecf20Sopenharmony_ci u8 *m_InitAtomicRead; 1528c2ecf20Sopenharmony_ci u8 *m_HiI2cPatch; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci u8 *m_ResetCEFR; 1558c2ecf20Sopenharmony_ci u8 *m_InitFE_1; 1568c2ecf20Sopenharmony_ci u8 *m_InitFE_2; 1578c2ecf20Sopenharmony_ci u8 *m_InitCP; 1588c2ecf20Sopenharmony_ci u8 *m_InitCE; 1598c2ecf20Sopenharmony_ci u8 *m_InitEQ; 1608c2ecf20Sopenharmony_ci u8 *m_InitSC; 1618c2ecf20Sopenharmony_ci u8 *m_InitEC; 1628c2ecf20Sopenharmony_ci u8 *m_ResetECRAM; 1638c2ecf20Sopenharmony_ci u8 *m_InitDiversityFront; 1648c2ecf20Sopenharmony_ci u8 *m_InitDiversityEnd; 1658c2ecf20Sopenharmony_ci u8 *m_DisableDiversity; 1668c2ecf20Sopenharmony_ci u8 *m_StartDiversityFront; 1678c2ecf20Sopenharmony_ci u8 *m_StartDiversityEnd; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci u8 *m_DiversityDelay8MHZ; 1708c2ecf20Sopenharmony_ci u8 *m_DiversityDelay6MHZ; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci u8 *microcode; 1738c2ecf20Sopenharmony_ci u32 microcode_length; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci int type_A; 1768c2ecf20Sopenharmony_ci int PGA; 1778c2ecf20Sopenharmony_ci int diversity; 1788c2ecf20Sopenharmony_ci int tuner_mirrors; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci enum app_env app_env_default; 1818c2ecf20Sopenharmony_ci enum app_env app_env_diversity; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci}; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci/****************************************************************************/ 1868c2ecf20Sopenharmony_ci/* I2C **********************************************************************/ 1878c2ecf20Sopenharmony_ci/****************************************************************************/ 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_cistatic int i2c_write(struct i2c_adapter *adap, u8 adr, u8 * data, int len) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len }; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci if (i2c_transfer(adap, &msg, 1) != 1) 1948c2ecf20Sopenharmony_ci return -1; 1958c2ecf20Sopenharmony_ci return 0; 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic int i2c_read(struct i2c_adapter *adap, 1998c2ecf20Sopenharmony_ci u8 adr, u8 *msg, int len, u8 *answ, int alen) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci struct i2c_msg msgs[2] = { 2028c2ecf20Sopenharmony_ci { 2038c2ecf20Sopenharmony_ci .addr = adr, .flags = 0, 2048c2ecf20Sopenharmony_ci .buf = msg, .len = len 2058c2ecf20Sopenharmony_ci }, { 2068c2ecf20Sopenharmony_ci .addr = adr, .flags = I2C_M_RD, 2078c2ecf20Sopenharmony_ci .buf = answ, .len = alen 2088c2ecf20Sopenharmony_ci } 2098c2ecf20Sopenharmony_ci }; 2108c2ecf20Sopenharmony_ci if (i2c_transfer(adap, msgs, 2) != 2) 2118c2ecf20Sopenharmony_ci return -1; 2128c2ecf20Sopenharmony_ci return 0; 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic inline u32 MulDiv32(u32 a, u32 b, u32 c) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci u64 tmp64; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci tmp64 = (u64)a * (u64)b; 2208c2ecf20Sopenharmony_ci do_div(tmp64, c); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci return (u32) tmp64; 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic int Read16(struct drxd_state *state, u32 reg, u16 *data, u8 flags) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci u8 adr = state->config.demod_address; 2288c2ecf20Sopenharmony_ci u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff, 2298c2ecf20Sopenharmony_ci flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff 2308c2ecf20Sopenharmony_ci }; 2318c2ecf20Sopenharmony_ci u8 mm2[2]; 2328c2ecf20Sopenharmony_ci if (i2c_read(state->i2c, adr, mm1, 4, mm2, 2) < 0) 2338c2ecf20Sopenharmony_ci return -1; 2348c2ecf20Sopenharmony_ci if (data) 2358c2ecf20Sopenharmony_ci *data = mm2[0] | (mm2[1] << 8); 2368c2ecf20Sopenharmony_ci return mm2[0] | (mm2[1] << 8); 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_cistatic int Read32(struct drxd_state *state, u32 reg, u32 *data, u8 flags) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci u8 adr = state->config.demod_address; 2428c2ecf20Sopenharmony_ci u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff, 2438c2ecf20Sopenharmony_ci flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff 2448c2ecf20Sopenharmony_ci }; 2458c2ecf20Sopenharmony_ci u8 mm2[4]; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (i2c_read(state->i2c, adr, mm1, 4, mm2, 4) < 0) 2488c2ecf20Sopenharmony_ci return -1; 2498c2ecf20Sopenharmony_ci if (data) 2508c2ecf20Sopenharmony_ci *data = 2518c2ecf20Sopenharmony_ci mm2[0] | (mm2[1] << 8) | (mm2[2] << 16) | (mm2[3] << 24); 2528c2ecf20Sopenharmony_ci return 0; 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_cistatic int Write16(struct drxd_state *state, u32 reg, u16 data, u8 flags) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci u8 adr = state->config.demod_address; 2588c2ecf20Sopenharmony_ci u8 mm[6] = { reg & 0xff, (reg >> 16) & 0xff, 2598c2ecf20Sopenharmony_ci flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff, 2608c2ecf20Sopenharmony_ci data & 0xff, (data >> 8) & 0xff 2618c2ecf20Sopenharmony_ci }; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (i2c_write(state->i2c, adr, mm, 6) < 0) 2648c2ecf20Sopenharmony_ci return -1; 2658c2ecf20Sopenharmony_ci return 0; 2668c2ecf20Sopenharmony_ci} 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_cistatic int Write32(struct drxd_state *state, u32 reg, u32 data, u8 flags) 2698c2ecf20Sopenharmony_ci{ 2708c2ecf20Sopenharmony_ci u8 adr = state->config.demod_address; 2718c2ecf20Sopenharmony_ci u8 mm[8] = { reg & 0xff, (reg >> 16) & 0xff, 2728c2ecf20Sopenharmony_ci flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff, 2738c2ecf20Sopenharmony_ci data & 0xff, (data >> 8) & 0xff, 2748c2ecf20Sopenharmony_ci (data >> 16) & 0xff, (data >> 24) & 0xff 2758c2ecf20Sopenharmony_ci }; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci if (i2c_write(state->i2c, adr, mm, 8) < 0) 2788c2ecf20Sopenharmony_ci return -1; 2798c2ecf20Sopenharmony_ci return 0; 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cistatic int write_chunk(struct drxd_state *state, 2838c2ecf20Sopenharmony_ci u32 reg, u8 *data, u32 len, u8 flags) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci u8 adr = state->config.demod_address; 2868c2ecf20Sopenharmony_ci u8 mm[CHUNK_SIZE + 4] = { reg & 0xff, (reg >> 16) & 0xff, 2878c2ecf20Sopenharmony_ci flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff 2888c2ecf20Sopenharmony_ci }; 2898c2ecf20Sopenharmony_ci int i; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) 2928c2ecf20Sopenharmony_ci mm[4 + i] = data[i]; 2938c2ecf20Sopenharmony_ci if (i2c_write(state->i2c, adr, mm, 4 + len) < 0) { 2948c2ecf20Sopenharmony_ci printk(KERN_ERR "error in write_chunk\n"); 2958c2ecf20Sopenharmony_ci return -1; 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci return 0; 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic int WriteBlock(struct drxd_state *state, 3018c2ecf20Sopenharmony_ci u32 Address, u16 BlockSize, u8 *pBlock, u8 Flags) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci while (BlockSize > 0) { 3048c2ecf20Sopenharmony_ci u16 Chunk = BlockSize > CHUNK_SIZE ? CHUNK_SIZE : BlockSize; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci if (write_chunk(state, Address, pBlock, Chunk, Flags) < 0) 3078c2ecf20Sopenharmony_ci return -1; 3088c2ecf20Sopenharmony_ci pBlock += Chunk; 3098c2ecf20Sopenharmony_ci Address += (Chunk >> 1); 3108c2ecf20Sopenharmony_ci BlockSize -= Chunk; 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci return 0; 3138c2ecf20Sopenharmony_ci} 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_cistatic int WriteTable(struct drxd_state *state, u8 * pTable) 3168c2ecf20Sopenharmony_ci{ 3178c2ecf20Sopenharmony_ci int status = 0; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci if (!pTable) 3208c2ecf20Sopenharmony_ci return 0; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci while (!status) { 3238c2ecf20Sopenharmony_ci u16 Length; 3248c2ecf20Sopenharmony_ci u32 Address = pTable[0] | (pTable[1] << 8) | 3258c2ecf20Sopenharmony_ci (pTable[2] << 16) | (pTable[3] << 24); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (Address == 0xFFFFFFFF) 3288c2ecf20Sopenharmony_ci break; 3298c2ecf20Sopenharmony_ci pTable += sizeof(u32); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci Length = pTable[0] | (pTable[1] << 8); 3328c2ecf20Sopenharmony_ci pTable += sizeof(u16); 3338c2ecf20Sopenharmony_ci if (!Length) 3348c2ecf20Sopenharmony_ci break; 3358c2ecf20Sopenharmony_ci status = WriteBlock(state, Address, Length * 2, pTable, 0); 3368c2ecf20Sopenharmony_ci pTable += (Length * 2); 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci return status; 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci/****************************************************************************/ 3428c2ecf20Sopenharmony_ci/****************************************************************************/ 3438c2ecf20Sopenharmony_ci/****************************************************************************/ 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_cistatic int ResetCEFR(struct drxd_state *state) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci return WriteTable(state, state->m_ResetCEFR); 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic int InitCP(struct drxd_state *state) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci return WriteTable(state, state->m_InitCP); 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic int InitCE(struct drxd_state *state) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci int status; 3588c2ecf20Sopenharmony_ci enum app_env AppEnv = state->app_env_default; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci do { 3618c2ecf20Sopenharmony_ci status = WriteTable(state, state->m_InitCE); 3628c2ecf20Sopenharmony_ci if (status < 0) 3638c2ecf20Sopenharmony_ci break; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci if (state->operation_mode == OM_DVBT_Diversity_Front || 3668c2ecf20Sopenharmony_ci state->operation_mode == OM_DVBT_Diversity_End) { 3678c2ecf20Sopenharmony_ci AppEnv = state->app_env_diversity; 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci if (AppEnv == APPENV_STATIC) { 3708c2ecf20Sopenharmony_ci status = Write16(state, CE_REG_TAPSET__A, 0x0000, 0); 3718c2ecf20Sopenharmony_ci if (status < 0) 3728c2ecf20Sopenharmony_ci break; 3738c2ecf20Sopenharmony_ci } else if (AppEnv == APPENV_PORTABLE) { 3748c2ecf20Sopenharmony_ci status = Write16(state, CE_REG_TAPSET__A, 0x0001, 0); 3758c2ecf20Sopenharmony_ci if (status < 0) 3768c2ecf20Sopenharmony_ci break; 3778c2ecf20Sopenharmony_ci } else if (AppEnv == APPENV_MOBILE && state->type_A) { 3788c2ecf20Sopenharmony_ci status = Write16(state, CE_REG_TAPSET__A, 0x0002, 0); 3798c2ecf20Sopenharmony_ci if (status < 0) 3808c2ecf20Sopenharmony_ci break; 3818c2ecf20Sopenharmony_ci } else if (AppEnv == APPENV_MOBILE && !state->type_A) { 3828c2ecf20Sopenharmony_ci status = Write16(state, CE_REG_TAPSET__A, 0x0006, 0); 3838c2ecf20Sopenharmony_ci if (status < 0) 3848c2ecf20Sopenharmony_ci break; 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci /* start ce */ 3888c2ecf20Sopenharmony_ci status = Write16(state, B_CE_REG_COMM_EXEC__A, 0x0001, 0); 3898c2ecf20Sopenharmony_ci if (status < 0) 3908c2ecf20Sopenharmony_ci break; 3918c2ecf20Sopenharmony_ci } while (0); 3928c2ecf20Sopenharmony_ci return status; 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_cistatic int StopOC(struct drxd_state *state) 3968c2ecf20Sopenharmony_ci{ 3978c2ecf20Sopenharmony_ci int status = 0; 3988c2ecf20Sopenharmony_ci u16 ocSyncLvl = 0; 3998c2ecf20Sopenharmony_ci u16 ocModeLop = state->m_EcOcRegOcModeLop; 4008c2ecf20Sopenharmony_ci u16 dtoIncLop = 0; 4018c2ecf20Sopenharmony_ci u16 dtoIncHip = 0; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci do { 4048c2ecf20Sopenharmony_ci /* Store output configuration */ 4058c2ecf20Sopenharmony_ci status = Read16(state, EC_OC_REG_SNC_ISC_LVL__A, &ocSyncLvl, 0); 4068c2ecf20Sopenharmony_ci if (status < 0) 4078c2ecf20Sopenharmony_ci break; 4088c2ecf20Sopenharmony_ci /* CHK_ERROR(Read16(EC_OC_REG_OC_MODE_LOP__A, &ocModeLop)); */ 4098c2ecf20Sopenharmony_ci state->m_EcOcRegSncSncLvl = ocSyncLvl; 4108c2ecf20Sopenharmony_ci /* m_EcOcRegOcModeLop = ocModeLop; */ 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci /* Flush FIFO (byte-boundary) at fixed rate */ 4138c2ecf20Sopenharmony_ci status = Read16(state, EC_OC_REG_RCN_MAP_LOP__A, &dtoIncLop, 0); 4148c2ecf20Sopenharmony_ci if (status < 0) 4158c2ecf20Sopenharmony_ci break; 4168c2ecf20Sopenharmony_ci status = Read16(state, EC_OC_REG_RCN_MAP_HIP__A, &dtoIncHip, 0); 4178c2ecf20Sopenharmony_ci if (status < 0) 4188c2ecf20Sopenharmony_ci break; 4198c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_DTO_INC_LOP__A, dtoIncLop, 0); 4208c2ecf20Sopenharmony_ci if (status < 0) 4218c2ecf20Sopenharmony_ci break; 4228c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_DTO_INC_HIP__A, dtoIncHip, 0); 4238c2ecf20Sopenharmony_ci if (status < 0) 4248c2ecf20Sopenharmony_ci break; 4258c2ecf20Sopenharmony_ci ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M); 4268c2ecf20Sopenharmony_ci ocModeLop |= EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC; 4278c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0); 4288c2ecf20Sopenharmony_ci if (status < 0) 4298c2ecf20Sopenharmony_ci break; 4308c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0); 4318c2ecf20Sopenharmony_ci if (status < 0) 4328c2ecf20Sopenharmony_ci break; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci msleep(1); 4358c2ecf20Sopenharmony_ci /* Output pins to '0' */ 4368c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS__M, 0); 4378c2ecf20Sopenharmony_ci if (status < 0) 4388c2ecf20Sopenharmony_ci break; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci /* Force the OC out of sync */ 4418c2ecf20Sopenharmony_ci ocSyncLvl &= ~(EC_OC_REG_SNC_ISC_LVL_OSC__M); 4428c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, ocSyncLvl, 0); 4438c2ecf20Sopenharmony_ci if (status < 0) 4448c2ecf20Sopenharmony_ci break; 4458c2ecf20Sopenharmony_ci ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M); 4468c2ecf20Sopenharmony_ci ocModeLop |= EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE; 4478c2ecf20Sopenharmony_ci ocModeLop |= 0x2; /* Magically-out-of-sync */ 4488c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0); 4498c2ecf20Sopenharmony_ci if (status < 0) 4508c2ecf20Sopenharmony_ci break; 4518c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_COMM_INT_STA__A, 0x0, 0); 4528c2ecf20Sopenharmony_ci if (status < 0) 4538c2ecf20Sopenharmony_ci break; 4548c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0); 4558c2ecf20Sopenharmony_ci if (status < 0) 4568c2ecf20Sopenharmony_ci break; 4578c2ecf20Sopenharmony_ci } while (0); 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci return status; 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_cistatic int StartOC(struct drxd_state *state) 4638c2ecf20Sopenharmony_ci{ 4648c2ecf20Sopenharmony_ci int status = 0; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci do { 4678c2ecf20Sopenharmony_ci /* Stop OC */ 4688c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0); 4698c2ecf20Sopenharmony_ci if (status < 0) 4708c2ecf20Sopenharmony_ci break; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci /* Restore output configuration */ 4738c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, state->m_EcOcRegSncSncLvl, 0); 4748c2ecf20Sopenharmony_ci if (status < 0) 4758c2ecf20Sopenharmony_ci break; 4768c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, state->m_EcOcRegOcModeLop, 0); 4778c2ecf20Sopenharmony_ci if (status < 0) 4788c2ecf20Sopenharmony_ci break; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci /* Output pins active again */ 4818c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS_INIT, 0); 4828c2ecf20Sopenharmony_ci if (status < 0) 4838c2ecf20Sopenharmony_ci break; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci /* Start OC */ 4868c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0); 4878c2ecf20Sopenharmony_ci if (status < 0) 4888c2ecf20Sopenharmony_ci break; 4898c2ecf20Sopenharmony_ci } while (0); 4908c2ecf20Sopenharmony_ci return status; 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cistatic int InitEQ(struct drxd_state *state) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci return WriteTable(state, state->m_InitEQ); 4968c2ecf20Sopenharmony_ci} 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_cistatic int InitEC(struct drxd_state *state) 4998c2ecf20Sopenharmony_ci{ 5008c2ecf20Sopenharmony_ci return WriteTable(state, state->m_InitEC); 5018c2ecf20Sopenharmony_ci} 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_cistatic int InitSC(struct drxd_state *state) 5048c2ecf20Sopenharmony_ci{ 5058c2ecf20Sopenharmony_ci return WriteTable(state, state->m_InitSC); 5068c2ecf20Sopenharmony_ci} 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_cistatic int InitAtomicRead(struct drxd_state *state) 5098c2ecf20Sopenharmony_ci{ 5108c2ecf20Sopenharmony_ci return WriteTable(state, state->m_InitAtomicRead); 5118c2ecf20Sopenharmony_ci} 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_cistatic int CorrectSysClockDeviation(struct drxd_state *state); 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_cistatic int DRX_GetLockStatus(struct drxd_state *state, u32 * pLockStatus) 5168c2ecf20Sopenharmony_ci{ 5178c2ecf20Sopenharmony_ci u16 ScRaRamLock = 0; 5188c2ecf20Sopenharmony_ci const u16 mpeg_lock_mask = (SC_RA_RAM_LOCK_MPEG__M | 5198c2ecf20Sopenharmony_ci SC_RA_RAM_LOCK_FEC__M | 5208c2ecf20Sopenharmony_ci SC_RA_RAM_LOCK_DEMOD__M); 5218c2ecf20Sopenharmony_ci const u16 fec_lock_mask = (SC_RA_RAM_LOCK_FEC__M | 5228c2ecf20Sopenharmony_ci SC_RA_RAM_LOCK_DEMOD__M); 5238c2ecf20Sopenharmony_ci const u16 demod_lock_mask = SC_RA_RAM_LOCK_DEMOD__M; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci int status; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci *pLockStatus = 0; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci status = Read16(state, SC_RA_RAM_LOCK__A, &ScRaRamLock, 0x0000); 5308c2ecf20Sopenharmony_ci if (status < 0) { 5318c2ecf20Sopenharmony_ci printk(KERN_ERR "Can't read SC_RA_RAM_LOCK__A status = %08x\n", status); 5328c2ecf20Sopenharmony_ci return status; 5338c2ecf20Sopenharmony_ci } 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci if (state->drxd_state != DRXD_STARTED) 5368c2ecf20Sopenharmony_ci return 0; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask) { 5398c2ecf20Sopenharmony_ci *pLockStatus |= DRX_LOCK_MPEG; 5408c2ecf20Sopenharmony_ci CorrectSysClockDeviation(state); 5418c2ecf20Sopenharmony_ci } 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask) 5448c2ecf20Sopenharmony_ci *pLockStatus |= DRX_LOCK_FEC; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask) 5478c2ecf20Sopenharmony_ci *pLockStatus |= DRX_LOCK_DEMOD; 5488c2ecf20Sopenharmony_ci return 0; 5498c2ecf20Sopenharmony_ci} 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci/****************************************************************************/ 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic int SetCfgIfAgc(struct drxd_state *state, struct SCfgAgc *cfg) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci int status; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci if (cfg->outputLevel > DRXD_FE_CTRL_MAX) 5588c2ecf20Sopenharmony_ci return -1; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci if (cfg->ctrlMode == AGC_CTRL_USER) { 5618c2ecf20Sopenharmony_ci do { 5628c2ecf20Sopenharmony_ci u16 FeAgRegPm1AgcWri; 5638c2ecf20Sopenharmony_ci u16 FeAgRegAgModeLop; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0); 5668c2ecf20Sopenharmony_ci if (status < 0) 5678c2ecf20Sopenharmony_ci break; 5688c2ecf20Sopenharmony_ci FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M); 5698c2ecf20Sopenharmony_ci FeAgRegAgModeLop |= FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC; 5708c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0); 5718c2ecf20Sopenharmony_ci if (status < 0) 5728c2ecf20Sopenharmony_ci break; 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci FeAgRegPm1AgcWri = (u16) (cfg->outputLevel & 5758c2ecf20Sopenharmony_ci FE_AG_REG_PM1_AGC_WRI__M); 5768c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_PM1_AGC_WRI__A, FeAgRegPm1AgcWri, 0); 5778c2ecf20Sopenharmony_ci if (status < 0) 5788c2ecf20Sopenharmony_ci break; 5798c2ecf20Sopenharmony_ci } while (0); 5808c2ecf20Sopenharmony_ci } else if (cfg->ctrlMode == AGC_CTRL_AUTO) { 5818c2ecf20Sopenharmony_ci if (((cfg->maxOutputLevel) < (cfg->minOutputLevel)) || 5828c2ecf20Sopenharmony_ci ((cfg->maxOutputLevel) > DRXD_FE_CTRL_MAX) || 5838c2ecf20Sopenharmony_ci ((cfg->speed) > DRXD_FE_CTRL_MAX) || 5848c2ecf20Sopenharmony_ci ((cfg->settleLevel) > DRXD_FE_CTRL_MAX) 5858c2ecf20Sopenharmony_ci ) 5868c2ecf20Sopenharmony_ci return -1; 5878c2ecf20Sopenharmony_ci do { 5888c2ecf20Sopenharmony_ci u16 FeAgRegAgModeLop; 5898c2ecf20Sopenharmony_ci u16 FeAgRegEgcSetLvl; 5908c2ecf20Sopenharmony_ci u16 slope, offset; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci /* == Mode == */ 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0); 5958c2ecf20Sopenharmony_ci if (status < 0) 5968c2ecf20Sopenharmony_ci break; 5978c2ecf20Sopenharmony_ci FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M); 5988c2ecf20Sopenharmony_ci FeAgRegAgModeLop |= 5998c2ecf20Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC; 6008c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0); 6018c2ecf20Sopenharmony_ci if (status < 0) 6028c2ecf20Sopenharmony_ci break; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci /* == Settle level == */ 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci FeAgRegEgcSetLvl = (u16) ((cfg->settleLevel >> 1) & 6078c2ecf20Sopenharmony_ci FE_AG_REG_EGC_SET_LVL__M); 6088c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_EGC_SET_LVL__A, FeAgRegEgcSetLvl, 0); 6098c2ecf20Sopenharmony_ci if (status < 0) 6108c2ecf20Sopenharmony_ci break; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci /* == Min/Max == */ 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci slope = (u16) ((cfg->maxOutputLevel - 6158c2ecf20Sopenharmony_ci cfg->minOutputLevel) / 2); 6168c2ecf20Sopenharmony_ci offset = (u16) ((cfg->maxOutputLevel + 6178c2ecf20Sopenharmony_ci cfg->minOutputLevel) / 2 - 511); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_GC1_AGC_RIC__A, slope, 0); 6208c2ecf20Sopenharmony_ci if (status < 0) 6218c2ecf20Sopenharmony_ci break; 6228c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_GC1_AGC_OFF__A, offset, 0); 6238c2ecf20Sopenharmony_ci if (status < 0) 6248c2ecf20Sopenharmony_ci break; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci /* == Speed == */ 6278c2ecf20Sopenharmony_ci { 6288c2ecf20Sopenharmony_ci const u16 maxRur = 8; 6298c2ecf20Sopenharmony_ci static const u16 slowIncrDecLUT[] = { 6308c2ecf20Sopenharmony_ci 3, 4, 4, 5, 6 }; 6318c2ecf20Sopenharmony_ci static const u16 fastIncrDecLUT[] = { 6328c2ecf20Sopenharmony_ci 14, 15, 15, 16, 6338c2ecf20Sopenharmony_ci 17, 18, 18, 19, 6348c2ecf20Sopenharmony_ci 20, 21, 22, 23, 6358c2ecf20Sopenharmony_ci 24, 26, 27, 28, 6368c2ecf20Sopenharmony_ci 29, 31 6378c2ecf20Sopenharmony_ci }; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci u16 fineSteps = (DRXD_FE_CTRL_MAX + 1) / 6408c2ecf20Sopenharmony_ci (maxRur + 1); 6418c2ecf20Sopenharmony_ci u16 fineSpeed = (u16) (cfg->speed - 6428c2ecf20Sopenharmony_ci ((cfg->speed / 6438c2ecf20Sopenharmony_ci fineSteps) * 6448c2ecf20Sopenharmony_ci fineSteps)); 6458c2ecf20Sopenharmony_ci u16 invRurCount = (u16) (cfg->speed / 6468c2ecf20Sopenharmony_ci fineSteps); 6478c2ecf20Sopenharmony_ci u16 rurCount; 6488c2ecf20Sopenharmony_ci if (invRurCount > maxRur) { 6498c2ecf20Sopenharmony_ci rurCount = 0; 6508c2ecf20Sopenharmony_ci fineSpeed += fineSteps; 6518c2ecf20Sopenharmony_ci } else { 6528c2ecf20Sopenharmony_ci rurCount = maxRur - invRurCount; 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci /* 6568c2ecf20Sopenharmony_ci fastInc = default * 6578c2ecf20Sopenharmony_ci (2^(fineSpeed/fineSteps)) 6588c2ecf20Sopenharmony_ci => range[default...2*default> 6598c2ecf20Sopenharmony_ci slowInc = default * 6608c2ecf20Sopenharmony_ci (2^(fineSpeed/fineSteps)) 6618c2ecf20Sopenharmony_ci */ 6628c2ecf20Sopenharmony_ci { 6638c2ecf20Sopenharmony_ci u16 fastIncrDec = 6648c2ecf20Sopenharmony_ci fastIncrDecLUT[fineSpeed / 6658c2ecf20Sopenharmony_ci ((fineSteps / 6668c2ecf20Sopenharmony_ci (14 + 1)) + 1)]; 6678c2ecf20Sopenharmony_ci u16 slowIncrDec = 6688c2ecf20Sopenharmony_ci slowIncrDecLUT[fineSpeed / 6698c2ecf20Sopenharmony_ci (fineSteps / 6708c2ecf20Sopenharmony_ci (3 + 1))]; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_EGC_RUR_CNT__A, rurCount, 0); 6738c2ecf20Sopenharmony_ci if (status < 0) 6748c2ecf20Sopenharmony_ci break; 6758c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_EGC_FAS_INC__A, fastIncrDec, 0); 6768c2ecf20Sopenharmony_ci if (status < 0) 6778c2ecf20Sopenharmony_ci break; 6788c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_EGC_FAS_DEC__A, fastIncrDec, 0); 6798c2ecf20Sopenharmony_ci if (status < 0) 6808c2ecf20Sopenharmony_ci break; 6818c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_EGC_SLO_INC__A, slowIncrDec, 0); 6828c2ecf20Sopenharmony_ci if (status < 0) 6838c2ecf20Sopenharmony_ci break; 6848c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_EGC_SLO_DEC__A, slowIncrDec, 0); 6858c2ecf20Sopenharmony_ci if (status < 0) 6868c2ecf20Sopenharmony_ci break; 6878c2ecf20Sopenharmony_ci } 6888c2ecf20Sopenharmony_ci } 6898c2ecf20Sopenharmony_ci } while (0); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci } else { 6928c2ecf20Sopenharmony_ci /* No OFF mode for IF control */ 6938c2ecf20Sopenharmony_ci return -1; 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci return status; 6968c2ecf20Sopenharmony_ci} 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_cistatic int SetCfgRfAgc(struct drxd_state *state, struct SCfgAgc *cfg) 6998c2ecf20Sopenharmony_ci{ 7008c2ecf20Sopenharmony_ci int status = 0; 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci if (cfg->outputLevel > DRXD_FE_CTRL_MAX) 7038c2ecf20Sopenharmony_ci return -1; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci if (cfg->ctrlMode == AGC_CTRL_USER) { 7068c2ecf20Sopenharmony_ci do { 7078c2ecf20Sopenharmony_ci u16 AgModeLop = 0; 7088c2ecf20Sopenharmony_ci u16 level = (cfg->outputLevel); 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci if (level == DRXD_FE_CTRL_MAX) 7118c2ecf20Sopenharmony_ci level++; 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_PM2_AGC_WRI__A, level, 0x0000); 7148c2ecf20Sopenharmony_ci if (status < 0) 7158c2ecf20Sopenharmony_ci break; 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci /*==== Mode ====*/ 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci /* Powerdown PD2, WRI source */ 7208c2ecf20Sopenharmony_ci state->m_FeAgRegAgPwd &= ~(FE_AG_REG_AG_PWD_PWD_PD2__M); 7218c2ecf20Sopenharmony_ci state->m_FeAgRegAgPwd |= 7228c2ecf20Sopenharmony_ci FE_AG_REG_AG_PWD_PWD_PD2_DISABLE; 7238c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000); 7248c2ecf20Sopenharmony_ci if (status < 0) 7258c2ecf20Sopenharmony_ci break; 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); 7288c2ecf20Sopenharmony_ci if (status < 0) 7298c2ecf20Sopenharmony_ci break; 7308c2ecf20Sopenharmony_ci AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M | 7318c2ecf20Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_E__M)); 7328c2ecf20Sopenharmony_ci AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC | 7338c2ecf20Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC); 7348c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); 7358c2ecf20Sopenharmony_ci if (status < 0) 7368c2ecf20Sopenharmony_ci break; 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci /* enable AGC2 pin */ 7398c2ecf20Sopenharmony_ci { 7408c2ecf20Sopenharmony_ci u16 FeAgRegAgAgcSio = 0; 7418c2ecf20Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000); 7428c2ecf20Sopenharmony_ci if (status < 0) 7438c2ecf20Sopenharmony_ci break; 7448c2ecf20Sopenharmony_ci FeAgRegAgAgcSio &= 7458c2ecf20Sopenharmony_ci ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M); 7468c2ecf20Sopenharmony_ci FeAgRegAgAgcSio |= 7478c2ecf20Sopenharmony_ci FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT; 7488c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000); 7498c2ecf20Sopenharmony_ci if (status < 0) 7508c2ecf20Sopenharmony_ci break; 7518c2ecf20Sopenharmony_ci } 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci } while (0); 7548c2ecf20Sopenharmony_ci } else if (cfg->ctrlMode == AGC_CTRL_AUTO) { 7558c2ecf20Sopenharmony_ci u16 AgModeLop = 0; 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci do { 7588c2ecf20Sopenharmony_ci u16 level; 7598c2ecf20Sopenharmony_ci /* Automatic control */ 7608c2ecf20Sopenharmony_ci /* Powerup PD2, AGC2 as output, TGC source */ 7618c2ecf20Sopenharmony_ci (state->m_FeAgRegAgPwd) &= 7628c2ecf20Sopenharmony_ci ~(FE_AG_REG_AG_PWD_PWD_PD2__M); 7638c2ecf20Sopenharmony_ci (state->m_FeAgRegAgPwd) |= 7648c2ecf20Sopenharmony_ci FE_AG_REG_AG_PWD_PWD_PD2_DISABLE; 7658c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000); 7668c2ecf20Sopenharmony_ci if (status < 0) 7678c2ecf20Sopenharmony_ci break; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); 7708c2ecf20Sopenharmony_ci if (status < 0) 7718c2ecf20Sopenharmony_ci break; 7728c2ecf20Sopenharmony_ci AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M | 7738c2ecf20Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_E__M)); 7748c2ecf20Sopenharmony_ci AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC | 7758c2ecf20Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC); 7768c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); 7778c2ecf20Sopenharmony_ci if (status < 0) 7788c2ecf20Sopenharmony_ci break; 7798c2ecf20Sopenharmony_ci /* Settle level */ 7808c2ecf20Sopenharmony_ci level = (((cfg->settleLevel) >> 4) & 7818c2ecf20Sopenharmony_ci FE_AG_REG_TGC_SET_LVL__M); 7828c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_TGC_SET_LVL__A, level, 0x0000); 7838c2ecf20Sopenharmony_ci if (status < 0) 7848c2ecf20Sopenharmony_ci break; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci /* Min/max: don't care */ 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci /* Speed: TODO */ 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci /* enable AGC2 pin */ 7918c2ecf20Sopenharmony_ci { 7928c2ecf20Sopenharmony_ci u16 FeAgRegAgAgcSio = 0; 7938c2ecf20Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000); 7948c2ecf20Sopenharmony_ci if (status < 0) 7958c2ecf20Sopenharmony_ci break; 7968c2ecf20Sopenharmony_ci FeAgRegAgAgcSio &= 7978c2ecf20Sopenharmony_ci ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M); 7988c2ecf20Sopenharmony_ci FeAgRegAgAgcSio |= 7998c2ecf20Sopenharmony_ci FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT; 8008c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000); 8018c2ecf20Sopenharmony_ci if (status < 0) 8028c2ecf20Sopenharmony_ci break; 8038c2ecf20Sopenharmony_ci } 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci } while (0); 8068c2ecf20Sopenharmony_ci } else { 8078c2ecf20Sopenharmony_ci u16 AgModeLop = 0; 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci do { 8108c2ecf20Sopenharmony_ci /* No RF AGC control */ 8118c2ecf20Sopenharmony_ci /* Powerdown PD2, AGC2 as output, WRI source */ 8128c2ecf20Sopenharmony_ci (state->m_FeAgRegAgPwd) &= 8138c2ecf20Sopenharmony_ci ~(FE_AG_REG_AG_PWD_PWD_PD2__M); 8148c2ecf20Sopenharmony_ci (state->m_FeAgRegAgPwd) |= 8158c2ecf20Sopenharmony_ci FE_AG_REG_AG_PWD_PWD_PD2_ENABLE; 8168c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000); 8178c2ecf20Sopenharmony_ci if (status < 0) 8188c2ecf20Sopenharmony_ci break; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); 8218c2ecf20Sopenharmony_ci if (status < 0) 8228c2ecf20Sopenharmony_ci break; 8238c2ecf20Sopenharmony_ci AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M | 8248c2ecf20Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_E__M)); 8258c2ecf20Sopenharmony_ci AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC | 8268c2ecf20Sopenharmony_ci FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC); 8278c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); 8288c2ecf20Sopenharmony_ci if (status < 0) 8298c2ecf20Sopenharmony_ci break; 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci /* set FeAgRegAgAgcSio AGC2 (RF) as input */ 8328c2ecf20Sopenharmony_ci { 8338c2ecf20Sopenharmony_ci u16 FeAgRegAgAgcSio = 0; 8348c2ecf20Sopenharmony_ci status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000); 8358c2ecf20Sopenharmony_ci if (status < 0) 8368c2ecf20Sopenharmony_ci break; 8378c2ecf20Sopenharmony_ci FeAgRegAgAgcSio &= 8388c2ecf20Sopenharmony_ci ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M); 8398c2ecf20Sopenharmony_ci FeAgRegAgAgcSio |= 8408c2ecf20Sopenharmony_ci FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT; 8418c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000); 8428c2ecf20Sopenharmony_ci if (status < 0) 8438c2ecf20Sopenharmony_ci break; 8448c2ecf20Sopenharmony_ci } 8458c2ecf20Sopenharmony_ci } while (0); 8468c2ecf20Sopenharmony_ci } 8478c2ecf20Sopenharmony_ci return status; 8488c2ecf20Sopenharmony_ci} 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_cistatic int ReadIFAgc(struct drxd_state *state, u32 * pValue) 8518c2ecf20Sopenharmony_ci{ 8528c2ecf20Sopenharmony_ci int status = 0; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci *pValue = 0; 8558c2ecf20Sopenharmony_ci if (state->if_agc_cfg.ctrlMode != AGC_CTRL_OFF) { 8568c2ecf20Sopenharmony_ci u16 Value; 8578c2ecf20Sopenharmony_ci status = Read16(state, FE_AG_REG_GC1_AGC_DAT__A, &Value, 0); 8588c2ecf20Sopenharmony_ci Value &= FE_AG_REG_GC1_AGC_DAT__M; 8598c2ecf20Sopenharmony_ci if (status >= 0) { 8608c2ecf20Sopenharmony_ci /* 3.3V 8618c2ecf20Sopenharmony_ci | 8628c2ecf20Sopenharmony_ci R1 8638c2ecf20Sopenharmony_ci | 8648c2ecf20Sopenharmony_ci Vin - R3 - * -- Vout 8658c2ecf20Sopenharmony_ci | 8668c2ecf20Sopenharmony_ci R2 8678c2ecf20Sopenharmony_ci | 8688c2ecf20Sopenharmony_ci GND 8698c2ecf20Sopenharmony_ci */ 8708c2ecf20Sopenharmony_ci u32 R1 = state->if_agc_cfg.R1; 8718c2ecf20Sopenharmony_ci u32 R2 = state->if_agc_cfg.R2; 8728c2ecf20Sopenharmony_ci u32 R3 = state->if_agc_cfg.R3; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci u32 Vmax, Rpar, Vmin, Vout; 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci if (R2 == 0 && (R1 == 0 || R3 == 0)) 8778c2ecf20Sopenharmony_ci return 0; 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci Vmax = (3300 * R2) / (R1 + R2); 8808c2ecf20Sopenharmony_ci Rpar = (R2 * R3) / (R3 + R2); 8818c2ecf20Sopenharmony_ci Vmin = (3300 * Rpar) / (R1 + Rpar); 8828c2ecf20Sopenharmony_ci Vout = Vmin + ((Vmax - Vmin) * Value) / 1024; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci *pValue = Vout; 8858c2ecf20Sopenharmony_ci } 8868c2ecf20Sopenharmony_ci } 8878c2ecf20Sopenharmony_ci return status; 8888c2ecf20Sopenharmony_ci} 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_cistatic int load_firmware(struct drxd_state *state, const char *fw_name) 8918c2ecf20Sopenharmony_ci{ 8928c2ecf20Sopenharmony_ci const struct firmware *fw; 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci if (request_firmware(&fw, fw_name, state->dev) < 0) { 8958c2ecf20Sopenharmony_ci printk(KERN_ERR "drxd: firmware load failure [%s]\n", fw_name); 8968c2ecf20Sopenharmony_ci return -EIO; 8978c2ecf20Sopenharmony_ci } 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci state->microcode = kmemdup(fw->data, fw->size, GFP_KERNEL); 9008c2ecf20Sopenharmony_ci if (!state->microcode) { 9018c2ecf20Sopenharmony_ci release_firmware(fw); 9028c2ecf20Sopenharmony_ci return -ENOMEM; 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci state->microcode_length = fw->size; 9068c2ecf20Sopenharmony_ci release_firmware(fw); 9078c2ecf20Sopenharmony_ci return 0; 9088c2ecf20Sopenharmony_ci} 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_cistatic int DownloadMicrocode(struct drxd_state *state, 9118c2ecf20Sopenharmony_ci const u8 *pMCImage, u32 Length) 9128c2ecf20Sopenharmony_ci{ 9138c2ecf20Sopenharmony_ci u8 *pSrc; 9148c2ecf20Sopenharmony_ci u32 Address; 9158c2ecf20Sopenharmony_ci u16 nBlocks; 9168c2ecf20Sopenharmony_ci u16 BlockSize; 9178c2ecf20Sopenharmony_ci u32 offset = 0; 9188c2ecf20Sopenharmony_ci int i, status = 0; 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci pSrc = (u8 *) pMCImage; 9218c2ecf20Sopenharmony_ci /* We're not using Flags */ 9228c2ecf20Sopenharmony_ci /* Flags = (pSrc[0] << 8) | pSrc[1]; */ 9238c2ecf20Sopenharmony_ci pSrc += sizeof(u16); 9248c2ecf20Sopenharmony_ci offset += sizeof(u16); 9258c2ecf20Sopenharmony_ci nBlocks = (pSrc[0] << 8) | pSrc[1]; 9268c2ecf20Sopenharmony_ci pSrc += sizeof(u16); 9278c2ecf20Sopenharmony_ci offset += sizeof(u16); 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci for (i = 0; i < nBlocks; i++) { 9308c2ecf20Sopenharmony_ci Address = (pSrc[0] << 24) | (pSrc[1] << 16) | 9318c2ecf20Sopenharmony_ci (pSrc[2] << 8) | pSrc[3]; 9328c2ecf20Sopenharmony_ci pSrc += sizeof(u32); 9338c2ecf20Sopenharmony_ci offset += sizeof(u32); 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16); 9368c2ecf20Sopenharmony_ci pSrc += sizeof(u16); 9378c2ecf20Sopenharmony_ci offset += sizeof(u16); 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci /* We're not using Flags */ 9408c2ecf20Sopenharmony_ci /* u16 Flags = (pSrc[0] << 8) | pSrc[1]; */ 9418c2ecf20Sopenharmony_ci pSrc += sizeof(u16); 9428c2ecf20Sopenharmony_ci offset += sizeof(u16); 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci /* We're not using BlockCRC */ 9458c2ecf20Sopenharmony_ci /* u16 BlockCRC = (pSrc[0] << 8) | pSrc[1]; */ 9468c2ecf20Sopenharmony_ci pSrc += sizeof(u16); 9478c2ecf20Sopenharmony_ci offset += sizeof(u16); 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci status = WriteBlock(state, Address, BlockSize, 9508c2ecf20Sopenharmony_ci pSrc, DRX_I2C_CLEARCRC); 9518c2ecf20Sopenharmony_ci if (status < 0) 9528c2ecf20Sopenharmony_ci break; 9538c2ecf20Sopenharmony_ci pSrc += BlockSize; 9548c2ecf20Sopenharmony_ci offset += BlockSize; 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci return status; 9588c2ecf20Sopenharmony_ci} 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_cistatic int HI_Command(struct drxd_state *state, u16 cmd, u16 * pResult) 9618c2ecf20Sopenharmony_ci{ 9628c2ecf20Sopenharmony_ci u32 nrRetries = 0; 9638c2ecf20Sopenharmony_ci int status; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CMD__A, cmd, 0); 9668c2ecf20Sopenharmony_ci if (status < 0) 9678c2ecf20Sopenharmony_ci return status; 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci do { 9708c2ecf20Sopenharmony_ci nrRetries += 1; 9718c2ecf20Sopenharmony_ci if (nrRetries > DRXD_MAX_RETRIES) { 9728c2ecf20Sopenharmony_ci status = -1; 9738c2ecf20Sopenharmony_ci break; 9748c2ecf20Sopenharmony_ci } 9758c2ecf20Sopenharmony_ci status = Read16(state, HI_RA_RAM_SRV_CMD__A, NULL, 0); 9768c2ecf20Sopenharmony_ci } while (status != 0); 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci if (status >= 0) 9798c2ecf20Sopenharmony_ci status = Read16(state, HI_RA_RAM_SRV_RES__A, pResult, 0); 9808c2ecf20Sopenharmony_ci return status; 9818c2ecf20Sopenharmony_ci} 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_cistatic int HI_CfgCommand(struct drxd_state *state) 9848c2ecf20Sopenharmony_ci{ 9858c2ecf20Sopenharmony_ci int status = 0; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci mutex_lock(&state->mutex); 9888c2ecf20Sopenharmony_ci Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0); 9898c2ecf20Sopenharmony_ci Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, state->hi_cfg_timing_div, 0); 9908c2ecf20Sopenharmony_ci Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, state->hi_cfg_bridge_delay, 0); 9918c2ecf20Sopenharmony_ci Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, state->hi_cfg_wakeup_key, 0); 9928c2ecf20Sopenharmony_ci Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, state->hi_cfg_ctrl, 0); 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0); 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci if ((state->hi_cfg_ctrl & HI_RA_RAM_SRV_CFG_ACT_PWD_EXE) == 9978c2ecf20Sopenharmony_ci HI_RA_RAM_SRV_CFG_ACT_PWD_EXE) 9988c2ecf20Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CMD__A, 9998c2ecf20Sopenharmony_ci HI_RA_RAM_SRV_CMD_CONFIG, 0); 10008c2ecf20Sopenharmony_ci else 10018c2ecf20Sopenharmony_ci status = HI_Command(state, HI_RA_RAM_SRV_CMD_CONFIG, NULL); 10028c2ecf20Sopenharmony_ci mutex_unlock(&state->mutex); 10038c2ecf20Sopenharmony_ci return status; 10048c2ecf20Sopenharmony_ci} 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_cistatic int InitHI(struct drxd_state *state) 10078c2ecf20Sopenharmony_ci{ 10088c2ecf20Sopenharmony_ci state->hi_cfg_wakeup_key = (state->chip_adr); 10098c2ecf20Sopenharmony_ci /* port/bridge/power down ctrl */ 10108c2ecf20Sopenharmony_ci state->hi_cfg_ctrl = HI_RA_RAM_SRV_CFG_ACT_SLV0_ON; 10118c2ecf20Sopenharmony_ci return HI_CfgCommand(state); 10128c2ecf20Sopenharmony_ci} 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_cistatic int HI_ResetCommand(struct drxd_state *state) 10158c2ecf20Sopenharmony_ci{ 10168c2ecf20Sopenharmony_ci int status; 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci mutex_lock(&state->mutex); 10198c2ecf20Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_RST_KEY__A, 10208c2ecf20Sopenharmony_ci HI_RA_RAM_SRV_RST_KEY_ACT, 0); 10218c2ecf20Sopenharmony_ci if (status == 0) 10228c2ecf20Sopenharmony_ci status = HI_Command(state, HI_RA_RAM_SRV_CMD_RESET, NULL); 10238c2ecf20Sopenharmony_ci mutex_unlock(&state->mutex); 10248c2ecf20Sopenharmony_ci msleep(1); 10258c2ecf20Sopenharmony_ci return status; 10268c2ecf20Sopenharmony_ci} 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_cistatic int DRX_ConfigureI2CBridge(struct drxd_state *state, int bEnableBridge) 10298c2ecf20Sopenharmony_ci{ 10308c2ecf20Sopenharmony_ci state->hi_cfg_ctrl &= (~HI_RA_RAM_SRV_CFG_ACT_BRD__M); 10318c2ecf20Sopenharmony_ci if (bEnableBridge) 10328c2ecf20Sopenharmony_ci state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_ON; 10338c2ecf20Sopenharmony_ci else 10348c2ecf20Sopenharmony_ci state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_OFF; 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci return HI_CfgCommand(state); 10378c2ecf20Sopenharmony_ci} 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci#define HI_TR_WRITE 0x9 10408c2ecf20Sopenharmony_ci#define HI_TR_READ 0xA 10418c2ecf20Sopenharmony_ci#define HI_TR_READ_WRITE 0xB 10428c2ecf20Sopenharmony_ci#define HI_TR_BROADCAST 0x4 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci#if 0 10458c2ecf20Sopenharmony_cistatic int AtomicReadBlock(struct drxd_state *state, 10468c2ecf20Sopenharmony_ci u32 Addr, u16 DataSize, u8 *pData, u8 Flags) 10478c2ecf20Sopenharmony_ci{ 10488c2ecf20Sopenharmony_ci int status; 10498c2ecf20Sopenharmony_ci int i = 0; 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci /* Parameter check */ 10528c2ecf20Sopenharmony_ci if ((!pData) || ((DataSize & 1) != 0)) 10538c2ecf20Sopenharmony_ci return -1; 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci mutex_lock(&state->mutex); 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ci do { 10588c2ecf20Sopenharmony_ci /* Instruct HI to read n bytes */ 10598c2ecf20Sopenharmony_ci /* TODO use proper names forthese egisters */ 10608c2ecf20Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, (HI_TR_FUNC_ADDR & 0xFFFF), 0); 10618c2ecf20Sopenharmony_ci if (status < 0) 10628c2ecf20Sopenharmony_ci break; 10638c2ecf20Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, (u16) (Addr >> 16), 0); 10648c2ecf20Sopenharmony_ci if (status < 0) 10658c2ecf20Sopenharmony_ci break; 10668c2ecf20Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, (u16) (Addr & 0xFFFF), 0); 10678c2ecf20Sopenharmony_ci if (status < 0) 10688c2ecf20Sopenharmony_ci break; 10698c2ecf20Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, (u16) ((DataSize / 2) - 1), 0); 10708c2ecf20Sopenharmony_ci if (status < 0) 10718c2ecf20Sopenharmony_ci break; 10728c2ecf20Sopenharmony_ci status = Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, HI_TR_READ, 0); 10738c2ecf20Sopenharmony_ci if (status < 0) 10748c2ecf20Sopenharmony_ci break; 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci status = HI_Command(state, HI_RA_RAM_SRV_CMD_EXECUTE, 0); 10778c2ecf20Sopenharmony_ci if (status < 0) 10788c2ecf20Sopenharmony_ci break; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci } while (0); 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci if (status >= 0) { 10838c2ecf20Sopenharmony_ci for (i = 0; i < (DataSize / 2); i += 1) { 10848c2ecf20Sopenharmony_ci u16 word; 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci status = Read16(state, (HI_RA_RAM_USR_BEGIN__A + i), 10878c2ecf20Sopenharmony_ci &word, 0); 10888c2ecf20Sopenharmony_ci if (status < 0) 10898c2ecf20Sopenharmony_ci break; 10908c2ecf20Sopenharmony_ci pData[2 * i] = (u8) (word & 0xFF); 10918c2ecf20Sopenharmony_ci pData[(2 * i) + 1] = (u8) (word >> 8); 10928c2ecf20Sopenharmony_ci } 10938c2ecf20Sopenharmony_ci } 10948c2ecf20Sopenharmony_ci mutex_unlock(&state->mutex); 10958c2ecf20Sopenharmony_ci return status; 10968c2ecf20Sopenharmony_ci} 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_cistatic int AtomicReadReg32(struct drxd_state *state, 10998c2ecf20Sopenharmony_ci u32 Addr, u32 *pData, u8 Flags) 11008c2ecf20Sopenharmony_ci{ 11018c2ecf20Sopenharmony_ci u8 buf[sizeof(u32)]; 11028c2ecf20Sopenharmony_ci int status; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci if (!pData) 11058c2ecf20Sopenharmony_ci return -1; 11068c2ecf20Sopenharmony_ci status = AtomicReadBlock(state, Addr, sizeof(u32), buf, Flags); 11078c2ecf20Sopenharmony_ci *pData = (((u32) buf[0]) << 0) + 11088c2ecf20Sopenharmony_ci (((u32) buf[1]) << 8) + 11098c2ecf20Sopenharmony_ci (((u32) buf[2]) << 16) + (((u32) buf[3]) << 24); 11108c2ecf20Sopenharmony_ci return status; 11118c2ecf20Sopenharmony_ci} 11128c2ecf20Sopenharmony_ci#endif 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_cistatic int StopAllProcessors(struct drxd_state *state) 11158c2ecf20Sopenharmony_ci{ 11168c2ecf20Sopenharmony_ci return Write16(state, HI_COMM_EXEC__A, 11178c2ecf20Sopenharmony_ci SC_COMM_EXEC_CTL_STOP, DRX_I2C_BROADCAST); 11188c2ecf20Sopenharmony_ci} 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_cistatic int EnableAndResetMB(struct drxd_state *state) 11218c2ecf20Sopenharmony_ci{ 11228c2ecf20Sopenharmony_ci if (state->type_A) { 11238c2ecf20Sopenharmony_ci /* disable? monitor bus observe @ EC_OC */ 11248c2ecf20Sopenharmony_ci Write16(state, EC_OC_REG_OC_MON_SIO__A, 0x0000, 0x0000); 11258c2ecf20Sopenharmony_ci } 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci /* do inverse broadcast, followed by explicit write to HI */ 11288c2ecf20Sopenharmony_ci Write16(state, HI_COMM_MB__A, 0x0000, DRX_I2C_BROADCAST); 11298c2ecf20Sopenharmony_ci Write16(state, HI_COMM_MB__A, 0x0000, 0x0000); 11308c2ecf20Sopenharmony_ci return 0; 11318c2ecf20Sopenharmony_ci} 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_cistatic int InitCC(struct drxd_state *state) 11348c2ecf20Sopenharmony_ci{ 11358c2ecf20Sopenharmony_ci int status = 0; 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci if (state->osc_clock_freq == 0 || 11388c2ecf20Sopenharmony_ci state->osc_clock_freq > 20000 || 11398c2ecf20Sopenharmony_ci (state->osc_clock_freq % 4000) != 0) { 11408c2ecf20Sopenharmony_ci printk(KERN_ERR "invalid osc frequency %d\n", state->osc_clock_freq); 11418c2ecf20Sopenharmony_ci return -1; 11428c2ecf20Sopenharmony_ci } 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci status |= Write16(state, CC_REG_OSC_MODE__A, CC_REG_OSC_MODE_M20, 0); 11458c2ecf20Sopenharmony_ci status |= Write16(state, CC_REG_PLL_MODE__A, 11468c2ecf20Sopenharmony_ci CC_REG_PLL_MODE_BYPASS_PLL | 11478c2ecf20Sopenharmony_ci CC_REG_PLL_MODE_PUMP_CUR_12, 0); 11488c2ecf20Sopenharmony_ci status |= Write16(state, CC_REG_REF_DIVIDE__A, 11498c2ecf20Sopenharmony_ci state->osc_clock_freq / 4000, 0); 11508c2ecf20Sopenharmony_ci status |= Write16(state, CC_REG_PWD_MODE__A, CC_REG_PWD_MODE_DOWN_PLL, 11518c2ecf20Sopenharmony_ci 0); 11528c2ecf20Sopenharmony_ci status |= Write16(state, CC_REG_UPDATE__A, CC_REG_UPDATE_KEY, 0); 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci return status; 11558c2ecf20Sopenharmony_ci} 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_cistatic int ResetECOD(struct drxd_state *state) 11588c2ecf20Sopenharmony_ci{ 11598c2ecf20Sopenharmony_ci int status = 0; 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci if (state->type_A) 11628c2ecf20Sopenharmony_ci status = Write16(state, EC_OD_REG_SYNC__A, 0x0664, 0); 11638c2ecf20Sopenharmony_ci else 11648c2ecf20Sopenharmony_ci status = Write16(state, B_EC_OD_REG_SYNC__A, 0x0664, 0); 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci if (!(status < 0)) 11678c2ecf20Sopenharmony_ci status = WriteTable(state, state->m_ResetECRAM); 11688c2ecf20Sopenharmony_ci if (!(status < 0)) 11698c2ecf20Sopenharmony_ci status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0001, 0); 11708c2ecf20Sopenharmony_ci return status; 11718c2ecf20Sopenharmony_ci} 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci/* Configure PGA switch */ 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_cistatic int SetCfgPga(struct drxd_state *state, int pgaSwitch) 11768c2ecf20Sopenharmony_ci{ 11778c2ecf20Sopenharmony_ci int status; 11788c2ecf20Sopenharmony_ci u16 AgModeLop = 0; 11798c2ecf20Sopenharmony_ci u16 AgModeHip = 0; 11808c2ecf20Sopenharmony_ci do { 11818c2ecf20Sopenharmony_ci if (pgaSwitch) { 11828c2ecf20Sopenharmony_ci /* PGA on */ 11838c2ecf20Sopenharmony_ci /* fine gain */ 11848c2ecf20Sopenharmony_ci status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); 11858c2ecf20Sopenharmony_ci if (status < 0) 11868c2ecf20Sopenharmony_ci break; 11878c2ecf20Sopenharmony_ci AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M)); 11888c2ecf20Sopenharmony_ci AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC; 11898c2ecf20Sopenharmony_ci status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); 11908c2ecf20Sopenharmony_ci if (status < 0) 11918c2ecf20Sopenharmony_ci break; 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci /* coarse gain */ 11948c2ecf20Sopenharmony_ci status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000); 11958c2ecf20Sopenharmony_ci if (status < 0) 11968c2ecf20Sopenharmony_ci break; 11978c2ecf20Sopenharmony_ci AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M)); 11988c2ecf20Sopenharmony_ci AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_DYNAMIC; 11998c2ecf20Sopenharmony_ci status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000); 12008c2ecf20Sopenharmony_ci if (status < 0) 12018c2ecf20Sopenharmony_ci break; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci /* enable fine and coarse gain, enable AAF, 12048c2ecf20Sopenharmony_ci no ext resistor */ 12058c2ecf20Sopenharmony_ci status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN, 0x0000); 12068c2ecf20Sopenharmony_ci if (status < 0) 12078c2ecf20Sopenharmony_ci break; 12088c2ecf20Sopenharmony_ci } else { 12098c2ecf20Sopenharmony_ci /* PGA off, bypass */ 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci /* fine gain */ 12128c2ecf20Sopenharmony_ci status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); 12138c2ecf20Sopenharmony_ci if (status < 0) 12148c2ecf20Sopenharmony_ci break; 12158c2ecf20Sopenharmony_ci AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M)); 12168c2ecf20Sopenharmony_ci AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC; 12178c2ecf20Sopenharmony_ci status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); 12188c2ecf20Sopenharmony_ci if (status < 0) 12198c2ecf20Sopenharmony_ci break; 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci /* coarse gain */ 12228c2ecf20Sopenharmony_ci status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000); 12238c2ecf20Sopenharmony_ci if (status < 0) 12248c2ecf20Sopenharmony_ci break; 12258c2ecf20Sopenharmony_ci AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M)); 12268c2ecf20Sopenharmony_ci AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_STATIC; 12278c2ecf20Sopenharmony_ci status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000); 12288c2ecf20Sopenharmony_ci if (status < 0) 12298c2ecf20Sopenharmony_ci break; 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci /* disable fine and coarse gain, enable AAF, 12328c2ecf20Sopenharmony_ci no ext resistor */ 12338c2ecf20Sopenharmony_ci status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 0x0000); 12348c2ecf20Sopenharmony_ci if (status < 0) 12358c2ecf20Sopenharmony_ci break; 12368c2ecf20Sopenharmony_ci } 12378c2ecf20Sopenharmony_ci } while (0); 12388c2ecf20Sopenharmony_ci return status; 12398c2ecf20Sopenharmony_ci} 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_cistatic int InitFE(struct drxd_state *state) 12428c2ecf20Sopenharmony_ci{ 12438c2ecf20Sopenharmony_ci int status; 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci do { 12468c2ecf20Sopenharmony_ci status = WriteTable(state, state->m_InitFE_1); 12478c2ecf20Sopenharmony_ci if (status < 0) 12488c2ecf20Sopenharmony_ci break; 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci if (state->type_A) { 12518c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_PGA_MODE__A, 12528c2ecf20Sopenharmony_ci FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 12538c2ecf20Sopenharmony_ci 0); 12548c2ecf20Sopenharmony_ci } else { 12558c2ecf20Sopenharmony_ci if (state->PGA) 12568c2ecf20Sopenharmony_ci status = SetCfgPga(state, 0); 12578c2ecf20Sopenharmony_ci else 12588c2ecf20Sopenharmony_ci status = 12598c2ecf20Sopenharmony_ci Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, 12608c2ecf20Sopenharmony_ci B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 12618c2ecf20Sopenharmony_ci 0); 12628c2ecf20Sopenharmony_ci } 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci if (status < 0) 12658c2ecf20Sopenharmony_ci break; 12668c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, state->m_FeAgRegAgAgcSio, 0x0000); 12678c2ecf20Sopenharmony_ci if (status < 0) 12688c2ecf20Sopenharmony_ci break; 12698c2ecf20Sopenharmony_ci status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000); 12708c2ecf20Sopenharmony_ci if (status < 0) 12718c2ecf20Sopenharmony_ci break; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci status = WriteTable(state, state->m_InitFE_2); 12748c2ecf20Sopenharmony_ci if (status < 0) 12758c2ecf20Sopenharmony_ci break; 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci } while (0); 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci return status; 12808c2ecf20Sopenharmony_ci} 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_cistatic int InitFT(struct drxd_state *state) 12838c2ecf20Sopenharmony_ci{ 12848c2ecf20Sopenharmony_ci /* 12858c2ecf20Sopenharmony_ci norm OFFSET, MB says =2 voor 8K en =3 voor 2K waarschijnlijk 12868c2ecf20Sopenharmony_ci SC stuff 12878c2ecf20Sopenharmony_ci */ 12888c2ecf20Sopenharmony_ci return Write16(state, FT_REG_COMM_EXEC__A, 0x0001, 0x0000); 12898c2ecf20Sopenharmony_ci} 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_cistatic int SC_WaitForReady(struct drxd_state *state) 12928c2ecf20Sopenharmony_ci{ 12938c2ecf20Sopenharmony_ci int i; 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci for (i = 0; i < DRXD_MAX_RETRIES; i += 1) { 12968c2ecf20Sopenharmony_ci int status = Read16(state, SC_RA_RAM_CMD__A, NULL, 0); 12978c2ecf20Sopenharmony_ci if (status == 0) 12988c2ecf20Sopenharmony_ci return status; 12998c2ecf20Sopenharmony_ci } 13008c2ecf20Sopenharmony_ci return -1; 13018c2ecf20Sopenharmony_ci} 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_cistatic int SC_SendCommand(struct drxd_state *state, u16 cmd) 13048c2ecf20Sopenharmony_ci{ 13058c2ecf20Sopenharmony_ci int status = 0, ret; 13068c2ecf20Sopenharmony_ci u16 errCode; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci status = Write16(state, SC_RA_RAM_CMD__A, cmd, 0); 13098c2ecf20Sopenharmony_ci if (status < 0) 13108c2ecf20Sopenharmony_ci return status; 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci SC_WaitForReady(state); 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci ret = Read16(state, SC_RA_RAM_CMD_ADDR__A, &errCode, 0); 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci if (ret < 0 || errCode == 0xFFFF) { 13178c2ecf20Sopenharmony_ci printk(KERN_ERR "Command Error\n"); 13188c2ecf20Sopenharmony_ci status = -1; 13198c2ecf20Sopenharmony_ci } 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci return status; 13228c2ecf20Sopenharmony_ci} 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_cistatic int SC_ProcStartCommand(struct drxd_state *state, 13258c2ecf20Sopenharmony_ci u16 subCmd, u16 param0, u16 param1) 13268c2ecf20Sopenharmony_ci{ 13278c2ecf20Sopenharmony_ci int ret, status = 0; 13288c2ecf20Sopenharmony_ci u16 scExec; 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci mutex_lock(&state->mutex); 13318c2ecf20Sopenharmony_ci do { 13328c2ecf20Sopenharmony_ci ret = Read16(state, SC_COMM_EXEC__A, &scExec, 0); 13338c2ecf20Sopenharmony_ci if (ret < 0 || scExec != 1) { 13348c2ecf20Sopenharmony_ci status = -1; 13358c2ecf20Sopenharmony_ci break; 13368c2ecf20Sopenharmony_ci } 13378c2ecf20Sopenharmony_ci SC_WaitForReady(state); 13388c2ecf20Sopenharmony_ci status |= Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0); 13398c2ecf20Sopenharmony_ci status |= Write16(state, SC_RA_RAM_PARAM1__A, param1, 0); 13408c2ecf20Sopenharmony_ci status |= Write16(state, SC_RA_RAM_PARAM0__A, param0, 0); 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci SC_SendCommand(state, SC_RA_RAM_CMD_PROC_START); 13438c2ecf20Sopenharmony_ci } while (0); 13448c2ecf20Sopenharmony_ci mutex_unlock(&state->mutex); 13458c2ecf20Sopenharmony_ci return status; 13468c2ecf20Sopenharmony_ci} 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_cistatic int SC_SetPrefParamCommand(struct drxd_state *state, 13498c2ecf20Sopenharmony_ci u16 subCmd, u16 param0, u16 param1) 13508c2ecf20Sopenharmony_ci{ 13518c2ecf20Sopenharmony_ci int status; 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci mutex_lock(&state->mutex); 13548c2ecf20Sopenharmony_ci do { 13558c2ecf20Sopenharmony_ci status = SC_WaitForReady(state); 13568c2ecf20Sopenharmony_ci if (status < 0) 13578c2ecf20Sopenharmony_ci break; 13588c2ecf20Sopenharmony_ci status = Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0); 13598c2ecf20Sopenharmony_ci if (status < 0) 13608c2ecf20Sopenharmony_ci break; 13618c2ecf20Sopenharmony_ci status = Write16(state, SC_RA_RAM_PARAM1__A, param1, 0); 13628c2ecf20Sopenharmony_ci if (status < 0) 13638c2ecf20Sopenharmony_ci break; 13648c2ecf20Sopenharmony_ci status = Write16(state, SC_RA_RAM_PARAM0__A, param0, 0); 13658c2ecf20Sopenharmony_ci if (status < 0) 13668c2ecf20Sopenharmony_ci break; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci status = SC_SendCommand(state, SC_RA_RAM_CMD_SET_PREF_PARAM); 13698c2ecf20Sopenharmony_ci if (status < 0) 13708c2ecf20Sopenharmony_ci break; 13718c2ecf20Sopenharmony_ci } while (0); 13728c2ecf20Sopenharmony_ci mutex_unlock(&state->mutex); 13738c2ecf20Sopenharmony_ci return status; 13748c2ecf20Sopenharmony_ci} 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci#if 0 13778c2ecf20Sopenharmony_cistatic int SC_GetOpParamCommand(struct drxd_state *state, u16 * result) 13788c2ecf20Sopenharmony_ci{ 13798c2ecf20Sopenharmony_ci int status = 0; 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci mutex_lock(&state->mutex); 13828c2ecf20Sopenharmony_ci do { 13838c2ecf20Sopenharmony_ci status = SC_WaitForReady(state); 13848c2ecf20Sopenharmony_ci if (status < 0) 13858c2ecf20Sopenharmony_ci break; 13868c2ecf20Sopenharmony_ci status = SC_SendCommand(state, SC_RA_RAM_CMD_GET_OP_PARAM); 13878c2ecf20Sopenharmony_ci if (status < 0) 13888c2ecf20Sopenharmony_ci break; 13898c2ecf20Sopenharmony_ci status = Read16(state, SC_RA_RAM_PARAM0__A, result, 0); 13908c2ecf20Sopenharmony_ci if (status < 0) 13918c2ecf20Sopenharmony_ci break; 13928c2ecf20Sopenharmony_ci } while (0); 13938c2ecf20Sopenharmony_ci mutex_unlock(&state->mutex); 13948c2ecf20Sopenharmony_ci return status; 13958c2ecf20Sopenharmony_ci} 13968c2ecf20Sopenharmony_ci#endif 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_cistatic int ConfigureMPEGOutput(struct drxd_state *state, int bEnableOutput) 13998c2ecf20Sopenharmony_ci{ 14008c2ecf20Sopenharmony_ci int status; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci do { 14038c2ecf20Sopenharmony_ci u16 EcOcRegIprInvMpg = 0; 14048c2ecf20Sopenharmony_ci u16 EcOcRegOcModeLop = 0; 14058c2ecf20Sopenharmony_ci u16 EcOcRegOcModeHip = 0; 14068c2ecf20Sopenharmony_ci u16 EcOcRegOcMpgSio = 0; 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci /*CHK_ERROR(Read16(state, EC_OC_REG_OC_MODE_LOP__A, &EcOcRegOcModeLop, 0)); */ 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci if (state->operation_mode == OM_DVBT_Diversity_Front) { 14118c2ecf20Sopenharmony_ci if (bEnableOutput) { 14128c2ecf20Sopenharmony_ci EcOcRegOcModeHip |= 14138c2ecf20Sopenharmony_ci B_EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR; 14148c2ecf20Sopenharmony_ci } else 14158c2ecf20Sopenharmony_ci EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M; 14168c2ecf20Sopenharmony_ci EcOcRegOcModeLop |= 14178c2ecf20Sopenharmony_ci EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE; 14188c2ecf20Sopenharmony_ci } else { 14198c2ecf20Sopenharmony_ci EcOcRegOcModeLop = state->m_EcOcRegOcModeLop; 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci if (bEnableOutput) 14228c2ecf20Sopenharmony_ci EcOcRegOcMpgSio &= (~(EC_OC_REG_OC_MPG_SIO__M)); 14238c2ecf20Sopenharmony_ci else 14248c2ecf20Sopenharmony_ci EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M; 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci /* Don't Insert RS Byte */ 14278c2ecf20Sopenharmony_ci if (state->insert_rs_byte) { 14288c2ecf20Sopenharmony_ci EcOcRegOcModeLop &= 14298c2ecf20Sopenharmony_ci (~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M)); 14308c2ecf20Sopenharmony_ci EcOcRegOcModeHip &= 14318c2ecf20Sopenharmony_ci (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M); 14328c2ecf20Sopenharmony_ci EcOcRegOcModeHip |= 14338c2ecf20Sopenharmony_ci EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE; 14348c2ecf20Sopenharmony_ci } else { 14358c2ecf20Sopenharmony_ci EcOcRegOcModeLop |= 14368c2ecf20Sopenharmony_ci EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE; 14378c2ecf20Sopenharmony_ci EcOcRegOcModeHip &= 14388c2ecf20Sopenharmony_ci (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M); 14398c2ecf20Sopenharmony_ci EcOcRegOcModeHip |= 14408c2ecf20Sopenharmony_ci EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE; 14418c2ecf20Sopenharmony_ci } 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci /* Mode = Parallel */ 14448c2ecf20Sopenharmony_ci if (state->enable_parallel) 14458c2ecf20Sopenharmony_ci EcOcRegOcModeLop &= 14468c2ecf20Sopenharmony_ci (~(EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M)); 14478c2ecf20Sopenharmony_ci else 14488c2ecf20Sopenharmony_ci EcOcRegOcModeLop |= 14498c2ecf20Sopenharmony_ci EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL; 14508c2ecf20Sopenharmony_ci } 14518c2ecf20Sopenharmony_ci /* Invert Data */ 14528c2ecf20Sopenharmony_ci /* EcOcRegIprInvMpg |= 0x00FF; */ 14538c2ecf20Sopenharmony_ci EcOcRegIprInvMpg &= (~(0x00FF)); 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci /* Invert Error ( we don't use the pin ) */ 14568c2ecf20Sopenharmony_ci /* EcOcRegIprInvMpg |= 0x0100; */ 14578c2ecf20Sopenharmony_ci EcOcRegIprInvMpg &= (~(0x0100)); 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci /* Invert Start ( we don't use the pin ) */ 14608c2ecf20Sopenharmony_ci /* EcOcRegIprInvMpg |= 0x0200; */ 14618c2ecf20Sopenharmony_ci EcOcRegIprInvMpg &= (~(0x0200)); 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci /* Invert Valid ( we don't use the pin ) */ 14648c2ecf20Sopenharmony_ci /* EcOcRegIprInvMpg |= 0x0400; */ 14658c2ecf20Sopenharmony_ci EcOcRegIprInvMpg &= (~(0x0400)); 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci /* Invert Clock */ 14688c2ecf20Sopenharmony_ci /* EcOcRegIprInvMpg |= 0x0800; */ 14698c2ecf20Sopenharmony_ci EcOcRegIprInvMpg &= (~(0x0800)); 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci /* EcOcRegOcModeLop =0x05; */ 14728c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_IPR_INV_MPG__A, EcOcRegIprInvMpg, 0); 14738c2ecf20Sopenharmony_ci if (status < 0) 14748c2ecf20Sopenharmony_ci break; 14758c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, EcOcRegOcModeLop, 0); 14768c2ecf20Sopenharmony_ci if (status < 0) 14778c2ecf20Sopenharmony_ci break; 14788c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_OC_MODE_HIP__A, EcOcRegOcModeHip, 0x0000); 14798c2ecf20Sopenharmony_ci if (status < 0) 14808c2ecf20Sopenharmony_ci break; 14818c2ecf20Sopenharmony_ci status = Write16(state, EC_OC_REG_OC_MPG_SIO__A, EcOcRegOcMpgSio, 0); 14828c2ecf20Sopenharmony_ci if (status < 0) 14838c2ecf20Sopenharmony_ci break; 14848c2ecf20Sopenharmony_ci } while (0); 14858c2ecf20Sopenharmony_ci return status; 14868c2ecf20Sopenharmony_ci} 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_cistatic int SetDeviceTypeId(struct drxd_state *state) 14898c2ecf20Sopenharmony_ci{ 14908c2ecf20Sopenharmony_ci int status = 0; 14918c2ecf20Sopenharmony_ci u16 deviceId = 0; 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci do { 14948c2ecf20Sopenharmony_ci status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0); 14958c2ecf20Sopenharmony_ci if (status < 0) 14968c2ecf20Sopenharmony_ci break; 14978c2ecf20Sopenharmony_ci /* TODO: why twice? */ 14988c2ecf20Sopenharmony_ci status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0); 14998c2ecf20Sopenharmony_ci if (status < 0) 15008c2ecf20Sopenharmony_ci break; 15018c2ecf20Sopenharmony_ci printk(KERN_INFO "drxd: deviceId = %04x\n", deviceId); 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci state->type_A = 0; 15048c2ecf20Sopenharmony_ci state->PGA = 0; 15058c2ecf20Sopenharmony_ci state->diversity = 0; 15068c2ecf20Sopenharmony_ci if (deviceId == 0) { /* on A2 only 3975 available */ 15078c2ecf20Sopenharmony_ci state->type_A = 1; 15088c2ecf20Sopenharmony_ci printk(KERN_INFO "DRX3975D-A2\n"); 15098c2ecf20Sopenharmony_ci } else { 15108c2ecf20Sopenharmony_ci deviceId >>= 12; 15118c2ecf20Sopenharmony_ci printk(KERN_INFO "DRX397%dD-B1\n", deviceId); 15128c2ecf20Sopenharmony_ci switch (deviceId) { 15138c2ecf20Sopenharmony_ci case 4: 15148c2ecf20Sopenharmony_ci state->diversity = 1; 15158c2ecf20Sopenharmony_ci fallthrough; 15168c2ecf20Sopenharmony_ci case 3: 15178c2ecf20Sopenharmony_ci case 7: 15188c2ecf20Sopenharmony_ci state->PGA = 1; 15198c2ecf20Sopenharmony_ci break; 15208c2ecf20Sopenharmony_ci case 6: 15218c2ecf20Sopenharmony_ci state->diversity = 1; 15228c2ecf20Sopenharmony_ci fallthrough; 15238c2ecf20Sopenharmony_ci case 5: 15248c2ecf20Sopenharmony_ci case 8: 15258c2ecf20Sopenharmony_ci break; 15268c2ecf20Sopenharmony_ci default: 15278c2ecf20Sopenharmony_ci status = -1; 15288c2ecf20Sopenharmony_ci break; 15298c2ecf20Sopenharmony_ci } 15308c2ecf20Sopenharmony_ci } 15318c2ecf20Sopenharmony_ci } while (0); 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci if (status < 0) 15348c2ecf20Sopenharmony_ci return status; 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci /* Init Table selection */ 15378c2ecf20Sopenharmony_ci state->m_InitAtomicRead = DRXD_InitAtomicRead; 15388c2ecf20Sopenharmony_ci state->m_InitSC = DRXD_InitSC; 15398c2ecf20Sopenharmony_ci state->m_ResetECRAM = DRXD_ResetECRAM; 15408c2ecf20Sopenharmony_ci if (state->type_A) { 15418c2ecf20Sopenharmony_ci state->m_ResetCEFR = DRXD_ResetCEFR; 15428c2ecf20Sopenharmony_ci state->m_InitFE_1 = DRXD_InitFEA2_1; 15438c2ecf20Sopenharmony_ci state->m_InitFE_2 = DRXD_InitFEA2_2; 15448c2ecf20Sopenharmony_ci state->m_InitCP = DRXD_InitCPA2; 15458c2ecf20Sopenharmony_ci state->m_InitCE = DRXD_InitCEA2; 15468c2ecf20Sopenharmony_ci state->m_InitEQ = DRXD_InitEQA2; 15478c2ecf20Sopenharmony_ci state->m_InitEC = DRXD_InitECA2; 15488c2ecf20Sopenharmony_ci if (load_firmware(state, DRX_FW_FILENAME_A2)) 15498c2ecf20Sopenharmony_ci return -EIO; 15508c2ecf20Sopenharmony_ci } else { 15518c2ecf20Sopenharmony_ci state->m_ResetCEFR = NULL; 15528c2ecf20Sopenharmony_ci state->m_InitFE_1 = DRXD_InitFEB1_1; 15538c2ecf20Sopenharmony_ci state->m_InitFE_2 = DRXD_InitFEB1_2; 15548c2ecf20Sopenharmony_ci state->m_InitCP = DRXD_InitCPB1; 15558c2ecf20Sopenharmony_ci state->m_InitCE = DRXD_InitCEB1; 15568c2ecf20Sopenharmony_ci state->m_InitEQ = DRXD_InitEQB1; 15578c2ecf20Sopenharmony_ci state->m_InitEC = DRXD_InitECB1; 15588c2ecf20Sopenharmony_ci if (load_firmware(state, DRX_FW_FILENAME_B1)) 15598c2ecf20Sopenharmony_ci return -EIO; 15608c2ecf20Sopenharmony_ci } 15618c2ecf20Sopenharmony_ci if (state->diversity) { 15628c2ecf20Sopenharmony_ci state->m_InitDiversityFront = DRXD_InitDiversityFront; 15638c2ecf20Sopenharmony_ci state->m_InitDiversityEnd = DRXD_InitDiversityEnd; 15648c2ecf20Sopenharmony_ci state->m_DisableDiversity = DRXD_DisableDiversity; 15658c2ecf20Sopenharmony_ci state->m_StartDiversityFront = DRXD_StartDiversityFront; 15668c2ecf20Sopenharmony_ci state->m_StartDiversityEnd = DRXD_StartDiversityEnd; 15678c2ecf20Sopenharmony_ci state->m_DiversityDelay8MHZ = DRXD_DiversityDelay8MHZ; 15688c2ecf20Sopenharmony_ci state->m_DiversityDelay6MHZ = DRXD_DiversityDelay6MHZ; 15698c2ecf20Sopenharmony_ci } else { 15708c2ecf20Sopenharmony_ci state->m_InitDiversityFront = NULL; 15718c2ecf20Sopenharmony_ci state->m_InitDiversityEnd = NULL; 15728c2ecf20Sopenharmony_ci state->m_DisableDiversity = NULL; 15738c2ecf20Sopenharmony_ci state->m_StartDiversityFront = NULL; 15748c2ecf20Sopenharmony_ci state->m_StartDiversityEnd = NULL; 15758c2ecf20Sopenharmony_ci state->m_DiversityDelay8MHZ = NULL; 15768c2ecf20Sopenharmony_ci state->m_DiversityDelay6MHZ = NULL; 15778c2ecf20Sopenharmony_ci } 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci return status; 15808c2ecf20Sopenharmony_ci} 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_cistatic int CorrectSysClockDeviation(struct drxd_state *state) 15838c2ecf20Sopenharmony_ci{ 15848c2ecf20Sopenharmony_ci int status; 15858c2ecf20Sopenharmony_ci s32 incr = 0; 15868c2ecf20Sopenharmony_ci s32 nomincr = 0; 15878c2ecf20Sopenharmony_ci u32 bandwidth = 0; 15888c2ecf20Sopenharmony_ci u32 sysClockInHz = 0; 15898c2ecf20Sopenharmony_ci u32 sysClockFreq = 0; /* in kHz */ 15908c2ecf20Sopenharmony_ci s16 oscClockDeviation; 15918c2ecf20Sopenharmony_ci s16 Diff; 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci do { 15948c2ecf20Sopenharmony_ci /* Retrieve bandwidth and incr, sanity check */ 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci /* These accesses should be AtomicReadReg32, but that 15978c2ecf20Sopenharmony_ci causes trouble (at least for diversity */ 15988c2ecf20Sopenharmony_ci status = Read32(state, LC_RA_RAM_IFINCR_NOM_L__A, ((u32 *) &nomincr), 0); 15998c2ecf20Sopenharmony_ci if (status < 0) 16008c2ecf20Sopenharmony_ci break; 16018c2ecf20Sopenharmony_ci status = Read32(state, FE_IF_REG_INCR0__A, (u32 *) &incr, 0); 16028c2ecf20Sopenharmony_ci if (status < 0) 16038c2ecf20Sopenharmony_ci break; 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci if (state->type_A) { 16068c2ecf20Sopenharmony_ci if ((nomincr - incr < -500) || (nomincr - incr > 500)) 16078c2ecf20Sopenharmony_ci break; 16088c2ecf20Sopenharmony_ci } else { 16098c2ecf20Sopenharmony_ci if ((nomincr - incr < -2000) || (nomincr - incr > 2000)) 16108c2ecf20Sopenharmony_ci break; 16118c2ecf20Sopenharmony_ci } 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_ci switch (state->props.bandwidth_hz) { 16148c2ecf20Sopenharmony_ci case 8000000: 16158c2ecf20Sopenharmony_ci bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ; 16168c2ecf20Sopenharmony_ci break; 16178c2ecf20Sopenharmony_ci case 7000000: 16188c2ecf20Sopenharmony_ci bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ; 16198c2ecf20Sopenharmony_ci break; 16208c2ecf20Sopenharmony_ci case 6000000: 16218c2ecf20Sopenharmony_ci bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ; 16228c2ecf20Sopenharmony_ci break; 16238c2ecf20Sopenharmony_ci default: 16248c2ecf20Sopenharmony_ci return -1; 16258c2ecf20Sopenharmony_ci break; 16268c2ecf20Sopenharmony_ci } 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci /* Compute new sysclock value 16298c2ecf20Sopenharmony_ci sysClockFreq = (((incr + 2^23)*bandwidth)/2^21)/1000 */ 16308c2ecf20Sopenharmony_ci incr += (1 << 23); 16318c2ecf20Sopenharmony_ci sysClockInHz = MulDiv32(incr, bandwidth, 1 << 21); 16328c2ecf20Sopenharmony_ci sysClockFreq = (u32) (sysClockInHz / 1000); 16338c2ecf20Sopenharmony_ci /* rounding */ 16348c2ecf20Sopenharmony_ci if ((sysClockInHz % 1000) > 500) 16358c2ecf20Sopenharmony_ci sysClockFreq++; 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_ci /* Compute clock deviation in ppm */ 16388c2ecf20Sopenharmony_ci oscClockDeviation = (u16) ((((s32) (sysClockFreq) - 16398c2ecf20Sopenharmony_ci (s32) 16408c2ecf20Sopenharmony_ci (state->expected_sys_clock_freq)) * 16418c2ecf20Sopenharmony_ci 1000000L) / 16428c2ecf20Sopenharmony_ci (s32) 16438c2ecf20Sopenharmony_ci (state->expected_sys_clock_freq)); 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci Diff = oscClockDeviation - state->osc_clock_deviation; 16468c2ecf20Sopenharmony_ci /*printk(KERN_INFO "sysclockdiff=%d\n", Diff); */ 16478c2ecf20Sopenharmony_ci if (Diff >= -200 && Diff <= 200) { 16488c2ecf20Sopenharmony_ci state->sys_clock_freq = (u16) sysClockFreq; 16498c2ecf20Sopenharmony_ci if (oscClockDeviation != state->osc_clock_deviation) { 16508c2ecf20Sopenharmony_ci if (state->config.osc_deviation) { 16518c2ecf20Sopenharmony_ci state->config.osc_deviation(state->priv, 16528c2ecf20Sopenharmony_ci oscClockDeviation, 16538c2ecf20Sopenharmony_ci 1); 16548c2ecf20Sopenharmony_ci state->osc_clock_deviation = 16558c2ecf20Sopenharmony_ci oscClockDeviation; 16568c2ecf20Sopenharmony_ci } 16578c2ecf20Sopenharmony_ci } 16588c2ecf20Sopenharmony_ci /* switch OFF SRMM scan in SC */ 16598c2ecf20Sopenharmony_ci status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DONT_SCAN, 0); 16608c2ecf20Sopenharmony_ci if (status < 0) 16618c2ecf20Sopenharmony_ci break; 16628c2ecf20Sopenharmony_ci /* overrule FE_IF internal value for 16638c2ecf20Sopenharmony_ci proper re-locking */ 16648c2ecf20Sopenharmony_ci status = Write16(state, SC_RA_RAM_IF_SAVE__AX, state->current_fe_if_incr, 0); 16658c2ecf20Sopenharmony_ci if (status < 0) 16668c2ecf20Sopenharmony_ci break; 16678c2ecf20Sopenharmony_ci state->cscd_state = CSCD_SAVED; 16688c2ecf20Sopenharmony_ci } 16698c2ecf20Sopenharmony_ci } while (0); 16708c2ecf20Sopenharmony_ci 16718c2ecf20Sopenharmony_ci return status; 16728c2ecf20Sopenharmony_ci} 16738c2ecf20Sopenharmony_ci 16748c2ecf20Sopenharmony_cistatic int DRX_Stop(struct drxd_state *state) 16758c2ecf20Sopenharmony_ci{ 16768c2ecf20Sopenharmony_ci int status; 16778c2ecf20Sopenharmony_ci 16788c2ecf20Sopenharmony_ci if (state->drxd_state != DRXD_STARTED) 16798c2ecf20Sopenharmony_ci return 0; 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci do { 16828c2ecf20Sopenharmony_ci if (state->cscd_state != CSCD_SAVED) { 16838c2ecf20Sopenharmony_ci u32 lock; 16848c2ecf20Sopenharmony_ci status = DRX_GetLockStatus(state, &lock); 16858c2ecf20Sopenharmony_ci if (status < 0) 16868c2ecf20Sopenharmony_ci break; 16878c2ecf20Sopenharmony_ci } 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci status = StopOC(state); 16908c2ecf20Sopenharmony_ci if (status < 0) 16918c2ecf20Sopenharmony_ci break; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci state->drxd_state = DRXD_STOPPED; 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_ci status = ConfigureMPEGOutput(state, 0); 16968c2ecf20Sopenharmony_ci if (status < 0) 16978c2ecf20Sopenharmony_ci break; 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci if (state->type_A) { 17008c2ecf20Sopenharmony_ci /* Stop relevant processors off the device */ 17018c2ecf20Sopenharmony_ci status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0x0000); 17028c2ecf20Sopenharmony_ci if (status < 0) 17038c2ecf20Sopenharmony_ci break; 17048c2ecf20Sopenharmony_ci 17058c2ecf20Sopenharmony_ci status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 17068c2ecf20Sopenharmony_ci if (status < 0) 17078c2ecf20Sopenharmony_ci break; 17088c2ecf20Sopenharmony_ci status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 17098c2ecf20Sopenharmony_ci if (status < 0) 17108c2ecf20Sopenharmony_ci break; 17118c2ecf20Sopenharmony_ci } else { 17128c2ecf20Sopenharmony_ci /* Stop all processors except HI & CC & FE */ 17138c2ecf20Sopenharmony_ci status = Write16(state, B_SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 17148c2ecf20Sopenharmony_ci if (status < 0) 17158c2ecf20Sopenharmony_ci break; 17168c2ecf20Sopenharmony_ci status = Write16(state, B_LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 17178c2ecf20Sopenharmony_ci if (status < 0) 17188c2ecf20Sopenharmony_ci break; 17198c2ecf20Sopenharmony_ci status = Write16(state, B_FT_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 17208c2ecf20Sopenharmony_ci if (status < 0) 17218c2ecf20Sopenharmony_ci break; 17228c2ecf20Sopenharmony_ci status = Write16(state, B_CP_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 17238c2ecf20Sopenharmony_ci if (status < 0) 17248c2ecf20Sopenharmony_ci break; 17258c2ecf20Sopenharmony_ci status = Write16(state, B_CE_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 17268c2ecf20Sopenharmony_ci if (status < 0) 17278c2ecf20Sopenharmony_ci break; 17288c2ecf20Sopenharmony_ci status = Write16(state, B_EQ_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 17298c2ecf20Sopenharmony_ci if (status < 0) 17308c2ecf20Sopenharmony_ci break; 17318c2ecf20Sopenharmony_ci status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0); 17328c2ecf20Sopenharmony_ci if (status < 0) 17338c2ecf20Sopenharmony_ci break; 17348c2ecf20Sopenharmony_ci } 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_ci } while (0); 17378c2ecf20Sopenharmony_ci return status; 17388c2ecf20Sopenharmony_ci} 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci#if 0 /* Currently unused */ 17418c2ecf20Sopenharmony_cistatic int SetOperationMode(struct drxd_state *state, int oMode) 17428c2ecf20Sopenharmony_ci{ 17438c2ecf20Sopenharmony_ci int status; 17448c2ecf20Sopenharmony_ci 17458c2ecf20Sopenharmony_ci do { 17468c2ecf20Sopenharmony_ci if (state->drxd_state != DRXD_STOPPED) { 17478c2ecf20Sopenharmony_ci status = -1; 17488c2ecf20Sopenharmony_ci break; 17498c2ecf20Sopenharmony_ci } 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci if (oMode == state->operation_mode) { 17528c2ecf20Sopenharmony_ci status = 0; 17538c2ecf20Sopenharmony_ci break; 17548c2ecf20Sopenharmony_ci } 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci if (oMode != OM_Default && !state->diversity) { 17578c2ecf20Sopenharmony_ci status = -1; 17588c2ecf20Sopenharmony_ci break; 17598c2ecf20Sopenharmony_ci } 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci switch (oMode) { 17628c2ecf20Sopenharmony_ci case OM_DVBT_Diversity_Front: 17638c2ecf20Sopenharmony_ci status = WriteTable(state, state->m_InitDiversityFront); 17648c2ecf20Sopenharmony_ci break; 17658c2ecf20Sopenharmony_ci case OM_DVBT_Diversity_End: 17668c2ecf20Sopenharmony_ci status = WriteTable(state, state->m_InitDiversityEnd); 17678c2ecf20Sopenharmony_ci break; 17688c2ecf20Sopenharmony_ci case OM_Default: 17698c2ecf20Sopenharmony_ci /* We need to check how to 17708c2ecf20Sopenharmony_ci get DRXD out of diversity */ 17718c2ecf20Sopenharmony_ci default: 17728c2ecf20Sopenharmony_ci status = WriteTable(state, state->m_DisableDiversity); 17738c2ecf20Sopenharmony_ci break; 17748c2ecf20Sopenharmony_ci } 17758c2ecf20Sopenharmony_ci } while (0); 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci if (!status) 17788c2ecf20Sopenharmony_ci state->operation_mode = oMode; 17798c2ecf20Sopenharmony_ci return status; 17808c2ecf20Sopenharmony_ci} 17818c2ecf20Sopenharmony_ci#endif 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_cistatic int StartDiversity(struct drxd_state *state) 17848c2ecf20Sopenharmony_ci{ 17858c2ecf20Sopenharmony_ci int status = 0; 17868c2ecf20Sopenharmony_ci u16 rcControl; 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci do { 17898c2ecf20Sopenharmony_ci if (state->operation_mode == OM_DVBT_Diversity_Front) { 17908c2ecf20Sopenharmony_ci status = WriteTable(state, state->m_StartDiversityFront); 17918c2ecf20Sopenharmony_ci if (status < 0) 17928c2ecf20Sopenharmony_ci break; 17938c2ecf20Sopenharmony_ci } else if (state->operation_mode == OM_DVBT_Diversity_End) { 17948c2ecf20Sopenharmony_ci status = WriteTable(state, state->m_StartDiversityEnd); 17958c2ecf20Sopenharmony_ci if (status < 0) 17968c2ecf20Sopenharmony_ci break; 17978c2ecf20Sopenharmony_ci if (state->props.bandwidth_hz == 8000000) { 17988c2ecf20Sopenharmony_ci status = WriteTable(state, state->m_DiversityDelay8MHZ); 17998c2ecf20Sopenharmony_ci if (status < 0) 18008c2ecf20Sopenharmony_ci break; 18018c2ecf20Sopenharmony_ci } else { 18028c2ecf20Sopenharmony_ci status = WriteTable(state, state->m_DiversityDelay6MHZ); 18038c2ecf20Sopenharmony_ci if (status < 0) 18048c2ecf20Sopenharmony_ci break; 18058c2ecf20Sopenharmony_ci } 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci status = Read16(state, B_EQ_REG_RC_SEL_CAR__A, &rcControl, 0); 18088c2ecf20Sopenharmony_ci if (status < 0) 18098c2ecf20Sopenharmony_ci break; 18108c2ecf20Sopenharmony_ci rcControl &= ~(B_EQ_REG_RC_SEL_CAR_FFTMODE__M); 18118c2ecf20Sopenharmony_ci rcControl |= B_EQ_REG_RC_SEL_CAR_DIV_ON | 18128c2ecf20Sopenharmony_ci /* combining enabled */ 18138c2ecf20Sopenharmony_ci B_EQ_REG_RC_SEL_CAR_MEAS_A_CC | 18148c2ecf20Sopenharmony_ci B_EQ_REG_RC_SEL_CAR_PASS_A_CC | 18158c2ecf20Sopenharmony_ci B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC; 18168c2ecf20Sopenharmony_ci status = Write16(state, B_EQ_REG_RC_SEL_CAR__A, rcControl, 0); 18178c2ecf20Sopenharmony_ci if (status < 0) 18188c2ecf20Sopenharmony_ci break; 18198c2ecf20Sopenharmony_ci } 18208c2ecf20Sopenharmony_ci } while (0); 18218c2ecf20Sopenharmony_ci return status; 18228c2ecf20Sopenharmony_ci} 18238c2ecf20Sopenharmony_ci 18248c2ecf20Sopenharmony_cistatic int SetFrequencyShift(struct drxd_state *state, 18258c2ecf20Sopenharmony_ci u32 offsetFreq, int channelMirrored) 18268c2ecf20Sopenharmony_ci{ 18278c2ecf20Sopenharmony_ci int negativeShift = (state->tuner_mirrors == channelMirrored); 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_ci /* Handle all mirroring 18308c2ecf20Sopenharmony_ci * 18318c2ecf20Sopenharmony_ci * Note: ADC mirroring (aliasing) is implictly handled by limiting 18328c2ecf20Sopenharmony_ci * feFsRegAddInc to 28 bits below 18338c2ecf20Sopenharmony_ci * (if the result before masking is more than 28 bits, this means 18348c2ecf20Sopenharmony_ci * that the ADC is mirroring. 18358c2ecf20Sopenharmony_ci * The masking is in fact the aliasing of the ADC) 18368c2ecf20Sopenharmony_ci * 18378c2ecf20Sopenharmony_ci */ 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci /* Compute register value, unsigned computation */ 18408c2ecf20Sopenharmony_ci state->fe_fs_add_incr = MulDiv32(state->intermediate_freq + 18418c2ecf20Sopenharmony_ci offsetFreq, 18428c2ecf20Sopenharmony_ci 1 << 28, state->sys_clock_freq); 18438c2ecf20Sopenharmony_ci /* Remove integer part */ 18448c2ecf20Sopenharmony_ci state->fe_fs_add_incr &= 0x0FFFFFFFL; 18458c2ecf20Sopenharmony_ci if (negativeShift) 18468c2ecf20Sopenharmony_ci state->fe_fs_add_incr = ((1 << 28) - state->fe_fs_add_incr); 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ci /* Save the frequency shift without tunerOffset compensation 18498c2ecf20Sopenharmony_ci for CtrlGetChannel. */ 18508c2ecf20Sopenharmony_ci state->org_fe_fs_add_incr = MulDiv32(state->intermediate_freq, 18518c2ecf20Sopenharmony_ci 1 << 28, state->sys_clock_freq); 18528c2ecf20Sopenharmony_ci /* Remove integer part */ 18538c2ecf20Sopenharmony_ci state->org_fe_fs_add_incr &= 0x0FFFFFFFL; 18548c2ecf20Sopenharmony_ci if (negativeShift) 18558c2ecf20Sopenharmony_ci state->org_fe_fs_add_incr = ((1L << 28) - 18568c2ecf20Sopenharmony_ci state->org_fe_fs_add_incr); 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci return Write32(state, FE_FS_REG_ADD_INC_LOP__A, 18598c2ecf20Sopenharmony_ci state->fe_fs_add_incr, 0); 18608c2ecf20Sopenharmony_ci} 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_cistatic int SetCfgNoiseCalibration(struct drxd_state *state, 18638c2ecf20Sopenharmony_ci struct SNoiseCal *noiseCal) 18648c2ecf20Sopenharmony_ci{ 18658c2ecf20Sopenharmony_ci u16 beOptEna; 18668c2ecf20Sopenharmony_ci int status = 0; 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci do { 18698c2ecf20Sopenharmony_ci status = Read16(state, SC_RA_RAM_BE_OPT_ENA__A, &beOptEna, 0); 18708c2ecf20Sopenharmony_ci if (status < 0) 18718c2ecf20Sopenharmony_ci break; 18728c2ecf20Sopenharmony_ci if (noiseCal->cpOpt) { 18738c2ecf20Sopenharmony_ci beOptEna |= (1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT); 18748c2ecf20Sopenharmony_ci } else { 18758c2ecf20Sopenharmony_ci beOptEna &= ~(1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT); 18768c2ecf20Sopenharmony_ci status = Write16(state, CP_REG_AC_NEXP_OFFS__A, noiseCal->cpNexpOfs, 0); 18778c2ecf20Sopenharmony_ci if (status < 0) 18788c2ecf20Sopenharmony_ci break; 18798c2ecf20Sopenharmony_ci } 18808c2ecf20Sopenharmony_ci status = Write16(state, SC_RA_RAM_BE_OPT_ENA__A, beOptEna, 0); 18818c2ecf20Sopenharmony_ci if (status < 0) 18828c2ecf20Sopenharmony_ci break; 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_ci if (!state->type_A) { 18858c2ecf20Sopenharmony_ci status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_2K__A, noiseCal->tdCal2k, 0); 18868c2ecf20Sopenharmony_ci if (status < 0) 18878c2ecf20Sopenharmony_ci break; 18888c2ecf20Sopenharmony_ci status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_8K__A, noiseCal->tdCal8k, 0); 18898c2ecf20Sopenharmony_ci if (status < 0) 18908c2ecf20Sopenharmony_ci break; 18918c2ecf20Sopenharmony_ci } 18928c2ecf20Sopenharmony_ci } while (0); 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ci return status; 18958c2ecf20Sopenharmony_ci} 18968c2ecf20Sopenharmony_ci 18978c2ecf20Sopenharmony_cistatic int DRX_Start(struct drxd_state *state, s32 off) 18988c2ecf20Sopenharmony_ci{ 18998c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &state->props; 19008c2ecf20Sopenharmony_ci int status; 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci u16 transmissionParams = 0; 19038c2ecf20Sopenharmony_ci u16 operationMode = 0; 19048c2ecf20Sopenharmony_ci u16 qpskTdTpsPwr = 0; 19058c2ecf20Sopenharmony_ci u16 qam16TdTpsPwr = 0; 19068c2ecf20Sopenharmony_ci u16 qam64TdTpsPwr = 0; 19078c2ecf20Sopenharmony_ci u32 feIfIncr = 0; 19088c2ecf20Sopenharmony_ci u32 bandwidth = 0; 19098c2ecf20Sopenharmony_ci int mirrorFreqSpect; 19108c2ecf20Sopenharmony_ci 19118c2ecf20Sopenharmony_ci u16 qpskSnCeGain = 0; 19128c2ecf20Sopenharmony_ci u16 qam16SnCeGain = 0; 19138c2ecf20Sopenharmony_ci u16 qam64SnCeGain = 0; 19148c2ecf20Sopenharmony_ci u16 qpskIsGainMan = 0; 19158c2ecf20Sopenharmony_ci u16 qam16IsGainMan = 0; 19168c2ecf20Sopenharmony_ci u16 qam64IsGainMan = 0; 19178c2ecf20Sopenharmony_ci u16 qpskIsGainExp = 0; 19188c2ecf20Sopenharmony_ci u16 qam16IsGainExp = 0; 19198c2ecf20Sopenharmony_ci u16 qam64IsGainExp = 0; 19208c2ecf20Sopenharmony_ci u16 bandwidthParam = 0; 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci if (off < 0) 19238c2ecf20Sopenharmony_ci off = (off - 500) / 1000; 19248c2ecf20Sopenharmony_ci else 19258c2ecf20Sopenharmony_ci off = (off + 500) / 1000; 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci do { 19288c2ecf20Sopenharmony_ci if (state->drxd_state != DRXD_STOPPED) 19298c2ecf20Sopenharmony_ci return -1; 19308c2ecf20Sopenharmony_ci status = ResetECOD(state); 19318c2ecf20Sopenharmony_ci if (status < 0) 19328c2ecf20Sopenharmony_ci break; 19338c2ecf20Sopenharmony_ci if (state->type_A) { 19348c2ecf20Sopenharmony_ci status = InitSC(state); 19358c2ecf20Sopenharmony_ci if (status < 0) 19368c2ecf20Sopenharmony_ci break; 19378c2ecf20Sopenharmony_ci } else { 19388c2ecf20Sopenharmony_ci status = InitFT(state); 19398c2ecf20Sopenharmony_ci if (status < 0) 19408c2ecf20Sopenharmony_ci break; 19418c2ecf20Sopenharmony_ci status = InitCP(state); 19428c2ecf20Sopenharmony_ci if (status < 0) 19438c2ecf20Sopenharmony_ci break; 19448c2ecf20Sopenharmony_ci status = InitCE(state); 19458c2ecf20Sopenharmony_ci if (status < 0) 19468c2ecf20Sopenharmony_ci break; 19478c2ecf20Sopenharmony_ci status = InitEQ(state); 19488c2ecf20Sopenharmony_ci if (status < 0) 19498c2ecf20Sopenharmony_ci break; 19508c2ecf20Sopenharmony_ci status = InitSC(state); 19518c2ecf20Sopenharmony_ci if (status < 0) 19528c2ecf20Sopenharmony_ci break; 19538c2ecf20Sopenharmony_ci } 19548c2ecf20Sopenharmony_ci 19558c2ecf20Sopenharmony_ci /* Restore current IF & RF AGC settings */ 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_ci status = SetCfgIfAgc(state, &state->if_agc_cfg); 19588c2ecf20Sopenharmony_ci if (status < 0) 19598c2ecf20Sopenharmony_ci break; 19608c2ecf20Sopenharmony_ci status = SetCfgRfAgc(state, &state->rf_agc_cfg); 19618c2ecf20Sopenharmony_ci if (status < 0) 19628c2ecf20Sopenharmony_ci break; 19638c2ecf20Sopenharmony_ci 19648c2ecf20Sopenharmony_ci mirrorFreqSpect = (state->props.inversion == INVERSION_ON); 19658c2ecf20Sopenharmony_ci 19668c2ecf20Sopenharmony_ci switch (p->transmission_mode) { 19678c2ecf20Sopenharmony_ci default: /* Not set, detect it automatically */ 19688c2ecf20Sopenharmony_ci operationMode |= SC_RA_RAM_OP_AUTO_MODE__M; 19698c2ecf20Sopenharmony_ci fallthrough; /* try first guess DRX_FFTMODE_8K */ 19708c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_8K: 19718c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_8K; 19728c2ecf20Sopenharmony_ci if (state->type_A) { 19738c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_8K, 0x0000); 19748c2ecf20Sopenharmony_ci if (status < 0) 19758c2ecf20Sopenharmony_ci break; 19768c2ecf20Sopenharmony_ci qpskSnCeGain = 99; 19778c2ecf20Sopenharmony_ci qam16SnCeGain = 83; 19788c2ecf20Sopenharmony_ci qam64SnCeGain = 67; 19798c2ecf20Sopenharmony_ci } 19808c2ecf20Sopenharmony_ci break; 19818c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_2K: 19828c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_2K; 19838c2ecf20Sopenharmony_ci if (state->type_A) { 19848c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_2K, 0x0000); 19858c2ecf20Sopenharmony_ci if (status < 0) 19868c2ecf20Sopenharmony_ci break; 19878c2ecf20Sopenharmony_ci qpskSnCeGain = 97; 19888c2ecf20Sopenharmony_ci qam16SnCeGain = 71; 19898c2ecf20Sopenharmony_ci qam64SnCeGain = 65; 19908c2ecf20Sopenharmony_ci } 19918c2ecf20Sopenharmony_ci break; 19928c2ecf20Sopenharmony_ci } 19938c2ecf20Sopenharmony_ci 19948c2ecf20Sopenharmony_ci switch (p->guard_interval) { 19958c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_4: 19968c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4; 19978c2ecf20Sopenharmony_ci break; 19988c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_8: 19998c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_8; 20008c2ecf20Sopenharmony_ci break; 20018c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_16: 20028c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_16; 20038c2ecf20Sopenharmony_ci break; 20048c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_32: 20058c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_32; 20068c2ecf20Sopenharmony_ci break; 20078c2ecf20Sopenharmony_ci default: /* Not set, detect it automatically */ 20088c2ecf20Sopenharmony_ci operationMode |= SC_RA_RAM_OP_AUTO_GUARD__M; 20098c2ecf20Sopenharmony_ci /* try first guess 1/4 */ 20108c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4; 20118c2ecf20Sopenharmony_ci break; 20128c2ecf20Sopenharmony_ci } 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_ci switch (p->hierarchy) { 20158c2ecf20Sopenharmony_ci case HIERARCHY_1: 20168c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A1; 20178c2ecf20Sopenharmony_ci if (state->type_A) { 20188c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0001, 0x0000); 20198c2ecf20Sopenharmony_ci if (status < 0) 20208c2ecf20Sopenharmony_ci break; 20218c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_ALPHA__A, 0x0001, 0x0000); 20228c2ecf20Sopenharmony_ci if (status < 0) 20238c2ecf20Sopenharmony_ci break; 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN; 20268c2ecf20Sopenharmony_ci qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA1; 20278c2ecf20Sopenharmony_ci qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA1; 20288c2ecf20Sopenharmony_ci 20298c2ecf20Sopenharmony_ci qpskIsGainMan = 20308c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE; 20318c2ecf20Sopenharmony_ci qam16IsGainMan = 20328c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE; 20338c2ecf20Sopenharmony_ci qam64IsGainMan = 20348c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE; 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci qpskIsGainExp = 20378c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE; 20388c2ecf20Sopenharmony_ci qam16IsGainExp = 20398c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE; 20408c2ecf20Sopenharmony_ci qam64IsGainExp = 20418c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE; 20428c2ecf20Sopenharmony_ci } 20438c2ecf20Sopenharmony_ci break; 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci case HIERARCHY_2: 20468c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A2; 20478c2ecf20Sopenharmony_ci if (state->type_A) { 20488c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0002, 0x0000); 20498c2ecf20Sopenharmony_ci if (status < 0) 20508c2ecf20Sopenharmony_ci break; 20518c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_ALPHA__A, 0x0002, 0x0000); 20528c2ecf20Sopenharmony_ci if (status < 0) 20538c2ecf20Sopenharmony_ci break; 20548c2ecf20Sopenharmony_ci 20558c2ecf20Sopenharmony_ci qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN; 20568c2ecf20Sopenharmony_ci qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA2; 20578c2ecf20Sopenharmony_ci qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA2; 20588c2ecf20Sopenharmony_ci 20598c2ecf20Sopenharmony_ci qpskIsGainMan = 20608c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE; 20618c2ecf20Sopenharmony_ci qam16IsGainMan = 20628c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE; 20638c2ecf20Sopenharmony_ci qam64IsGainMan = 20648c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE; 20658c2ecf20Sopenharmony_ci 20668c2ecf20Sopenharmony_ci qpskIsGainExp = 20678c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE; 20688c2ecf20Sopenharmony_ci qam16IsGainExp = 20698c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE; 20708c2ecf20Sopenharmony_ci qam64IsGainExp = 20718c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE; 20728c2ecf20Sopenharmony_ci } 20738c2ecf20Sopenharmony_ci break; 20748c2ecf20Sopenharmony_ci case HIERARCHY_4: 20758c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A4; 20768c2ecf20Sopenharmony_ci if (state->type_A) { 20778c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0003, 0x0000); 20788c2ecf20Sopenharmony_ci if (status < 0) 20798c2ecf20Sopenharmony_ci break; 20808c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_ALPHA__A, 0x0003, 0x0000); 20818c2ecf20Sopenharmony_ci if (status < 0) 20828c2ecf20Sopenharmony_ci break; 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN; 20858c2ecf20Sopenharmony_ci qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA4; 20868c2ecf20Sopenharmony_ci qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA4; 20878c2ecf20Sopenharmony_ci 20888c2ecf20Sopenharmony_ci qpskIsGainMan = 20898c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE; 20908c2ecf20Sopenharmony_ci qam16IsGainMan = 20918c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE; 20928c2ecf20Sopenharmony_ci qam64IsGainMan = 20938c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE; 20948c2ecf20Sopenharmony_ci 20958c2ecf20Sopenharmony_ci qpskIsGainExp = 20968c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE; 20978c2ecf20Sopenharmony_ci qam16IsGainExp = 20988c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE; 20998c2ecf20Sopenharmony_ci qam64IsGainExp = 21008c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE; 21018c2ecf20Sopenharmony_ci } 21028c2ecf20Sopenharmony_ci break; 21038c2ecf20Sopenharmony_ci case HIERARCHY_AUTO: 21048c2ecf20Sopenharmony_ci default: 21058c2ecf20Sopenharmony_ci /* Not set, detect it automatically, start with none */ 21068c2ecf20Sopenharmony_ci operationMode |= SC_RA_RAM_OP_AUTO_HIER__M; 21078c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_NO; 21088c2ecf20Sopenharmony_ci if (state->type_A) { 21098c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0000, 0x0000); 21108c2ecf20Sopenharmony_ci if (status < 0) 21118c2ecf20Sopenharmony_ci break; 21128c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_ALPHA__A, 0x0000, 0x0000); 21138c2ecf20Sopenharmony_ci if (status < 0) 21148c2ecf20Sopenharmony_ci break; 21158c2ecf20Sopenharmony_ci 21168c2ecf20Sopenharmony_ci qpskTdTpsPwr = EQ_TD_TPS_PWR_QPSK; 21178c2ecf20Sopenharmony_ci qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHAN; 21188c2ecf20Sopenharmony_ci qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHAN; 21198c2ecf20Sopenharmony_ci 21208c2ecf20Sopenharmony_ci qpskIsGainMan = 21218c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE; 21228c2ecf20Sopenharmony_ci qam16IsGainMan = 21238c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE; 21248c2ecf20Sopenharmony_ci qam64IsGainMan = 21258c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE; 21268c2ecf20Sopenharmony_ci 21278c2ecf20Sopenharmony_ci qpskIsGainExp = 21288c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE; 21298c2ecf20Sopenharmony_ci qam16IsGainExp = 21308c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE; 21318c2ecf20Sopenharmony_ci qam64IsGainExp = 21328c2ecf20Sopenharmony_ci SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE; 21338c2ecf20Sopenharmony_ci } 21348c2ecf20Sopenharmony_ci break; 21358c2ecf20Sopenharmony_ci } 21368c2ecf20Sopenharmony_ci if (status < 0) 21378c2ecf20Sopenharmony_ci break; 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci switch (p->modulation) { 21408c2ecf20Sopenharmony_ci default: 21418c2ecf20Sopenharmony_ci operationMode |= SC_RA_RAM_OP_AUTO_CONST__M; 21428c2ecf20Sopenharmony_ci fallthrough; /* try first guess DRX_CONSTELLATION_QAM64 */ 21438c2ecf20Sopenharmony_ci case QAM_64: 21448c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM64; 21458c2ecf20Sopenharmony_ci if (state->type_A) { 21468c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_OT_CONST__A, 0x0002, 0x0000); 21478c2ecf20Sopenharmony_ci if (status < 0) 21488c2ecf20Sopenharmony_ci break; 21498c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_64QAM, 0x0000); 21508c2ecf20Sopenharmony_ci if (status < 0) 21518c2ecf20Sopenharmony_ci break; 21528c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0020, 0x0000); 21538c2ecf20Sopenharmony_ci if (status < 0) 21548c2ecf20Sopenharmony_ci break; 21558c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0008, 0x0000); 21568c2ecf20Sopenharmony_ci if (status < 0) 21578c2ecf20Sopenharmony_ci break; 21588c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0002, 0x0000); 21598c2ecf20Sopenharmony_ci if (status < 0) 21608c2ecf20Sopenharmony_ci break; 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam64TdTpsPwr, 0x0000); 21638c2ecf20Sopenharmony_ci if (status < 0) 21648c2ecf20Sopenharmony_ci break; 21658c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_SN_CEGAIN__A, qam64SnCeGain, 0x0000); 21668c2ecf20Sopenharmony_ci if (status < 0) 21678c2ecf20Sopenharmony_ci break; 21688c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam64IsGainMan, 0x0000); 21698c2ecf20Sopenharmony_ci if (status < 0) 21708c2ecf20Sopenharmony_ci break; 21718c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam64IsGainExp, 0x0000); 21728c2ecf20Sopenharmony_ci if (status < 0) 21738c2ecf20Sopenharmony_ci break; 21748c2ecf20Sopenharmony_ci } 21758c2ecf20Sopenharmony_ci break; 21768c2ecf20Sopenharmony_ci case QPSK: 21778c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QPSK; 21788c2ecf20Sopenharmony_ci if (state->type_A) { 21798c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_OT_CONST__A, 0x0000, 0x0000); 21808c2ecf20Sopenharmony_ci if (status < 0) 21818c2ecf20Sopenharmony_ci break; 21828c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_QPSK, 0x0000); 21838c2ecf20Sopenharmony_ci if (status < 0) 21848c2ecf20Sopenharmony_ci break; 21858c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000); 21868c2ecf20Sopenharmony_ci if (status < 0) 21878c2ecf20Sopenharmony_ci break; 21888c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0000, 0x0000); 21898c2ecf20Sopenharmony_ci if (status < 0) 21908c2ecf20Sopenharmony_ci break; 21918c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000); 21928c2ecf20Sopenharmony_ci if (status < 0) 21938c2ecf20Sopenharmony_ci break; 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qpskTdTpsPwr, 0x0000); 21968c2ecf20Sopenharmony_ci if (status < 0) 21978c2ecf20Sopenharmony_ci break; 21988c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_SN_CEGAIN__A, qpskSnCeGain, 0x0000); 21998c2ecf20Sopenharmony_ci if (status < 0) 22008c2ecf20Sopenharmony_ci break; 22018c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qpskIsGainMan, 0x0000); 22028c2ecf20Sopenharmony_ci if (status < 0) 22038c2ecf20Sopenharmony_ci break; 22048c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qpskIsGainExp, 0x0000); 22058c2ecf20Sopenharmony_ci if (status < 0) 22068c2ecf20Sopenharmony_ci break; 22078c2ecf20Sopenharmony_ci } 22088c2ecf20Sopenharmony_ci break; 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci case QAM_16: 22118c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM16; 22128c2ecf20Sopenharmony_ci if (state->type_A) { 22138c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_OT_CONST__A, 0x0001, 0x0000); 22148c2ecf20Sopenharmony_ci if (status < 0) 22158c2ecf20Sopenharmony_ci break; 22168c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_16QAM, 0x0000); 22178c2ecf20Sopenharmony_ci if (status < 0) 22188c2ecf20Sopenharmony_ci break; 22198c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000); 22208c2ecf20Sopenharmony_ci if (status < 0) 22218c2ecf20Sopenharmony_ci break; 22228c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0004, 0x0000); 22238c2ecf20Sopenharmony_ci if (status < 0) 22248c2ecf20Sopenharmony_ci break; 22258c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000); 22268c2ecf20Sopenharmony_ci if (status < 0) 22278c2ecf20Sopenharmony_ci break; 22288c2ecf20Sopenharmony_ci 22298c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam16TdTpsPwr, 0x0000); 22308c2ecf20Sopenharmony_ci if (status < 0) 22318c2ecf20Sopenharmony_ci break; 22328c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_SN_CEGAIN__A, qam16SnCeGain, 0x0000); 22338c2ecf20Sopenharmony_ci if (status < 0) 22348c2ecf20Sopenharmony_ci break; 22358c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam16IsGainMan, 0x0000); 22368c2ecf20Sopenharmony_ci if (status < 0) 22378c2ecf20Sopenharmony_ci break; 22388c2ecf20Sopenharmony_ci status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam16IsGainExp, 0x0000); 22398c2ecf20Sopenharmony_ci if (status < 0) 22408c2ecf20Sopenharmony_ci break; 22418c2ecf20Sopenharmony_ci } 22428c2ecf20Sopenharmony_ci break; 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci } 22458c2ecf20Sopenharmony_ci if (status < 0) 22468c2ecf20Sopenharmony_ci break; 22478c2ecf20Sopenharmony_ci 22488c2ecf20Sopenharmony_ci switch (DRX_CHANNEL_HIGH) { 22498c2ecf20Sopenharmony_ci default: 22508c2ecf20Sopenharmony_ci case DRX_CHANNEL_AUTO: 22518c2ecf20Sopenharmony_ci case DRX_CHANNEL_LOW: 22528c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_LO; 22538c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_LO, 0x0000); 22548c2ecf20Sopenharmony_ci break; 22558c2ecf20Sopenharmony_ci case DRX_CHANNEL_HIGH: 22568c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_HI; 22578c2ecf20Sopenharmony_ci status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_HI, 0x0000); 22588c2ecf20Sopenharmony_ci break; 22598c2ecf20Sopenharmony_ci } 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_ci switch (p->code_rate_HP) { 22628c2ecf20Sopenharmony_ci case FEC_1_2: 22638c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_1_2; 22648c2ecf20Sopenharmony_ci if (state->type_A) 22658c2ecf20Sopenharmony_ci status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C1_2, 0x0000); 22668c2ecf20Sopenharmony_ci break; 22678c2ecf20Sopenharmony_ci default: 22688c2ecf20Sopenharmony_ci operationMode |= SC_RA_RAM_OP_AUTO_RATE__M; 22698c2ecf20Sopenharmony_ci fallthrough; 22708c2ecf20Sopenharmony_ci case FEC_2_3: 22718c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_2_3; 22728c2ecf20Sopenharmony_ci if (state->type_A) 22738c2ecf20Sopenharmony_ci status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C2_3, 0x0000); 22748c2ecf20Sopenharmony_ci break; 22758c2ecf20Sopenharmony_ci case FEC_3_4: 22768c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_3_4; 22778c2ecf20Sopenharmony_ci if (state->type_A) 22788c2ecf20Sopenharmony_ci status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C3_4, 0x0000); 22798c2ecf20Sopenharmony_ci break; 22808c2ecf20Sopenharmony_ci case FEC_5_6: 22818c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_5_6; 22828c2ecf20Sopenharmony_ci if (state->type_A) 22838c2ecf20Sopenharmony_ci status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C5_6, 0x0000); 22848c2ecf20Sopenharmony_ci break; 22858c2ecf20Sopenharmony_ci case FEC_7_8: 22868c2ecf20Sopenharmony_ci transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_7_8; 22878c2ecf20Sopenharmony_ci if (state->type_A) 22888c2ecf20Sopenharmony_ci status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C7_8, 0x0000); 22898c2ecf20Sopenharmony_ci break; 22908c2ecf20Sopenharmony_ci } 22918c2ecf20Sopenharmony_ci if (status < 0) 22928c2ecf20Sopenharmony_ci break; 22938c2ecf20Sopenharmony_ci 22948c2ecf20Sopenharmony_ci /* First determine real bandwidth (Hz) */ 22958c2ecf20Sopenharmony_ci /* Also set delay for impulse noise cruncher (only A2) */ 22968c2ecf20Sopenharmony_ci /* Also set parameters for EC_OC fix, note 22978c2ecf20Sopenharmony_ci EC_OC_REG_TMD_HIL_MAR is changed 22988c2ecf20Sopenharmony_ci by SC for fix for some 8K,1/8 guard but is restored by 22998c2ecf20Sopenharmony_ci InitEC and ResetEC 23008c2ecf20Sopenharmony_ci functions */ 23018c2ecf20Sopenharmony_ci switch (p->bandwidth_hz) { 23028c2ecf20Sopenharmony_ci case 0: 23038c2ecf20Sopenharmony_ci p->bandwidth_hz = 8000000; 23048c2ecf20Sopenharmony_ci fallthrough; 23058c2ecf20Sopenharmony_ci case 8000000: 23068c2ecf20Sopenharmony_ci /* (64/7)*(8/8)*1000000 */ 23078c2ecf20Sopenharmony_ci bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ; 23088c2ecf20Sopenharmony_ci 23098c2ecf20Sopenharmony_ci bandwidthParam = 0; 23108c2ecf20Sopenharmony_ci status = Write16(state, 23118c2ecf20Sopenharmony_ci FE_AG_REG_IND_DEL__A, 50, 0x0000); 23128c2ecf20Sopenharmony_ci break; 23138c2ecf20Sopenharmony_ci case 7000000: 23148c2ecf20Sopenharmony_ci /* (64/7)*(7/8)*1000000 */ 23158c2ecf20Sopenharmony_ci bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ; 23168c2ecf20Sopenharmony_ci bandwidthParam = 0x4807; /*binary:0100 1000 0000 0111 */ 23178c2ecf20Sopenharmony_ci status = Write16(state, 23188c2ecf20Sopenharmony_ci FE_AG_REG_IND_DEL__A, 59, 0x0000); 23198c2ecf20Sopenharmony_ci break; 23208c2ecf20Sopenharmony_ci case 6000000: 23218c2ecf20Sopenharmony_ci /* (64/7)*(6/8)*1000000 */ 23228c2ecf20Sopenharmony_ci bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ; 23238c2ecf20Sopenharmony_ci bandwidthParam = 0x0F07; /*binary: 0000 1111 0000 0111 */ 23248c2ecf20Sopenharmony_ci status = Write16(state, 23258c2ecf20Sopenharmony_ci FE_AG_REG_IND_DEL__A, 71, 0x0000); 23268c2ecf20Sopenharmony_ci break; 23278c2ecf20Sopenharmony_ci default: 23288c2ecf20Sopenharmony_ci status = -EINVAL; 23298c2ecf20Sopenharmony_ci } 23308c2ecf20Sopenharmony_ci if (status < 0) 23318c2ecf20Sopenharmony_ci break; 23328c2ecf20Sopenharmony_ci 23338c2ecf20Sopenharmony_ci status = Write16(state, SC_RA_RAM_BAND__A, bandwidthParam, 0x0000); 23348c2ecf20Sopenharmony_ci if (status < 0) 23358c2ecf20Sopenharmony_ci break; 23368c2ecf20Sopenharmony_ci 23378c2ecf20Sopenharmony_ci { 23388c2ecf20Sopenharmony_ci u16 sc_config; 23398c2ecf20Sopenharmony_ci status = Read16(state, SC_RA_RAM_CONFIG__A, &sc_config, 0); 23408c2ecf20Sopenharmony_ci if (status < 0) 23418c2ecf20Sopenharmony_ci break; 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_ci /* enable SLAVE mode in 2k 1/32 to 23448c2ecf20Sopenharmony_ci prevent timing change glitches */ 23458c2ecf20Sopenharmony_ci if ((p->transmission_mode == TRANSMISSION_MODE_2K) && 23468c2ecf20Sopenharmony_ci (p->guard_interval == GUARD_INTERVAL_1_32)) { 23478c2ecf20Sopenharmony_ci /* enable slave */ 23488c2ecf20Sopenharmony_ci sc_config |= SC_RA_RAM_CONFIG_SLAVE__M; 23498c2ecf20Sopenharmony_ci } else { 23508c2ecf20Sopenharmony_ci /* disable slave */ 23518c2ecf20Sopenharmony_ci sc_config &= ~SC_RA_RAM_CONFIG_SLAVE__M; 23528c2ecf20Sopenharmony_ci } 23538c2ecf20Sopenharmony_ci status = Write16(state, SC_RA_RAM_CONFIG__A, sc_config, 0); 23548c2ecf20Sopenharmony_ci if (status < 0) 23558c2ecf20Sopenharmony_ci break; 23568c2ecf20Sopenharmony_ci } 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci status = SetCfgNoiseCalibration(state, &state->noise_cal); 23598c2ecf20Sopenharmony_ci if (status < 0) 23608c2ecf20Sopenharmony_ci break; 23618c2ecf20Sopenharmony_ci 23628c2ecf20Sopenharmony_ci if (state->cscd_state == CSCD_INIT) { 23638c2ecf20Sopenharmony_ci /* switch on SRMM scan in SC */ 23648c2ecf20Sopenharmony_ci status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DO_SCAN, 0x0000); 23658c2ecf20Sopenharmony_ci if (status < 0) 23668c2ecf20Sopenharmony_ci break; 23678c2ecf20Sopenharmony_ci/* CHK_ERROR(Write16(SC_RA_RAM_SAMPLE_RATE_STEP__A, DRXD_OSCDEV_STEP, 0x0000));*/ 23688c2ecf20Sopenharmony_ci state->cscd_state = CSCD_SET; 23698c2ecf20Sopenharmony_ci } 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci /* Now compute FE_IF_REG_INCR */ 23728c2ecf20Sopenharmony_ci /*((( SysFreq/BandWidth)/2)/2) -1) * 2^23) => 23738c2ecf20Sopenharmony_ci ((SysFreq / BandWidth) * (2^21) ) - (2^23) */ 23748c2ecf20Sopenharmony_ci feIfIncr = MulDiv32(state->sys_clock_freq * 1000, 23758c2ecf20Sopenharmony_ci (1ULL << 21), bandwidth) - (1 << 23); 23768c2ecf20Sopenharmony_ci status = Write16(state, FE_IF_REG_INCR0__A, (u16) (feIfIncr & FE_IF_REG_INCR0__M), 0x0000); 23778c2ecf20Sopenharmony_ci if (status < 0) 23788c2ecf20Sopenharmony_ci break; 23798c2ecf20Sopenharmony_ci status = Write16(state, FE_IF_REG_INCR1__A, (u16) ((feIfIncr >> FE_IF_REG_INCR0__W) & FE_IF_REG_INCR1__M), 0x0000); 23808c2ecf20Sopenharmony_ci if (status < 0) 23818c2ecf20Sopenharmony_ci break; 23828c2ecf20Sopenharmony_ci /* Bandwidth setting done */ 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_ci /* Mirror & frequency offset */ 23858c2ecf20Sopenharmony_ci SetFrequencyShift(state, off, mirrorFreqSpect); 23868c2ecf20Sopenharmony_ci 23878c2ecf20Sopenharmony_ci /* Start SC, write channel settings to SC */ 23888c2ecf20Sopenharmony_ci 23898c2ecf20Sopenharmony_ci /* Enable SC after setting all other parameters */ 23908c2ecf20Sopenharmony_ci status = Write16(state, SC_COMM_STATE__A, 0, 0x0000); 23918c2ecf20Sopenharmony_ci if (status < 0) 23928c2ecf20Sopenharmony_ci break; 23938c2ecf20Sopenharmony_ci status = Write16(state, SC_COMM_EXEC__A, 1, 0x0000); 23948c2ecf20Sopenharmony_ci if (status < 0) 23958c2ecf20Sopenharmony_ci break; 23968c2ecf20Sopenharmony_ci 23978c2ecf20Sopenharmony_ci /* Write SC parameter registers, operation mode */ 23988c2ecf20Sopenharmony_ci#if 1 23998c2ecf20Sopenharmony_ci operationMode = (SC_RA_RAM_OP_AUTO_MODE__M | 24008c2ecf20Sopenharmony_ci SC_RA_RAM_OP_AUTO_GUARD__M | 24018c2ecf20Sopenharmony_ci SC_RA_RAM_OP_AUTO_CONST__M | 24028c2ecf20Sopenharmony_ci SC_RA_RAM_OP_AUTO_HIER__M | 24038c2ecf20Sopenharmony_ci SC_RA_RAM_OP_AUTO_RATE__M); 24048c2ecf20Sopenharmony_ci#endif 24058c2ecf20Sopenharmony_ci status = SC_SetPrefParamCommand(state, 0x0000, transmissionParams, operationMode); 24068c2ecf20Sopenharmony_ci if (status < 0) 24078c2ecf20Sopenharmony_ci break; 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_ci /* Start correct processes to get in lock */ 24108c2ecf20Sopenharmony_ci status = SC_ProcStartCommand(state, SC_RA_RAM_PROC_LOCKTRACK, SC_RA_RAM_SW_EVENT_RUN_NMASK__M, SC_RA_RAM_LOCKTRACK_MIN); 24118c2ecf20Sopenharmony_ci if (status < 0) 24128c2ecf20Sopenharmony_ci break; 24138c2ecf20Sopenharmony_ci 24148c2ecf20Sopenharmony_ci status = StartOC(state); 24158c2ecf20Sopenharmony_ci if (status < 0) 24168c2ecf20Sopenharmony_ci break; 24178c2ecf20Sopenharmony_ci 24188c2ecf20Sopenharmony_ci if (state->operation_mode != OM_Default) { 24198c2ecf20Sopenharmony_ci status = StartDiversity(state); 24208c2ecf20Sopenharmony_ci if (status < 0) 24218c2ecf20Sopenharmony_ci break; 24228c2ecf20Sopenharmony_ci } 24238c2ecf20Sopenharmony_ci 24248c2ecf20Sopenharmony_ci state->drxd_state = DRXD_STARTED; 24258c2ecf20Sopenharmony_ci } while (0); 24268c2ecf20Sopenharmony_ci 24278c2ecf20Sopenharmony_ci return status; 24288c2ecf20Sopenharmony_ci} 24298c2ecf20Sopenharmony_ci 24308c2ecf20Sopenharmony_cistatic int CDRXD(struct drxd_state *state, u32 IntermediateFrequency) 24318c2ecf20Sopenharmony_ci{ 24328c2ecf20Sopenharmony_ci u32 ulRfAgcOutputLevel = 0xffffffff; 24338c2ecf20Sopenharmony_ci u32 ulRfAgcSettleLevel = 528; /* Optimum value for MT2060 */ 24348c2ecf20Sopenharmony_ci u32 ulRfAgcMinLevel = 0; /* Currently unused */ 24358c2ecf20Sopenharmony_ci u32 ulRfAgcMaxLevel = DRXD_FE_CTRL_MAX; /* Currently unused */ 24368c2ecf20Sopenharmony_ci u32 ulRfAgcSpeed = 0; /* Currently unused */ 24378c2ecf20Sopenharmony_ci u32 ulRfAgcMode = 0; /*2; Off */ 24388c2ecf20Sopenharmony_ci u32 ulRfAgcR1 = 820; 24398c2ecf20Sopenharmony_ci u32 ulRfAgcR2 = 2200; 24408c2ecf20Sopenharmony_ci u32 ulRfAgcR3 = 150; 24418c2ecf20Sopenharmony_ci u32 ulIfAgcMode = 0; /* Auto */ 24428c2ecf20Sopenharmony_ci u32 ulIfAgcOutputLevel = 0xffffffff; 24438c2ecf20Sopenharmony_ci u32 ulIfAgcSettleLevel = 0xffffffff; 24448c2ecf20Sopenharmony_ci u32 ulIfAgcMinLevel = 0xffffffff; 24458c2ecf20Sopenharmony_ci u32 ulIfAgcMaxLevel = 0xffffffff; 24468c2ecf20Sopenharmony_ci u32 ulIfAgcSpeed = 0xffffffff; 24478c2ecf20Sopenharmony_ci u32 ulIfAgcR1 = 820; 24488c2ecf20Sopenharmony_ci u32 ulIfAgcR2 = 2200; 24498c2ecf20Sopenharmony_ci u32 ulIfAgcR3 = 150; 24508c2ecf20Sopenharmony_ci u32 ulClock = state->config.clock; 24518c2ecf20Sopenharmony_ci u32 ulSerialMode = 0; 24528c2ecf20Sopenharmony_ci u32 ulEcOcRegOcModeLop = 4; /* Dynamic DTO source */ 24538c2ecf20Sopenharmony_ci u32 ulHiI2cDelay = HI_I2C_DELAY; 24548c2ecf20Sopenharmony_ci u32 ulHiI2cBridgeDelay = HI_I2C_BRIDGE_DELAY; 24558c2ecf20Sopenharmony_ci u32 ulHiI2cPatch = 0; 24568c2ecf20Sopenharmony_ci u32 ulEnvironment = APPENV_PORTABLE; 24578c2ecf20Sopenharmony_ci u32 ulEnvironmentDiversity = APPENV_MOBILE; 24588c2ecf20Sopenharmony_ci u32 ulIFFilter = IFFILTER_SAW; 24598c2ecf20Sopenharmony_ci 24608c2ecf20Sopenharmony_ci state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO; 24618c2ecf20Sopenharmony_ci state->if_agc_cfg.outputLevel = 0; 24628c2ecf20Sopenharmony_ci state->if_agc_cfg.settleLevel = 140; 24638c2ecf20Sopenharmony_ci state->if_agc_cfg.minOutputLevel = 0; 24648c2ecf20Sopenharmony_ci state->if_agc_cfg.maxOutputLevel = 1023; 24658c2ecf20Sopenharmony_ci state->if_agc_cfg.speed = 904; 24668c2ecf20Sopenharmony_ci 24678c2ecf20Sopenharmony_ci if (ulIfAgcMode == 1 && ulIfAgcOutputLevel <= DRXD_FE_CTRL_MAX) { 24688c2ecf20Sopenharmony_ci state->if_agc_cfg.ctrlMode = AGC_CTRL_USER; 24698c2ecf20Sopenharmony_ci state->if_agc_cfg.outputLevel = (u16) (ulIfAgcOutputLevel); 24708c2ecf20Sopenharmony_ci } 24718c2ecf20Sopenharmony_ci 24728c2ecf20Sopenharmony_ci if (ulIfAgcMode == 0 && 24738c2ecf20Sopenharmony_ci ulIfAgcSettleLevel <= DRXD_FE_CTRL_MAX && 24748c2ecf20Sopenharmony_ci ulIfAgcMinLevel <= DRXD_FE_CTRL_MAX && 24758c2ecf20Sopenharmony_ci ulIfAgcMaxLevel <= DRXD_FE_CTRL_MAX && 24768c2ecf20Sopenharmony_ci ulIfAgcSpeed <= DRXD_FE_CTRL_MAX) { 24778c2ecf20Sopenharmony_ci state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO; 24788c2ecf20Sopenharmony_ci state->if_agc_cfg.settleLevel = (u16) (ulIfAgcSettleLevel); 24798c2ecf20Sopenharmony_ci state->if_agc_cfg.minOutputLevel = (u16) (ulIfAgcMinLevel); 24808c2ecf20Sopenharmony_ci state->if_agc_cfg.maxOutputLevel = (u16) (ulIfAgcMaxLevel); 24818c2ecf20Sopenharmony_ci state->if_agc_cfg.speed = (u16) (ulIfAgcSpeed); 24828c2ecf20Sopenharmony_ci } 24838c2ecf20Sopenharmony_ci 24848c2ecf20Sopenharmony_ci state->if_agc_cfg.R1 = (u16) (ulIfAgcR1); 24858c2ecf20Sopenharmony_ci state->if_agc_cfg.R2 = (u16) (ulIfAgcR2); 24868c2ecf20Sopenharmony_ci state->if_agc_cfg.R3 = (u16) (ulIfAgcR3); 24878c2ecf20Sopenharmony_ci 24888c2ecf20Sopenharmony_ci state->rf_agc_cfg.R1 = (u16) (ulRfAgcR1); 24898c2ecf20Sopenharmony_ci state->rf_agc_cfg.R2 = (u16) (ulRfAgcR2); 24908c2ecf20Sopenharmony_ci state->rf_agc_cfg.R3 = (u16) (ulRfAgcR3); 24918c2ecf20Sopenharmony_ci 24928c2ecf20Sopenharmony_ci state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO; 24938c2ecf20Sopenharmony_ci /* rest of the RFAgcCfg structure currently unused */ 24948c2ecf20Sopenharmony_ci if (ulRfAgcMode == 1 && ulRfAgcOutputLevel <= DRXD_FE_CTRL_MAX) { 24958c2ecf20Sopenharmony_ci state->rf_agc_cfg.ctrlMode = AGC_CTRL_USER; 24968c2ecf20Sopenharmony_ci state->rf_agc_cfg.outputLevel = (u16) (ulRfAgcOutputLevel); 24978c2ecf20Sopenharmony_ci } 24988c2ecf20Sopenharmony_ci 24998c2ecf20Sopenharmony_ci if (ulRfAgcMode == 0 && 25008c2ecf20Sopenharmony_ci ulRfAgcSettleLevel <= DRXD_FE_CTRL_MAX && 25018c2ecf20Sopenharmony_ci ulRfAgcMinLevel <= DRXD_FE_CTRL_MAX && 25028c2ecf20Sopenharmony_ci ulRfAgcMaxLevel <= DRXD_FE_CTRL_MAX && 25038c2ecf20Sopenharmony_ci ulRfAgcSpeed <= DRXD_FE_CTRL_MAX) { 25048c2ecf20Sopenharmony_ci state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO; 25058c2ecf20Sopenharmony_ci state->rf_agc_cfg.settleLevel = (u16) (ulRfAgcSettleLevel); 25068c2ecf20Sopenharmony_ci state->rf_agc_cfg.minOutputLevel = (u16) (ulRfAgcMinLevel); 25078c2ecf20Sopenharmony_ci state->rf_agc_cfg.maxOutputLevel = (u16) (ulRfAgcMaxLevel); 25088c2ecf20Sopenharmony_ci state->rf_agc_cfg.speed = (u16) (ulRfAgcSpeed); 25098c2ecf20Sopenharmony_ci } 25108c2ecf20Sopenharmony_ci 25118c2ecf20Sopenharmony_ci if (ulRfAgcMode == 2) 25128c2ecf20Sopenharmony_ci state->rf_agc_cfg.ctrlMode = AGC_CTRL_OFF; 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_ci if (ulEnvironment <= 2) 25158c2ecf20Sopenharmony_ci state->app_env_default = (enum app_env) 25168c2ecf20Sopenharmony_ci (ulEnvironment); 25178c2ecf20Sopenharmony_ci if (ulEnvironmentDiversity <= 2) 25188c2ecf20Sopenharmony_ci state->app_env_diversity = (enum app_env) 25198c2ecf20Sopenharmony_ci (ulEnvironmentDiversity); 25208c2ecf20Sopenharmony_ci 25218c2ecf20Sopenharmony_ci if (ulIFFilter == IFFILTER_DISCRETE) { 25228c2ecf20Sopenharmony_ci /* discrete filter */ 25238c2ecf20Sopenharmony_ci state->noise_cal.cpOpt = 0; 25248c2ecf20Sopenharmony_ci state->noise_cal.cpNexpOfs = 40; 25258c2ecf20Sopenharmony_ci state->noise_cal.tdCal2k = -40; 25268c2ecf20Sopenharmony_ci state->noise_cal.tdCal8k = -24; 25278c2ecf20Sopenharmony_ci } else { 25288c2ecf20Sopenharmony_ci /* SAW filter */ 25298c2ecf20Sopenharmony_ci state->noise_cal.cpOpt = 1; 25308c2ecf20Sopenharmony_ci state->noise_cal.cpNexpOfs = 0; 25318c2ecf20Sopenharmony_ci state->noise_cal.tdCal2k = -21; 25328c2ecf20Sopenharmony_ci state->noise_cal.tdCal8k = -24; 25338c2ecf20Sopenharmony_ci } 25348c2ecf20Sopenharmony_ci state->m_EcOcRegOcModeLop = (u16) (ulEcOcRegOcModeLop); 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci state->chip_adr = (state->config.demod_address << 1) | 1; 25378c2ecf20Sopenharmony_ci switch (ulHiI2cPatch) { 25388c2ecf20Sopenharmony_ci case 1: 25398c2ecf20Sopenharmony_ci state->m_HiI2cPatch = DRXD_HiI2cPatch_1; 25408c2ecf20Sopenharmony_ci break; 25418c2ecf20Sopenharmony_ci case 3: 25428c2ecf20Sopenharmony_ci state->m_HiI2cPatch = DRXD_HiI2cPatch_3; 25438c2ecf20Sopenharmony_ci break; 25448c2ecf20Sopenharmony_ci default: 25458c2ecf20Sopenharmony_ci state->m_HiI2cPatch = NULL; 25468c2ecf20Sopenharmony_ci } 25478c2ecf20Sopenharmony_ci 25488c2ecf20Sopenharmony_ci /* modify tuner and clock attributes */ 25498c2ecf20Sopenharmony_ci state->intermediate_freq = (u16) (IntermediateFrequency / 1000); 25508c2ecf20Sopenharmony_ci /* expected system clock frequency in kHz */ 25518c2ecf20Sopenharmony_ci state->expected_sys_clock_freq = 48000; 25528c2ecf20Sopenharmony_ci /* real system clock frequency in kHz */ 25538c2ecf20Sopenharmony_ci state->sys_clock_freq = 48000; 25548c2ecf20Sopenharmony_ci state->osc_clock_freq = (u16) ulClock; 25558c2ecf20Sopenharmony_ci state->osc_clock_deviation = 0; 25568c2ecf20Sopenharmony_ci state->cscd_state = CSCD_INIT; 25578c2ecf20Sopenharmony_ci state->drxd_state = DRXD_UNINITIALIZED; 25588c2ecf20Sopenharmony_ci 25598c2ecf20Sopenharmony_ci state->PGA = 0; 25608c2ecf20Sopenharmony_ci state->type_A = 0; 25618c2ecf20Sopenharmony_ci state->tuner_mirrors = 0; 25628c2ecf20Sopenharmony_ci 25638c2ecf20Sopenharmony_ci /* modify MPEG output attributes */ 25648c2ecf20Sopenharmony_ci state->insert_rs_byte = state->config.insert_rs_byte; 25658c2ecf20Sopenharmony_ci state->enable_parallel = (ulSerialMode != 1); 25668c2ecf20Sopenharmony_ci 25678c2ecf20Sopenharmony_ci /* Timing div, 250ns/Psys */ 25688c2ecf20Sopenharmony_ci /* Timing div, = ( delay (nano seconds) * sysclk (kHz) )/ 1000 */ 25698c2ecf20Sopenharmony_ci 25708c2ecf20Sopenharmony_ci state->hi_cfg_timing_div = (u16) ((state->sys_clock_freq / 1000) * 25718c2ecf20Sopenharmony_ci ulHiI2cDelay) / 1000; 25728c2ecf20Sopenharmony_ci /* Bridge delay, uses oscilator clock */ 25738c2ecf20Sopenharmony_ci /* Delay = ( delay (nano seconds) * oscclk (kHz) )/ 1000 */ 25748c2ecf20Sopenharmony_ci state->hi_cfg_bridge_delay = (u16) ((state->osc_clock_freq / 1000) * 25758c2ecf20Sopenharmony_ci ulHiI2cBridgeDelay) / 1000; 25768c2ecf20Sopenharmony_ci 25778c2ecf20Sopenharmony_ci state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER; 25788c2ecf20Sopenharmony_ci /* state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO; */ 25798c2ecf20Sopenharmony_ci state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO; 25808c2ecf20Sopenharmony_ci return 0; 25818c2ecf20Sopenharmony_ci} 25828c2ecf20Sopenharmony_ci 25838c2ecf20Sopenharmony_cistatic int DRXD_init(struct drxd_state *state, const u8 *fw, u32 fw_size) 25848c2ecf20Sopenharmony_ci{ 25858c2ecf20Sopenharmony_ci int status = 0; 25868c2ecf20Sopenharmony_ci u32 driverVersion; 25878c2ecf20Sopenharmony_ci 25888c2ecf20Sopenharmony_ci if (state->init_done) 25898c2ecf20Sopenharmony_ci return 0; 25908c2ecf20Sopenharmony_ci 25918c2ecf20Sopenharmony_ci CDRXD(state, state->config.IF ? state->config.IF : 36000000); 25928c2ecf20Sopenharmony_ci 25938c2ecf20Sopenharmony_ci do { 25948c2ecf20Sopenharmony_ci state->operation_mode = OM_Default; 25958c2ecf20Sopenharmony_ci 25968c2ecf20Sopenharmony_ci status = SetDeviceTypeId(state); 25978c2ecf20Sopenharmony_ci if (status < 0) 25988c2ecf20Sopenharmony_ci break; 25998c2ecf20Sopenharmony_ci 26008c2ecf20Sopenharmony_ci /* Apply I2c address patch to B1 */ 26018c2ecf20Sopenharmony_ci if (!state->type_A && state->m_HiI2cPatch) { 26028c2ecf20Sopenharmony_ci status = WriteTable(state, state->m_HiI2cPatch); 26038c2ecf20Sopenharmony_ci if (status < 0) 26048c2ecf20Sopenharmony_ci break; 26058c2ecf20Sopenharmony_ci } 26068c2ecf20Sopenharmony_ci 26078c2ecf20Sopenharmony_ci if (state->type_A) { 26088c2ecf20Sopenharmony_ci /* HI firmware patch for UIO readout, 26098c2ecf20Sopenharmony_ci avoid clearing of result register */ 26108c2ecf20Sopenharmony_ci status = Write16(state, 0x43012D, 0x047f, 0); 26118c2ecf20Sopenharmony_ci if (status < 0) 26128c2ecf20Sopenharmony_ci break; 26138c2ecf20Sopenharmony_ci } 26148c2ecf20Sopenharmony_ci 26158c2ecf20Sopenharmony_ci status = HI_ResetCommand(state); 26168c2ecf20Sopenharmony_ci if (status < 0) 26178c2ecf20Sopenharmony_ci break; 26188c2ecf20Sopenharmony_ci 26198c2ecf20Sopenharmony_ci status = StopAllProcessors(state); 26208c2ecf20Sopenharmony_ci if (status < 0) 26218c2ecf20Sopenharmony_ci break; 26228c2ecf20Sopenharmony_ci status = InitCC(state); 26238c2ecf20Sopenharmony_ci if (status < 0) 26248c2ecf20Sopenharmony_ci break; 26258c2ecf20Sopenharmony_ci 26268c2ecf20Sopenharmony_ci state->osc_clock_deviation = 0; 26278c2ecf20Sopenharmony_ci 26288c2ecf20Sopenharmony_ci if (state->config.osc_deviation) 26298c2ecf20Sopenharmony_ci state->osc_clock_deviation = 26308c2ecf20Sopenharmony_ci state->config.osc_deviation(state->priv, 0, 0); 26318c2ecf20Sopenharmony_ci { 26328c2ecf20Sopenharmony_ci /* Handle clock deviation */ 26338c2ecf20Sopenharmony_ci s32 devB; 26348c2ecf20Sopenharmony_ci s32 devA = (s32) (state->osc_clock_deviation) * 26358c2ecf20Sopenharmony_ci (s32) (state->expected_sys_clock_freq); 26368c2ecf20Sopenharmony_ci /* deviation in kHz */ 26378c2ecf20Sopenharmony_ci s32 deviation = (devA / (1000000L)); 26388c2ecf20Sopenharmony_ci /* rounding, signed */ 26398c2ecf20Sopenharmony_ci if (devA > 0) 26408c2ecf20Sopenharmony_ci devB = (2); 26418c2ecf20Sopenharmony_ci else 26428c2ecf20Sopenharmony_ci devB = (-2); 26438c2ecf20Sopenharmony_ci if ((devB * (devA % 1000000L) > 1000000L)) { 26448c2ecf20Sopenharmony_ci /* add +1 or -1 */ 26458c2ecf20Sopenharmony_ci deviation += (devB / 2); 26468c2ecf20Sopenharmony_ci } 26478c2ecf20Sopenharmony_ci 26488c2ecf20Sopenharmony_ci state->sys_clock_freq = 26498c2ecf20Sopenharmony_ci (u16) ((state->expected_sys_clock_freq) + 26508c2ecf20Sopenharmony_ci deviation); 26518c2ecf20Sopenharmony_ci } 26528c2ecf20Sopenharmony_ci status = InitHI(state); 26538c2ecf20Sopenharmony_ci if (status < 0) 26548c2ecf20Sopenharmony_ci break; 26558c2ecf20Sopenharmony_ci status = InitAtomicRead(state); 26568c2ecf20Sopenharmony_ci if (status < 0) 26578c2ecf20Sopenharmony_ci break; 26588c2ecf20Sopenharmony_ci 26598c2ecf20Sopenharmony_ci status = EnableAndResetMB(state); 26608c2ecf20Sopenharmony_ci if (status < 0) 26618c2ecf20Sopenharmony_ci break; 26628c2ecf20Sopenharmony_ci if (state->type_A) { 26638c2ecf20Sopenharmony_ci status = ResetCEFR(state); 26648c2ecf20Sopenharmony_ci if (status < 0) 26658c2ecf20Sopenharmony_ci break; 26668c2ecf20Sopenharmony_ci } 26678c2ecf20Sopenharmony_ci if (fw) { 26688c2ecf20Sopenharmony_ci status = DownloadMicrocode(state, fw, fw_size); 26698c2ecf20Sopenharmony_ci if (status < 0) 26708c2ecf20Sopenharmony_ci break; 26718c2ecf20Sopenharmony_ci } else { 26728c2ecf20Sopenharmony_ci status = DownloadMicrocode(state, state->microcode, state->microcode_length); 26738c2ecf20Sopenharmony_ci if (status < 0) 26748c2ecf20Sopenharmony_ci break; 26758c2ecf20Sopenharmony_ci } 26768c2ecf20Sopenharmony_ci 26778c2ecf20Sopenharmony_ci if (state->PGA) { 26788c2ecf20Sopenharmony_ci state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO; 26798c2ecf20Sopenharmony_ci SetCfgPga(state, 0); /* PGA = 0 dB */ 26808c2ecf20Sopenharmony_ci } else { 26818c2ecf20Sopenharmony_ci state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER; 26828c2ecf20Sopenharmony_ci } 26838c2ecf20Sopenharmony_ci 26848c2ecf20Sopenharmony_ci state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO; 26858c2ecf20Sopenharmony_ci 26868c2ecf20Sopenharmony_ci status = InitFE(state); 26878c2ecf20Sopenharmony_ci if (status < 0) 26888c2ecf20Sopenharmony_ci break; 26898c2ecf20Sopenharmony_ci status = InitFT(state); 26908c2ecf20Sopenharmony_ci if (status < 0) 26918c2ecf20Sopenharmony_ci break; 26928c2ecf20Sopenharmony_ci status = InitCP(state); 26938c2ecf20Sopenharmony_ci if (status < 0) 26948c2ecf20Sopenharmony_ci break; 26958c2ecf20Sopenharmony_ci status = InitCE(state); 26968c2ecf20Sopenharmony_ci if (status < 0) 26978c2ecf20Sopenharmony_ci break; 26988c2ecf20Sopenharmony_ci status = InitEQ(state); 26998c2ecf20Sopenharmony_ci if (status < 0) 27008c2ecf20Sopenharmony_ci break; 27018c2ecf20Sopenharmony_ci status = InitEC(state); 27028c2ecf20Sopenharmony_ci if (status < 0) 27038c2ecf20Sopenharmony_ci break; 27048c2ecf20Sopenharmony_ci status = InitSC(state); 27058c2ecf20Sopenharmony_ci if (status < 0) 27068c2ecf20Sopenharmony_ci break; 27078c2ecf20Sopenharmony_ci 27088c2ecf20Sopenharmony_ci status = SetCfgIfAgc(state, &state->if_agc_cfg); 27098c2ecf20Sopenharmony_ci if (status < 0) 27108c2ecf20Sopenharmony_ci break; 27118c2ecf20Sopenharmony_ci status = SetCfgRfAgc(state, &state->rf_agc_cfg); 27128c2ecf20Sopenharmony_ci if (status < 0) 27138c2ecf20Sopenharmony_ci break; 27148c2ecf20Sopenharmony_ci 27158c2ecf20Sopenharmony_ci state->cscd_state = CSCD_INIT; 27168c2ecf20Sopenharmony_ci status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 27178c2ecf20Sopenharmony_ci if (status < 0) 27188c2ecf20Sopenharmony_ci break; 27198c2ecf20Sopenharmony_ci status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); 27208c2ecf20Sopenharmony_ci if (status < 0) 27218c2ecf20Sopenharmony_ci break; 27228c2ecf20Sopenharmony_ci 27238c2ecf20Sopenharmony_ci driverVersion = (((VERSION_MAJOR / 10) << 4) + 27248c2ecf20Sopenharmony_ci (VERSION_MAJOR % 10)) << 24; 27258c2ecf20Sopenharmony_ci driverVersion += (((VERSION_MINOR / 10) << 4) + 27268c2ecf20Sopenharmony_ci (VERSION_MINOR % 10)) << 16; 27278c2ecf20Sopenharmony_ci driverVersion += ((VERSION_PATCH / 1000) << 12) + 27288c2ecf20Sopenharmony_ci ((VERSION_PATCH / 100) << 8) + 27298c2ecf20Sopenharmony_ci ((VERSION_PATCH / 10) << 4) + (VERSION_PATCH % 10); 27308c2ecf20Sopenharmony_ci 27318c2ecf20Sopenharmony_ci status = Write32(state, SC_RA_RAM_DRIVER_VERSION__AX, driverVersion, 0); 27328c2ecf20Sopenharmony_ci if (status < 0) 27338c2ecf20Sopenharmony_ci break; 27348c2ecf20Sopenharmony_ci 27358c2ecf20Sopenharmony_ci status = StopOC(state); 27368c2ecf20Sopenharmony_ci if (status < 0) 27378c2ecf20Sopenharmony_ci break; 27388c2ecf20Sopenharmony_ci 27398c2ecf20Sopenharmony_ci state->drxd_state = DRXD_STOPPED; 27408c2ecf20Sopenharmony_ci state->init_done = 1; 27418c2ecf20Sopenharmony_ci status = 0; 27428c2ecf20Sopenharmony_ci } while (0); 27438c2ecf20Sopenharmony_ci return status; 27448c2ecf20Sopenharmony_ci} 27458c2ecf20Sopenharmony_ci 27468c2ecf20Sopenharmony_cistatic int DRXD_status(struct drxd_state *state, u32 *pLockStatus) 27478c2ecf20Sopenharmony_ci{ 27488c2ecf20Sopenharmony_ci DRX_GetLockStatus(state, pLockStatus); 27498c2ecf20Sopenharmony_ci 27508c2ecf20Sopenharmony_ci /*if (*pLockStatus&DRX_LOCK_MPEG) */ 27518c2ecf20Sopenharmony_ci if (*pLockStatus & DRX_LOCK_FEC) { 27528c2ecf20Sopenharmony_ci ConfigureMPEGOutput(state, 1); 27538c2ecf20Sopenharmony_ci /* Get status again, in case we have MPEG lock now */ 27548c2ecf20Sopenharmony_ci /*DRX_GetLockStatus(state, pLockStatus); */ 27558c2ecf20Sopenharmony_ci } 27568c2ecf20Sopenharmony_ci 27578c2ecf20Sopenharmony_ci return 0; 27588c2ecf20Sopenharmony_ci} 27598c2ecf20Sopenharmony_ci 27608c2ecf20Sopenharmony_ci/****************************************************************************/ 27618c2ecf20Sopenharmony_ci/****************************************************************************/ 27628c2ecf20Sopenharmony_ci/****************************************************************************/ 27638c2ecf20Sopenharmony_ci 27648c2ecf20Sopenharmony_cistatic int drxd_read_signal_strength(struct dvb_frontend *fe, u16 * strength) 27658c2ecf20Sopenharmony_ci{ 27668c2ecf20Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 27678c2ecf20Sopenharmony_ci u32 value; 27688c2ecf20Sopenharmony_ci int res; 27698c2ecf20Sopenharmony_ci 27708c2ecf20Sopenharmony_ci res = ReadIFAgc(state, &value); 27718c2ecf20Sopenharmony_ci if (res < 0) 27728c2ecf20Sopenharmony_ci *strength = 0; 27738c2ecf20Sopenharmony_ci else 27748c2ecf20Sopenharmony_ci *strength = 0xffff - (value << 4); 27758c2ecf20Sopenharmony_ci return 0; 27768c2ecf20Sopenharmony_ci} 27778c2ecf20Sopenharmony_ci 27788c2ecf20Sopenharmony_cistatic int drxd_read_status(struct dvb_frontend *fe, enum fe_status *status) 27798c2ecf20Sopenharmony_ci{ 27808c2ecf20Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 27818c2ecf20Sopenharmony_ci u32 lock; 27828c2ecf20Sopenharmony_ci 27838c2ecf20Sopenharmony_ci DRXD_status(state, &lock); 27848c2ecf20Sopenharmony_ci *status = 0; 27858c2ecf20Sopenharmony_ci /* No MPEG lock in V255 firmware, bug ? */ 27868c2ecf20Sopenharmony_ci#if 1 27878c2ecf20Sopenharmony_ci if (lock & DRX_LOCK_MPEG) 27888c2ecf20Sopenharmony_ci *status |= FE_HAS_LOCK; 27898c2ecf20Sopenharmony_ci#else 27908c2ecf20Sopenharmony_ci if (lock & DRX_LOCK_FEC) 27918c2ecf20Sopenharmony_ci *status |= FE_HAS_LOCK; 27928c2ecf20Sopenharmony_ci#endif 27938c2ecf20Sopenharmony_ci if (lock & DRX_LOCK_FEC) 27948c2ecf20Sopenharmony_ci *status |= FE_HAS_VITERBI | FE_HAS_SYNC; 27958c2ecf20Sopenharmony_ci if (lock & DRX_LOCK_DEMOD) 27968c2ecf20Sopenharmony_ci *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; 27978c2ecf20Sopenharmony_ci 27988c2ecf20Sopenharmony_ci return 0; 27998c2ecf20Sopenharmony_ci} 28008c2ecf20Sopenharmony_ci 28018c2ecf20Sopenharmony_cistatic int drxd_init(struct dvb_frontend *fe) 28028c2ecf20Sopenharmony_ci{ 28038c2ecf20Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 28048c2ecf20Sopenharmony_ci 28058c2ecf20Sopenharmony_ci return DRXD_init(state, NULL, 0); 28068c2ecf20Sopenharmony_ci} 28078c2ecf20Sopenharmony_ci 28088c2ecf20Sopenharmony_cistatic int drxd_config_i2c(struct dvb_frontend *fe, int onoff) 28098c2ecf20Sopenharmony_ci{ 28108c2ecf20Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_ci if (state->config.disable_i2c_gate_ctrl == 1) 28138c2ecf20Sopenharmony_ci return 0; 28148c2ecf20Sopenharmony_ci 28158c2ecf20Sopenharmony_ci return DRX_ConfigureI2CBridge(state, onoff); 28168c2ecf20Sopenharmony_ci} 28178c2ecf20Sopenharmony_ci 28188c2ecf20Sopenharmony_cistatic int drxd_get_tune_settings(struct dvb_frontend *fe, 28198c2ecf20Sopenharmony_ci struct dvb_frontend_tune_settings *sets) 28208c2ecf20Sopenharmony_ci{ 28218c2ecf20Sopenharmony_ci sets->min_delay_ms = 10000; 28228c2ecf20Sopenharmony_ci sets->max_drift = 0; 28238c2ecf20Sopenharmony_ci sets->step_size = 0; 28248c2ecf20Sopenharmony_ci return 0; 28258c2ecf20Sopenharmony_ci} 28268c2ecf20Sopenharmony_ci 28278c2ecf20Sopenharmony_cistatic int drxd_read_ber(struct dvb_frontend *fe, u32 * ber) 28288c2ecf20Sopenharmony_ci{ 28298c2ecf20Sopenharmony_ci *ber = 0; 28308c2ecf20Sopenharmony_ci return 0; 28318c2ecf20Sopenharmony_ci} 28328c2ecf20Sopenharmony_ci 28338c2ecf20Sopenharmony_cistatic int drxd_read_snr(struct dvb_frontend *fe, u16 * snr) 28348c2ecf20Sopenharmony_ci{ 28358c2ecf20Sopenharmony_ci *snr = 0; 28368c2ecf20Sopenharmony_ci return 0; 28378c2ecf20Sopenharmony_ci} 28388c2ecf20Sopenharmony_ci 28398c2ecf20Sopenharmony_cistatic int drxd_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) 28408c2ecf20Sopenharmony_ci{ 28418c2ecf20Sopenharmony_ci *ucblocks = 0; 28428c2ecf20Sopenharmony_ci return 0; 28438c2ecf20Sopenharmony_ci} 28448c2ecf20Sopenharmony_ci 28458c2ecf20Sopenharmony_cistatic int drxd_sleep(struct dvb_frontend *fe) 28468c2ecf20Sopenharmony_ci{ 28478c2ecf20Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 28488c2ecf20Sopenharmony_ci 28498c2ecf20Sopenharmony_ci ConfigureMPEGOutput(state, 0); 28508c2ecf20Sopenharmony_ci return 0; 28518c2ecf20Sopenharmony_ci} 28528c2ecf20Sopenharmony_ci 28538c2ecf20Sopenharmony_cistatic int drxd_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 28548c2ecf20Sopenharmony_ci{ 28558c2ecf20Sopenharmony_ci return drxd_config_i2c(fe, enable); 28568c2ecf20Sopenharmony_ci} 28578c2ecf20Sopenharmony_ci 28588c2ecf20Sopenharmony_cistatic int drxd_set_frontend(struct dvb_frontend *fe) 28598c2ecf20Sopenharmony_ci{ 28608c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 28618c2ecf20Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 28628c2ecf20Sopenharmony_ci s32 off = 0; 28638c2ecf20Sopenharmony_ci 28648c2ecf20Sopenharmony_ci state->props = *p; 28658c2ecf20Sopenharmony_ci DRX_Stop(state); 28668c2ecf20Sopenharmony_ci 28678c2ecf20Sopenharmony_ci if (fe->ops.tuner_ops.set_params) { 28688c2ecf20Sopenharmony_ci fe->ops.tuner_ops.set_params(fe); 28698c2ecf20Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 28708c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 0); 28718c2ecf20Sopenharmony_ci } 28728c2ecf20Sopenharmony_ci 28738c2ecf20Sopenharmony_ci msleep(200); 28748c2ecf20Sopenharmony_ci 28758c2ecf20Sopenharmony_ci return DRX_Start(state, off); 28768c2ecf20Sopenharmony_ci} 28778c2ecf20Sopenharmony_ci 28788c2ecf20Sopenharmony_cistatic void drxd_release(struct dvb_frontend *fe) 28798c2ecf20Sopenharmony_ci{ 28808c2ecf20Sopenharmony_ci struct drxd_state *state = fe->demodulator_priv; 28818c2ecf20Sopenharmony_ci 28828c2ecf20Sopenharmony_ci kfree(state); 28838c2ecf20Sopenharmony_ci} 28848c2ecf20Sopenharmony_ci 28858c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops drxd_ops = { 28868c2ecf20Sopenharmony_ci .delsys = { SYS_DVBT}, 28878c2ecf20Sopenharmony_ci .info = { 28888c2ecf20Sopenharmony_ci .name = "Micronas DRXD DVB-T", 28898c2ecf20Sopenharmony_ci .frequency_min_hz = 47125 * kHz, 28908c2ecf20Sopenharmony_ci .frequency_max_hz = 855250 * kHz, 28918c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 166667, 28928c2ecf20Sopenharmony_ci .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | 28938c2ecf20Sopenharmony_ci FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | 28948c2ecf20Sopenharmony_ci FE_CAN_FEC_AUTO | 28958c2ecf20Sopenharmony_ci FE_CAN_QAM_16 | FE_CAN_QAM_64 | 28968c2ecf20Sopenharmony_ci FE_CAN_QAM_AUTO | 28978c2ecf20Sopenharmony_ci FE_CAN_TRANSMISSION_MODE_AUTO | 28988c2ecf20Sopenharmony_ci FE_CAN_GUARD_INTERVAL_AUTO | 28998c2ecf20Sopenharmony_ci FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS}, 29008c2ecf20Sopenharmony_ci 29018c2ecf20Sopenharmony_ci .release = drxd_release, 29028c2ecf20Sopenharmony_ci .init = drxd_init, 29038c2ecf20Sopenharmony_ci .sleep = drxd_sleep, 29048c2ecf20Sopenharmony_ci .i2c_gate_ctrl = drxd_i2c_gate_ctrl, 29058c2ecf20Sopenharmony_ci 29068c2ecf20Sopenharmony_ci .set_frontend = drxd_set_frontend, 29078c2ecf20Sopenharmony_ci .get_tune_settings = drxd_get_tune_settings, 29088c2ecf20Sopenharmony_ci 29098c2ecf20Sopenharmony_ci .read_status = drxd_read_status, 29108c2ecf20Sopenharmony_ci .read_ber = drxd_read_ber, 29118c2ecf20Sopenharmony_ci .read_signal_strength = drxd_read_signal_strength, 29128c2ecf20Sopenharmony_ci .read_snr = drxd_read_snr, 29138c2ecf20Sopenharmony_ci .read_ucblocks = drxd_read_ucblocks, 29148c2ecf20Sopenharmony_ci}; 29158c2ecf20Sopenharmony_ci 29168c2ecf20Sopenharmony_cistruct dvb_frontend *drxd_attach(const struct drxd_config *config, 29178c2ecf20Sopenharmony_ci void *priv, struct i2c_adapter *i2c, 29188c2ecf20Sopenharmony_ci struct device *dev) 29198c2ecf20Sopenharmony_ci{ 29208c2ecf20Sopenharmony_ci struct drxd_state *state = NULL; 29218c2ecf20Sopenharmony_ci 29228c2ecf20Sopenharmony_ci state = kzalloc(sizeof(*state), GFP_KERNEL); 29238c2ecf20Sopenharmony_ci if (!state) 29248c2ecf20Sopenharmony_ci return NULL; 29258c2ecf20Sopenharmony_ci 29268c2ecf20Sopenharmony_ci state->ops = drxd_ops; 29278c2ecf20Sopenharmony_ci state->dev = dev; 29288c2ecf20Sopenharmony_ci state->config = *config; 29298c2ecf20Sopenharmony_ci state->i2c = i2c; 29308c2ecf20Sopenharmony_ci state->priv = priv; 29318c2ecf20Sopenharmony_ci 29328c2ecf20Sopenharmony_ci mutex_init(&state->mutex); 29338c2ecf20Sopenharmony_ci 29348c2ecf20Sopenharmony_ci if (Read16(state, 0, NULL, 0) < 0) 29358c2ecf20Sopenharmony_ci goto error; 29368c2ecf20Sopenharmony_ci 29378c2ecf20Sopenharmony_ci state->frontend.ops = drxd_ops; 29388c2ecf20Sopenharmony_ci state->frontend.demodulator_priv = state; 29398c2ecf20Sopenharmony_ci ConfigureMPEGOutput(state, 0); 29408c2ecf20Sopenharmony_ci /* add few initialization to allow gate control */ 29418c2ecf20Sopenharmony_ci CDRXD(state, state->config.IF ? state->config.IF : 36000000); 29428c2ecf20Sopenharmony_ci InitHI(state); 29438c2ecf20Sopenharmony_ci 29448c2ecf20Sopenharmony_ci return &state->frontend; 29458c2ecf20Sopenharmony_ci 29468c2ecf20Sopenharmony_cierror: 29478c2ecf20Sopenharmony_ci printk(KERN_ERR "drxd: not found\n"); 29488c2ecf20Sopenharmony_ci kfree(state); 29498c2ecf20Sopenharmony_ci return NULL; 29508c2ecf20Sopenharmony_ci} 29518c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(drxd_attach); 29528c2ecf20Sopenharmony_ci 29538c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("DRXD driver"); 29548c2ecf20Sopenharmony_ciMODULE_AUTHOR("Micronas"); 29558c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 2956