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