mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 04:33:26 +02:00
3262 lines
95 KiB
C
3262 lines
95 KiB
C
#include <linux/bitrev.h>
|
|
#include "r850.h"
|
|
#include "r850_priv.h"
|
|
|
|
static int r850_rd(struct r850_priv *priv,u8 reg, u8 *buf,u8 len)
|
|
{
|
|
int ret,i;
|
|
|
|
struct i2c_msg msg[2]={
|
|
{
|
|
.addr = priv->cfg->i2c_address,
|
|
.flags = 0, .buf = ®, .len = 1
|
|
},{
|
|
.addr = priv->cfg->i2c_address,
|
|
.flags = I2C_M_RD, .buf = buf, .len = len
|
|
}
|
|
};
|
|
ret = i2c_transfer(priv->i2c, msg, 2);
|
|
if (ret == 2) {
|
|
for (i = 0; i < len; i++)
|
|
buf[i] = bitrev8(buf[i]);
|
|
ret = 0;
|
|
} else {
|
|
dev_warn(&priv->i2c->dev, "%s: i2c tuner rd failed=%d " \
|
|
"len=%d\n", KBUILD_MODNAME, ret, len);
|
|
ret = -EREMOTEIO;
|
|
}
|
|
return ret;
|
|
|
|
}
|
|
static int r850_wrm(struct r850_priv *priv,u8 reg, u8 *val,u8 len)
|
|
{
|
|
int ret;
|
|
u8 buf[len + 1];
|
|
|
|
memcpy(&buf[1], val, len);
|
|
buf[0] = reg;
|
|
|
|
struct i2c_msg msg = {
|
|
.addr = priv->cfg->i2c_address,
|
|
.flags = 0, .buf = buf, .len = len + 1 };
|
|
|
|
|
|
ret = i2c_transfer(priv->i2c, &msg, 1);
|
|
if (ret == 1) {
|
|
ret = 0;
|
|
} else {
|
|
dev_warn(&priv->i2c->dev, "%s: i2c tuner wr failed=%d " \
|
|
"len=%d\n", KBUILD_MODNAME, ret, len);
|
|
ret = -EREMOTEIO;
|
|
}
|
|
return ret;
|
|
|
|
}
|
|
static int r850_wr(struct r850_priv *priv,u8 reg, u8 val)
|
|
{
|
|
return r850_wrm(priv,reg,&val,1);
|
|
}
|
|
struct R850_Freq_Info_Type R850_Freq_Sel(u32 LO_freq, u32 RF_freq, enum R850_Standard_Type R850_Standard)
|
|
{
|
|
struct R850_Freq_Info_Type R850_Freq_Info;
|
|
|
|
|
|
//----- LO dependent parameter --------
|
|
|
|
//IMR point
|
|
if((LO_freq>0) && (LO_freq<170000))
|
|
{
|
|
R850_Freq_Info.IMR_MEM_NOR = 0;
|
|
R850_Freq_Info.IMR_MEM_REV = 5;
|
|
}
|
|
else if((LO_freq>=170000) && (LO_freq<240000))
|
|
{
|
|
R850_Freq_Info.IMR_MEM_NOR = 4;
|
|
R850_Freq_Info.IMR_MEM_REV = 9;
|
|
}
|
|
else if((LO_freq>=240000) && (LO_freq<400000))
|
|
{
|
|
R850_Freq_Info.IMR_MEM_NOR = 1;
|
|
R850_Freq_Info.IMR_MEM_REV = 6;
|
|
}
|
|
else if((LO_freq>=400000) && (LO_freq<760000))
|
|
{
|
|
R850_Freq_Info.IMR_MEM_NOR = 2;
|
|
R850_Freq_Info.IMR_MEM_REV = 7;
|
|
}
|
|
else
|
|
{
|
|
R850_Freq_Info.IMR_MEM_NOR = 3;
|
|
R850_Freq_Info.IMR_MEM_REV = 8;
|
|
}
|
|
|
|
//TF_HPF_BPF R16[2:0]
|
|
/* 7-lowest:111 ; 6:011 ; 5:101 ; 4:001 ; 3:110 ; 2:010 ; 1:100 ; 0-noBPF:000 */
|
|
if(LO_freq<580000)
|
|
R850_Freq_Info.TF_HPF_BPF = 0x07; //7 => 111:lowset BPF R16[2:0]
|
|
else if(LO_freq>=580000 && LO_freq<660000)
|
|
R850_Freq_Info.TF_HPF_BPF = 0x01; //4 => 001
|
|
else if(LO_freq>=660000 && LO_freq<780000)
|
|
R850_Freq_Info.TF_HPF_BPF = 0x06; //3 => 110
|
|
else if(LO_freq>=780000 && LO_freq<900000)
|
|
R850_Freq_Info.TF_HPF_BPF = 0x04; //1 => 100
|
|
else
|
|
R850_Freq_Info.TF_HPF_BPF = 0x00; //0 => 000
|
|
|
|
/*
|
|
00: highest band
|
|
01: med band
|
|
10: low band
|
|
11: Ultrawide band
|
|
*/
|
|
//RF polyfilter band
|
|
if((LO_freq>0) && (LO_freq<133000))
|
|
R850_Freq_Info.RF_POLY = 2; //R17[6:5]=2; low => R18[1:0]
|
|
else if((LO_freq>=133000) && (LO_freq<221000))
|
|
R850_Freq_Info.RF_POLY = 1; //R17[6:5]=1; mid => R18[1:0]
|
|
else if((LO_freq>=221000) && (LO_freq<760000))
|
|
R850_Freq_Info.RF_POLY = 0; //R17[6:5]=0; highest => R18[1:0]
|
|
else
|
|
R850_Freq_Info.RF_POLY = 3; //R17[6:5]=3; ultra high => R18[1:0]
|
|
|
|
|
|
/*
|
|
00: highest
|
|
01: high
|
|
10: low
|
|
11: lowest
|
|
*/
|
|
//TF_HPF_Corner
|
|
if((LO_freq>0) && (LO_freq<480000))
|
|
R850_Freq_Info.TF_HPF_CNR = 3; //lowest => R16[4:3]
|
|
else if((LO_freq>=480000) && (LO_freq<550000))
|
|
R850_Freq_Info.TF_HPF_CNR = 2; // low => R16[4:3]
|
|
else if((LO_freq>=550000) && (LO_freq<700000))
|
|
R850_Freq_Info.TF_HPF_CNR = 1; // high => R16[4:3]
|
|
else
|
|
R850_Freq_Info.TF_HPF_CNR = 0; //highest => R16[4:3]
|
|
|
|
|
|
//LPF Cap, Notch
|
|
switch(R850_Standard)
|
|
{
|
|
case R850_DVB_C_8M: //Cable
|
|
case R850_DVB_C_6M:
|
|
case R850_J83B:
|
|
case R850_DVB_C_8M_IF_5M:
|
|
case R850_DVB_C_6M_IF_5M:
|
|
case R850_J83B_IF_5M:
|
|
if(LO_freq<77000)
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 15;
|
|
R850_Freq_Info.LPF_NOTCH = 10;
|
|
}
|
|
else if((LO_freq>=77000) && (LO_freq<85000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 15;
|
|
R850_Freq_Info.LPF_NOTCH = 4;
|
|
}
|
|
else if((LO_freq>=85000) && (LO_freq<115000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 13;
|
|
R850_Freq_Info.LPF_NOTCH = 3;
|
|
}
|
|
else if((LO_freq>=115000) && (LO_freq<125000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 11;
|
|
R850_Freq_Info.LPF_NOTCH = 1;
|
|
}
|
|
else if((LO_freq>=125000) && (LO_freq<141000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 9;
|
|
R850_Freq_Info.LPF_NOTCH = 0;
|
|
}
|
|
else if((LO_freq>=141000) && (LO_freq<157000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 8;
|
|
R850_Freq_Info.LPF_NOTCH = 0;
|
|
}
|
|
else if((LO_freq>=157000) && (LO_freq<181000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 6;
|
|
R850_Freq_Info.LPF_NOTCH = 0;
|
|
}
|
|
else if((LO_freq>=181000) && (LO_freq<205000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 3;
|
|
R850_Freq_Info.LPF_NOTCH = 0;
|
|
}
|
|
else //LO>=201M
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 0;
|
|
R850_Freq_Info.LPF_NOTCH = 0;
|
|
}
|
|
//Diplexer Select R14[3:2]
|
|
if(LO_freq<330000)
|
|
R850_Freq_Info.TF_DIPLEXER = 2; //LPF R14[3:2]
|
|
else
|
|
R850_Freq_Info.TF_DIPLEXER = 0; //HPF
|
|
|
|
|
|
break;
|
|
|
|
default: //Air, DTMB (for 180nH)
|
|
if((LO_freq>0) && (LO_freq<73000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 8;
|
|
R850_Freq_Info.LPF_NOTCH = 10;
|
|
}
|
|
else if((LO_freq>=73000) && (LO_freq<81000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 8;
|
|
R850_Freq_Info.LPF_NOTCH = 4;
|
|
}
|
|
else if((LO_freq>=81000) && (LO_freq<89000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 8;
|
|
R850_Freq_Info.LPF_NOTCH = 3;
|
|
}
|
|
else if((LO_freq>=89000) && (LO_freq<121000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 6;
|
|
R850_Freq_Info.LPF_NOTCH = 1;
|
|
}
|
|
else if((LO_freq>=121000) && (LO_freq<145000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 4;
|
|
R850_Freq_Info.LPF_NOTCH = 0;
|
|
}
|
|
else if((LO_freq>=145000) && (LO_freq<153000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 3;
|
|
R850_Freq_Info.LPF_NOTCH = 0;
|
|
}
|
|
else if((LO_freq>=153000) && (LO_freq<177000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 2;
|
|
R850_Freq_Info.LPF_NOTCH = 0;
|
|
}
|
|
else if((LO_freq>=177000) && (LO_freq<201000))
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 1;
|
|
R850_Freq_Info.LPF_NOTCH = 0;
|
|
}
|
|
else //LO>=201M
|
|
{
|
|
R850_Freq_Info.LPF_CAP = 0;
|
|
R850_Freq_Info.LPF_NOTCH = 0;
|
|
}
|
|
//Diplexer Select R14[3:2]
|
|
if(LO_freq<340000)
|
|
R850_Freq_Info.TF_DIPLEXER = 2; //LPF R14[3:2]
|
|
else
|
|
R850_Freq_Info.TF_DIPLEXER = 0; //HPF
|
|
break;
|
|
|
|
}//end switch(standard)
|
|
|
|
|
|
return R850_Freq_Info;
|
|
|
|
}
|
|
|
|
struct R850_SysFreq_Info_Type R850_SysFreq_NrbDetOn_Sel(enum R850_Standard_Type R850_Standard,u32 RF_freq)
|
|
{
|
|
|
|
struct R850_SysFreq_Info_Type R850_SysFreq_Info;
|
|
|
|
switch(R850_Standard)
|
|
{
|
|
case R850_DTMB_8M_4570:
|
|
case R850_DTMB_6M_4500:
|
|
case R850_DTMB_8M_IF_5M:
|
|
case R850_DTMB_6M_IF_5M:
|
|
if(RF_freq<=100000)
|
|
{
|
|
//LNA
|
|
R850_SysFreq_Info.LNA_VTL_H=0x6B; //R39[7:0] LNA VTL/H = 0.94(6) / 1.44(B)
|
|
|
|
//NRB
|
|
R850_SysFreq_Info.NRB_TOP=10; //R40[7:4] ["15-highest ~ 0-lowest" (0~15) ; input: "15~0"]
|
|
R850_SysFreq_Info.NRB_BW_LPF=3; //R26[7:6] [widest (0), wide (1), low (2), lowest (3)]
|
|
R850_SysFreq_Info.NRB_BW_HPF=3; //R26[3:2] [lowest (0), low (1), high (2), highest (3)]
|
|
R850_SysFreq_Info.IMG_NRB_ADDER=1; //R46[3:2] ["original" (0), "top+6" (1), "top+9" (2), "top+11" (3)]
|
|
|
|
//Filter
|
|
R850_SysFreq_Info.FILT_3TH_LPF_GAIN=0; //R24[1:0] [normal (0), +1.5dB (1), +3dB (2), +4.5dB (3)]
|
|
}
|
|
else if(RF_freq<=340000)
|
|
{
|
|
//LNA
|
|
R850_SysFreq_Info.LNA_VTL_H=0x6B; //R39[7:0] LNA VTL/H = 0.94(6) / 1.44(B)
|
|
|
|
//NRB
|
|
R850_SysFreq_Info.NRB_TOP=10; //R40[7:4] ["15-highest ~ 0-lowest" (0~15) ; input: "15~0"]
|
|
R850_SysFreq_Info.NRB_BW_LPF=2; //R26[7:6] [widest (0), wide (1), low (2), lowest (3)]
|
|
R850_SysFreq_Info.NRB_BW_HPF=3; //R26[3:2] [lowest (0), low (1), high (2), highest (3)]
|
|
R850_SysFreq_Info.IMG_NRB_ADDER=1; //R46[3:2] ["original" (0), "top+6" (1), "top+9" (2), "top+11" (3)]
|
|
|
|
//Filter
|
|
R850_SysFreq_Info.FILT_3TH_LPF_GAIN=0; //R24[1:0] [normal (0), +1.5dB (1), +3dB (2), +4.5dB (3)]
|
|
}
|
|
else
|
|
{
|
|
//LNA
|
|
R850_SysFreq_Info.LNA_VTL_H=0x5A; //R39[7:0] LNA VTL/H = 0.84(5) / 1.34(A)
|
|
|
|
//NRB
|
|
R850_SysFreq_Info.NRB_TOP=6; //R40[7:4] ["15-highest ~ 0-lowest" (0~15) ; input: "15~0"]
|
|
R850_SysFreq_Info.NRB_BW_LPF=2; //R26[7:6] [widest (0), wide (1), low (2), lowest (3)]
|
|
R850_SysFreq_Info.NRB_BW_HPF=2; //R26[3:2] [lowest (0), low (1), high (2), highest (3)]
|
|
R850_SysFreq_Info.IMG_NRB_ADDER=0; //R46[3:2] ["original" (0), "top+6" (1), "top+9" (2), "top+11" (3)]
|
|
|
|
//Filter
|
|
R850_SysFreq_Info.FILT_3TH_LPF_GAIN=3; //R24[1:0] [normal (0), +1.5dB (1), +3dB (2), +4.5dB (3)]
|
|
}
|
|
|
|
//PW
|
|
R850_SysFreq_Info.NA_PWR_DET = 0; //R10[6] ["off" (0), "on" (1)]
|
|
R850_SysFreq_Info.LNA_NRB_DET=0; //R11[7] ["on" (0), "off" (1)]
|
|
|
|
//LNA
|
|
R850_SysFreq_Info.LNA_TOP=4; //R38[2:0] ["7~0" (0~7) ; input: "7~0"]
|
|
R850_SysFreq_Info.RF_LTE_PSG=1; //R17[4] ["no psg" (0), "7.5dB(5~8)" (1)]
|
|
|
|
|
|
//RFBuf
|
|
R850_SysFreq_Info.RF_TOP=4; //R38[6:4] ["7~0" (0~7) ; input: "7~0"]
|
|
R850_SysFreq_Info.RF_VTL_H=0x4A; //R42[7:0] RF VTL/H = 0.74(4) / 1.34(A)
|
|
R850_SysFreq_Info.RF_GAIN_LIMIT=0; //MSB R18[2], LSB R16[6] ["max =15" (0), "max =11" (1), "max =13" (2), "max =9" (3)]
|
|
|
|
//Mixer and Mixamp
|
|
R850_SysFreq_Info.MIXER_AMP_LPF = 4; //R19[2:0] ["normal (widest)" (0), "1" (1), "2" (2), "3" (3), "4" (4), "5" (5), "6" (6), "narrowest" (7)]
|
|
R850_SysFreq_Info.MIXER_TOP=9; //R40[3:0] ["15-highest ~ 0-lowest" (0~15) ; input: "15~0"]
|
|
R850_SysFreq_Info.MIXER_VTH=0x09; //R41[3:0] 1.24 (9)
|
|
R850_SysFreq_Info.MIXER_VTL=0x04; //R43[3:0] 0.74 (4)
|
|
R850_SysFreq_Info.MIXER_GAIN_LIMIT=1; //R22[7:6] ["max=6" (0), "max=8" (1), "max=10" (2), "max=12" (3)]
|
|
R850_SysFreq_Info.MIXER_DETBW_LPF =0; //R46[7] ["normal" (0), "enhance amp det LPF" (1)]
|
|
|
|
//Filter
|
|
R850_SysFreq_Info.FILTER_TOP=4; //R44[3:0] ["15-highest ~ 0-lowest" (0~15) ; input: "15~0"]
|
|
R850_SysFreq_Info.FILTER_VTH=0x90; //R41[7:4] 1.24 (9)
|
|
R850_SysFreq_Info.FILTER_VTL=0x40; //R43[7:4] 0.74 (4)
|
|
R850_SysFreq_Info.FILT_3TH_LPF_CUR=0; //R10[4] [high (0), low (1)]
|
|
|
|
|
|
//Discharge
|
|
R850_SysFreq_Info.LNA_RF_DIS_MODE=1; //Both (fast+slow) (R45[1:0]=0'b00; R31[0]=1 ;R32[5]=1) : 1111 Both (fast+slow) case 1
|
|
R850_SysFreq_Info.LNA_RF_CHARGE_CUR=1; //R31[1] ["6x chargeI" (0), "4x chargeI" (1)]
|
|
R850_SysFreq_Info.LNA_RF_DIS_CURR=1; //R13[5] ["1/3 dis current" (0), "normal" (1)]
|
|
R850_SysFreq_Info.RF_DIS_SLOW_FAST=5; //R45[7:4] 0.3u (1) / 0.9u (4)
|
|
R850_SysFreq_Info.LNA_DIS_SLOW_FAST=9; //R44[7:4] 0.3u (1) / 1.5u (8) => 1 + 8 = 9
|
|
R850_SysFreq_Info.BB_DIS_CURR=0; //R25[6] ["x1" (0) , "x1/2" (1)]
|
|
R850_SysFreq_Info.MIXER_FILTER_DIS=2; //R37[7:6] ["highest" (0), "high" (1), "low" (2), "lowest" (3)]
|
|
R850_SysFreq_Info.BB_DET_MODE=0; //R37[2] ["peak" (0), "average" (1)]
|
|
|
|
//Polyphase
|
|
R850_SysFreq_Info.ENB_POLY_GAIN=0; //R25[1]=0 original ["original" (0), "ctrl by mixamp (>10)" (1)]
|
|
|
|
//VGA
|
|
R850_SysFreq_Info.HPF_COMP=0; //R13[2:1] ["normal" (0) , "+1.5dB" (1), "+3dB" (2), "+4dB" (3)]
|
|
R850_SysFreq_Info.FB_RES_1ST=0; //R21[4] ["2K" (0) , "8K" (1)]
|
|
|
|
break;
|
|
|
|
default: //DVB-T
|
|
//PW
|
|
R850_SysFreq_Info.NA_PWR_DET = 0; //R10[6] ["off" (0), "on" (1)]
|
|
R850_SysFreq_Info.LNA_NRB_DET=0; //R11[7] ["on" (0), "off" (1)]
|
|
|
|
//LNA
|
|
R850_SysFreq_Info.LNA_TOP=4; //R38[2:0] ["7~0" (0~7) ; input: "7~0"]
|
|
R850_SysFreq_Info.LNA_VTL_H=0x5A; //R39[7:0] LNA VTL/H = 0.84(5) / 1.34(A)
|
|
R850_SysFreq_Info.RF_LTE_PSG=1; //R17[4] ["no psg" (0), "7.5dB(5~8)" (1)]
|
|
|
|
|
|
//RFBuf
|
|
R850_SysFreq_Info.RF_TOP=4; //R38[6:4] ["7~0" (0~7) ; input: "7~0"]
|
|
R850_SysFreq_Info.RF_VTL_H=0x4A; //R42[7:0] RF VTL/H = 0.74(4) / 1.34(A)
|
|
R850_SysFreq_Info.RF_GAIN_LIMIT=0; //MSB R18[2], LSB R16[6] ["max =15" (0), "max =11" (1), "max =13" (2), "max =9" (3)]
|
|
|
|
//Mixer and Mixamp
|
|
R850_SysFreq_Info.MIXER_AMP_LPF = 4; //R19[2:0] ["normal (widest)" (0), "1" (1), "2" (2), "3" (3), "4" (4), "5" (5), "6" (6), "narrowest" (7)]
|
|
R850_SysFreq_Info.MIXER_TOP=9; //R40[3:0] ["15-highest ~ 0-lowest" (0~15) ; input: "15~0"]
|
|
R850_SysFreq_Info.MIXER_VTH=0x09; //R41[3:0] 1.24 (9)
|
|
R850_SysFreq_Info.MIXER_VTL=0x04; //R43[3:0] 0.74 (4)
|
|
R850_SysFreq_Info.MIXER_GAIN_LIMIT=3; //R22[7:6] ["max=6" (0), "max=8" (1), "max=10" (2), "max=12" (3)]
|
|
R850_SysFreq_Info.MIXER_DETBW_LPF =0; //R46[7] ["normal" (0), "enhance amp det LPF" (1)]
|
|
|
|
|
|
//Filter
|
|
R850_SysFreq_Info.FILTER_TOP=4; //R44[3:0] ["15-highest ~ 0-lowest" (0~15) ; input: "15~0"]
|
|
R850_SysFreq_Info.FILTER_VTH=0x90; //R41[7:4] 1.24 (9)
|
|
R850_SysFreq_Info.FILTER_VTL=0x40; //R43[7:4] 0.74 (4)
|
|
R850_SysFreq_Info.FILT_3TH_LPF_CUR=1; //R10[4] [high (0), low (1)]
|
|
R850_SysFreq_Info.FILT_3TH_LPF_GAIN=3; //R24[1:0] [normal (0), +1.5dB (1), +3dB (2), +4.5dB (3)]
|
|
|
|
//Discharge
|
|
R850_SysFreq_Info.LNA_RF_DIS_MODE=1; //Both (fast+slow) (R45[1:0]=0'b00; R31[0]=1 ;R32[5]=1) : 1111 Both (fast+slow) case 1
|
|
R850_SysFreq_Info.LNA_RF_CHARGE_CUR=1; //R31[1] ["6x chargeI" (0), "4x chargeI" (1)]
|
|
R850_SysFreq_Info.LNA_RF_DIS_CURR=1; //R13[5] ["1/3 dis current" (0), "normal" (1)]
|
|
R850_SysFreq_Info.RF_DIS_SLOW_FAST=5; //R45[7:4] 0.3u (1) / 0.9u (4)
|
|
R850_SysFreq_Info.LNA_DIS_SLOW_FAST=9; //R44[7:4] 0.3u (1) / 1.5u (8) => 1 + 8 = 9
|
|
R850_SysFreq_Info.BB_DIS_CURR=0; //R25[6] ["x1" (0) , "x1/2" (1)]
|
|
R850_SysFreq_Info.MIXER_FILTER_DIS=2; //R37[7:6] ["highest" (0), "high" (1), "low" (2), "lowest" (3)]
|
|
R850_SysFreq_Info.BB_DET_MODE=0; //R37[2] ["peak" (0), "average" (1)]
|
|
|
|
//Polyphase
|
|
R850_SysFreq_Info.ENB_POLY_GAIN=0; //R25[1]=0 original ["original" (0), "ctrl by mixamp (>10)" (1)]
|
|
|
|
//NRB
|
|
R850_SysFreq_Info.NRB_TOP=4; //R40[7:4] ["15-highest ~ 0-lowest" (0~15) ; input: "15~0"]
|
|
R850_SysFreq_Info.NRB_BW_HPF=0; //R26[3:2] [lowest (0), low (1), high (2), highest (3)]
|
|
R850_SysFreq_Info.NRB_BW_LPF=2; //R26[7:6] [widest (0), wide (1), low (2), lowest (3)]
|
|
R850_SysFreq_Info.IMG_NRB_ADDER=2; //R46[3:2] ["original" (0), "top+6" (1), "top+9" (2), "top+11" (3)]
|
|
|
|
//VGA
|
|
R850_SysFreq_Info.HPF_COMP=1; //R13[2:1] ["normal" (0) , "+1.5dB" (1), "+3dB" (2), "+4dB" (3)]
|
|
R850_SysFreq_Info.FB_RES_1ST=1; //R21[4] ["2K" (0) , "8K" (1)]
|
|
break;
|
|
|
|
} //end switch
|
|
|
|
|
|
R850_SysFreq_Info.DEGLITCH_CLK = 1; //R38[3] ["500Hz"(0), "1KHz"(1)]
|
|
//R850_SysFreq_Info.LNA_RF_DIS_MODE =1; //Both (fast+slow) (R45[1:0]=0'b00; R31[0]=1 ;R32[5]=1) : 1111 Both (fast+slow) case 1
|
|
//R850_SysFreq_Info.LNA_DIS_SLOW_FAST &= 0x03;
|
|
//R850_SysFreq_Info.LNA_DIS_SLOW_FAST += 8; //R44[7:6] R45[7:6] ["0.6u" (0), "0.9u" (4), "1.5u" (8), "2.4u" (12)]
|
|
R850_SysFreq_Info.NAT_HYS = 1; //R35[6] ["no hys"(0) , "-6.5dB hys"(1)]
|
|
R850_SysFreq_Info.NAT_CAIN = 2; //R31[4:5] ["max-17dB"(0) , "max-11dB"(1), "max-6dB"(2), "max"(3)]
|
|
R850_SysFreq_Info.PULSE_HYS = 1; //R26[1:0] ["1.0V"(0), "0.8V"(1), "0.6V"(2), "0.4V"(3)]
|
|
R850_SysFreq_Info.FAST_DEGLITCH = 1; //R36[3:2] ["70ms"(0), "45ms"(1), "20ms"(2), "10ms"(3)]
|
|
R850_SysFreq_Info.PUL_RANGE_SEL = 0; //R31[2] ["0"(0), "1"(1)]
|
|
R850_SysFreq_Info.PUL_FLAG_RANGE = 3; //R35[1:0] ["0~14"(0), "1~14"(1), "2~14"(2), "3~14"(3)]
|
|
R850_SysFreq_Info.PULG_CNT_THRE = 1; //R17[1] ["threshold =14"(0), "threshold =15"(1)]
|
|
R850_SysFreq_Info.FORCE_PULSE = 1; //R46[5] ["pul_flag=0"(0), "auto"(1)]
|
|
R850_SysFreq_Info.FLG_CNT_CLK = 1; //R47[7:6] ["0.25Sec"(0), "0.5Sec"(1), "1Sec"(2), "2Sec"(3)]
|
|
R850_SysFreq_Info.NATG_OFFSET = 0; //R36[5:4] ["-6dB"(0), "-3dB"(1), "Normal"(2), "3dB"(3)]
|
|
|
|
|
|
return R850_SysFreq_Info;
|
|
|
|
}
|
|
//-----------------------------------------------------------------------------------/
|
|
// Purpose: read multiple IMR results for stability
|
|
// input: IMR_Reg: IMR result address
|
|
// IMR_Result_Data: result
|
|
// output: TRUE or FALSE
|
|
//-----------------------------------------------------------------------------------/
|
|
R850_ErrCode R850_Muti_Read( struct r850_priv*priv, u8* IMR_Result_Data) //ok
|
|
{
|
|
int ret = 0;
|
|
u8 buf[2];
|
|
|
|
|
|
msleep(2);//2 //R850_ADC_READ_DELAY = 2;
|
|
|
|
ret = r850_rd(priv,0x00,buf,2);
|
|
if(ret!=0){
|
|
*IMR_Result_Data = 0;
|
|
return R850_Fail;
|
|
}
|
|
*IMR_Result_Data = buf[1] & 0x3F;
|
|
|
|
return R850_Success;
|
|
}
|
|
R850_ErrCode R850_SetXtalCap(struct r850_priv *priv,u8 u8XtalCap)
|
|
{
|
|
u8 XtalCap;
|
|
u8 Capx;
|
|
u8 Capx_3_0, Capxx;
|
|
|
|
if(u8XtalCap>31)
|
|
{
|
|
XtalCap = 1; //10
|
|
Capx = u8XtalCap-10;
|
|
}
|
|
else
|
|
{
|
|
XtalCap = 0; //0
|
|
Capx = u8XtalCap;
|
|
}
|
|
|
|
Capxx = Capx & 0x01;
|
|
Capx_3_0 = Capx >> 1;
|
|
|
|
// Set Xtal Cap R33[6:3], R34[3] XtalCap => R33[7]
|
|
|
|
priv->regs[33] = (priv->regs[33 ] & 0x07) | (Capx_3_0 << 3) | ( XtalCap << 7);
|
|
if(r850_wr(priv,33,priv->regs[33])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
priv->regs[34] = (priv->regs[34] & 0xF7) | (Capxx << 3);
|
|
if(r850_wr(priv,34,priv->regs[34])!=0)
|
|
return R850_Fail;
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
R850_ErrCode R850_SetXtalCap_No_Write(struct r850_priv *priv,u8 u8XtalCap)
|
|
{
|
|
u8 XtalCap;
|
|
u8 Capx;
|
|
u8 Capx_3_0, Capxx;
|
|
|
|
if(u8XtalCap>31)
|
|
{
|
|
XtalCap = 1; //10
|
|
Capx = u8XtalCap-10;
|
|
}
|
|
else
|
|
{
|
|
XtalCap = 0; //0
|
|
Capx = u8XtalCap;
|
|
}
|
|
|
|
Capxx = Capx & 0x01;
|
|
Capx_3_0 = Capx >> 1;
|
|
|
|
// Set Xtal Cap R33[6:3], R34[3] XtalCap => R33[7]
|
|
|
|
priv->regs[33] = (priv->regs[33] & 0x07) | (Capx_3_0 << 3) | ( XtalCap << 7);
|
|
|
|
priv->regs[34] = (priv->regs[34] & 0xF7) | (Capxx << 3);
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
/*parameter 2: xtal_gm
|
|
0:24MHz (strong)
|
|
1:24MHz
|
|
2:gm (16MHz)
|
|
3:off
|
|
*/
|
|
R850_ErrCode R850_Set_XTAL_GM(struct r850_priv *priv,u8 xtal_gm)
|
|
{
|
|
// Set Xtal gm R34[7:6]
|
|
|
|
priv->regs[34] = (priv->regs[34] & 0x3F) | (xtal_gm << 6);
|
|
if(r850_wr(priv,34,priv->regs[34])!=0)
|
|
return R850_Fail;
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
/*
|
|
XTAL_PWR_VALUE
|
|
{
|
|
XTAL_LOWEST = 0,
|
|
XTAL_LOW,
|
|
XTAL_HIGH,
|
|
XTAL_HIGHEST,
|
|
XTAL_CHECK_SIZE
|
|
};
|
|
*/
|
|
R850_ErrCode R850_SetXtalPW( struct r850_priv *priv,u8 u8Xtalpw)
|
|
{
|
|
u8 Xtal_power;
|
|
|
|
Xtal_power = (3 - u8Xtalpw);
|
|
|
|
priv->regs[34] = (priv->regs[34] & 0xCF) | (Xtal_power<<4); //R34[5:4]
|
|
|
|
if(r850_wr(priv,34,priv->regs[34])!=0)
|
|
return R850_Fail;
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
R850_ErrCode R850_PLL(struct r850_priv*priv, u32 LO_Freq, enum R850_Standard_Type R850_Standard)//ok
|
|
{
|
|
u8 MixDiv = 2;
|
|
u8 DivBuf = 0;
|
|
u8 Ni = 0;
|
|
u8 Si = 0;
|
|
u8 DivNum = 0;
|
|
u16 Nint = 0;
|
|
u32 VCO_Min = 2200000;
|
|
u32 VCO_Max = 4400000;
|
|
u32 VCO_Freq = 0;
|
|
u32 PLL_Ref = priv->cfg->R850_Xtal;
|
|
u32 VCO_Fra = 0;
|
|
u16 Nsdm = 2;
|
|
u16 SDM = 0;
|
|
u16 SDM16to9 = 0;
|
|
u16 SDM8to1 = 0;
|
|
u8 XTAL_POW = 0;
|
|
u16 u2XalDivJudge;
|
|
u8 u1XtalDivRemain;
|
|
u8 CP_CUR = 0x00;
|
|
u8 CP_OFFSET = 0x00;
|
|
u8 SDM_RES = 0x00;
|
|
u8 NS_RES = 0x00;
|
|
u8 IQGen_Cur = 0; //DminDmin
|
|
u8 IQBias = 1; //BiasI
|
|
u8 IQLoad = 0; //3.2k/2
|
|
u8 OutBuf_Bias = 0; //max
|
|
u8 BiasHf = 0; //135u
|
|
u8 PllArrayCunt = 0;
|
|
int ret = 0;
|
|
|
|
// if(R850_Chip == R850_MP)
|
|
// VCO_Min=2270000;
|
|
// else
|
|
VCO_Min=2200000;
|
|
|
|
VCO_Max = VCO_Min*2;
|
|
|
|
// VCO current = 0 (max)
|
|
priv->regs[32] = (priv->regs[32] & 0xFC) | 0x00; // R31[1:0] = 0 => R32[3:2] = 0
|
|
|
|
// VCO power = auto
|
|
priv->regs[46] = (priv->regs[46] & 0xBF) | 0x40; // R26[7] = 1 => R46[6] = 1
|
|
|
|
// HfDiv Buf = 6dB buffer
|
|
priv->regs[37] = (priv->regs[37] & 0xEF) | 0x00; // R17[7]=0 => R37[4]=0
|
|
|
|
// Divider HfDiv current = 135u
|
|
priv->regs[12] = (priv->regs[12] & 0xFC) | 0x00; // R10[1:0]=00 => R12[3:2]=00
|
|
|
|
// PLL LDOA=2.2V
|
|
priv->regs[11] = (priv->regs[11] & 0xF3) | 0x00; // R11[3:2]=00 => R11[3:2]=00
|
|
|
|
// PFD DLDO=4mA
|
|
priv->regs[12] = (priv->regs[12] & 0x3F) | 0x00; // R8[5:4]=00 => R12[7:6]=00
|
|
|
|
// DLDO2=3mA
|
|
priv->regs[11] = (priv->regs[11] & 0xCF) | 0x10; // R11[5:4]=01 => R11[5:4]=01
|
|
|
|
// HF Fiv LDO=7mA (new bonding set this off)
|
|
priv->regs[9] = (priv->regs[9] & 0xF9) | 0x00; // R12[2:1]=00 => R9[2:1]=00
|
|
|
|
//------ Xtal freq depend setting: Xtal Gm & AGC ref clk --------//
|
|
if(priv->cfg->R850_Xtal==24000)
|
|
{
|
|
priv->regs[34] = (priv->regs[34] & 0x3F) | 0x00; //gm*2(24) R32[4:3]:00 => R34[7:6]:00
|
|
priv->regs[37] = (priv->regs[37] & 0xDF) | 0x20; //clk /3 (24) => R37[5]=1
|
|
}
|
|
else if(priv->cfg->R850_Xtal==16000)
|
|
{
|
|
priv->regs[34] = (priv->regs[34] & 0x3F) | 0x80; //gm(16) R32[4:3]:10 => R34[7:6]:10
|
|
priv->regs[37] = (priv->regs[37] & 0xDF) | 0x00; //clk /2 (16) => R37[5]=0
|
|
}
|
|
else if(priv->cfg->R850_Xtal==27000)
|
|
{
|
|
priv->regs[34] = (priv->regs[34] & 0x3F) | 0x00; //gm*2(24) R32[4:3]:00 => R34[7:6]:00
|
|
priv->regs[37] = (priv->regs[37] & 0xDF) | 0x20; //clk /3 (24) => R37[5]=1
|
|
}
|
|
else //not support Xtal freq
|
|
return R850_Fail;
|
|
|
|
|
|
if(priv->R850_clock_out == 1)
|
|
{
|
|
XTAL_POW = 0; //highest, R32[2:1]=0
|
|
//Set X'tal Cap
|
|
R850_SetXtalCap(priv, priv->R850_Xtal_cap);
|
|
}
|
|
else if(priv->R850_clock_out == 0)
|
|
{
|
|
XTAL_POW = 3; //lowest, R32[2:1]=3
|
|
//Set X'tal Cap
|
|
R850_SetXtalCap(priv, 0);
|
|
//gm off
|
|
R850_Set_XTAL_GM(priv, 1); //3:xtal gm off
|
|
}
|
|
else
|
|
{
|
|
if(LO_Freq<100000) //Xtal PW : Low
|
|
{
|
|
if(priv->R850_Xtal_Pwr <= R850_XTAL_LOW )
|
|
{
|
|
XTAL_POW = 2;
|
|
}
|
|
else
|
|
{
|
|
XTAL_POW = 3 - priv->R850_Xtal_Pwr;
|
|
}
|
|
}
|
|
else if((110000<=LO_Freq) && (LO_Freq<130000)) //Xtal PW: High
|
|
{
|
|
if(priv->R850_Xtal_Pwr <= R850_XTAL_HIGH )
|
|
{
|
|
XTAL_POW = 1;
|
|
}
|
|
else
|
|
{
|
|
XTAL_POW = 3 - priv->R850_Xtal_Pwr;
|
|
}
|
|
}
|
|
else //Xtal PW : Highest
|
|
{
|
|
XTAL_POW = 0;
|
|
}
|
|
//Set X'tal Cap
|
|
R850_SetXtalCap(priv, priv->R850_Xtal_cap);
|
|
}
|
|
|
|
|
|
priv->regs[34] = (priv->regs[34] & 0xCF) | (XTAL_POW<<4); //R32[2:1] => R34[5:4]
|
|
|
|
|
|
CP_CUR = 0x00; //0.7m, R30[7:5]=000
|
|
CP_OFFSET = 0x00; //0u, R37[1]=0
|
|
if(priv->cfg->R850_Xtal == 24000)
|
|
{
|
|
u2XalDivJudge = (u16) ((LO_Freq+priv->R850_IF_GOLOBAL)/1000/12);
|
|
// 48, 120 ,264 ,288, 336
|
|
if((u2XalDivJudge==4)||(u2XalDivJudge==10)||(u2XalDivJudge==22)||(u2XalDivJudge==24)||(u2XalDivJudge==28))
|
|
{
|
|
CP_OFFSET = 0x02; //30u, R37[1]=1
|
|
}
|
|
else
|
|
{
|
|
CP_OFFSET = 0x00; //0u, R37[1]=0
|
|
}
|
|
}
|
|
else if(priv->cfg->R850_Xtal == 16000)
|
|
{
|
|
u2XalDivJudge = (u16) ((LO_Freq+priv->R850_IF_GOLOBAL)/1000/8);
|
|
//
|
|
if((u2XalDivJudge==6)||(u2XalDivJudge==10)||(u2XalDivJudge==12)||(u2XalDivJudge==48))
|
|
{
|
|
CP_OFFSET = 0x02; //30u, R37[1]=1
|
|
}
|
|
else
|
|
{
|
|
CP_OFFSET = 0x00; //0u, R37[1]=0
|
|
}
|
|
}
|
|
else if(priv->cfg->R850_Xtal == 27000)
|
|
{
|
|
u2XalDivJudge = (u16) ((LO_Freq+priv->R850_IF_GOLOBAL)*10/1000/135);
|
|
// 48, 120 ,264 ,288, 336
|
|
if((u2XalDivJudge==4)||(u2XalDivJudge==10)||(u2XalDivJudge==22)||(u2XalDivJudge==24)||(u2XalDivJudge==28))
|
|
{
|
|
CP_OFFSET = 0x02; //30u, R37[1]=1
|
|
}
|
|
else
|
|
{
|
|
CP_OFFSET = 0x00; //0u, R37[1]=0
|
|
}
|
|
}
|
|
|
|
|
|
priv->regs[30] = (priv->regs[30] & 0x1F) | (CP_CUR); // => R30[7:5]
|
|
|
|
priv->regs[37] = (priv->regs[37] & 0xFD) | (CP_OFFSET); // => R37[1]
|
|
|
|
//set pll autotune = 64kHz (fast) R47[1:0](MP) , R47[0](MT1)
|
|
|
|
priv->regs[47] = priv->regs[47] & 0xFD;
|
|
|
|
//Divider
|
|
while(MixDiv <= 64)
|
|
{
|
|
if(((LO_Freq * MixDiv) >= VCO_Min) && ((LO_Freq * MixDiv) < VCO_Max))
|
|
{
|
|
DivBuf = MixDiv;
|
|
while(DivBuf > 2)
|
|
{
|
|
DivBuf = DivBuf >> 1;
|
|
DivNum ++;
|
|
}
|
|
break;
|
|
}
|
|
MixDiv = MixDiv << 1;
|
|
}
|
|
|
|
//IQ Gen block & BiasHF & NS_RES & SDM_Res
|
|
if(MixDiv <= 4) //Div=2,4
|
|
{
|
|
IQGen_Cur = 0; //DminDmin
|
|
IQBias = 1; //BiasI
|
|
IQLoad = 0; //3.2k/2
|
|
OutBuf_Bias = 0; //0 (max)
|
|
BiasHf = 0; //135u
|
|
SDM_RES = 0; //short
|
|
NS_RES = 0; //0R
|
|
}
|
|
else if(MixDiv == 8)
|
|
{
|
|
IQGen_Cur = 0; //DminDmin
|
|
IQBias = 0; //BiasI/2
|
|
IQLoad = 1; //3.2k
|
|
OutBuf_Bias = 1; //1
|
|
BiasHf = 1; //110u
|
|
SDM_RES = 0; //short
|
|
NS_RES = 1; //800R
|
|
}
|
|
else if(MixDiv == 16)
|
|
{
|
|
IQGen_Cur = 0; //DminDmin
|
|
IQBias = 0; //BiasI/2
|
|
IQLoad = 1; //3.2k
|
|
OutBuf_Bias = 2; //2
|
|
BiasHf = 1; //110u
|
|
SDM_RES = 0; //short
|
|
NS_RES = 0; //0R
|
|
}
|
|
else if(MixDiv >= 32) //32, 64
|
|
{
|
|
IQGen_Cur = 0; //DminDmin
|
|
IQBias = 0; //BiasI/2
|
|
IQLoad = 1; //3.2k
|
|
OutBuf_Bias = 3; //3 (min)
|
|
BiasHf = 1; //110u
|
|
SDM_RES = 0; //short
|
|
NS_RES = 0; //0R
|
|
}
|
|
else
|
|
{
|
|
return R850_Fail;
|
|
}
|
|
|
|
{
|
|
|
|
{
|
|
if(priv->cfg->R850_Xtal==24000)
|
|
u2XalDivJudge = (u16) ((LO_Freq + priv->R850_IF_GOLOBAL)/1000/12);
|
|
else if(priv->cfg->R850_Xtal==16000)
|
|
u2XalDivJudge = (u16) ((LO_Freq + priv->R850_IF_GOLOBAL)/1000/8);
|
|
else if(priv->cfg->R850_Xtal==27000)
|
|
u2XalDivJudge = (u16) ((LO_Freq + priv->R850_IF_GOLOBAL)*10/1000/135);
|
|
else
|
|
return R850_Fail;
|
|
|
|
u1XtalDivRemain = (u8) (u2XalDivJudge % 2);
|
|
|
|
if(LO_Freq < (372000+8500))
|
|
{
|
|
if(u1XtalDivRemain==1) //odd
|
|
{
|
|
priv->R850_XtalDiv = R850_XTAL_DIV1;
|
|
}
|
|
else //even, spur area
|
|
{
|
|
priv->R850_XtalDiv = R850_XTAL_DIV1_2;
|
|
}
|
|
}
|
|
else if(((LO_Freq + priv->R850_IF_GOLOBAL) >= 478000) && ((LO_Freq + priv->R850_IF_GOLOBAL) < 482000) && (R850_Standard == R850_ISDB_T_4063))
|
|
{
|
|
priv->R850_XtalDiv = R850_XTAL_DIV4;
|
|
}
|
|
else
|
|
{
|
|
priv->R850_XtalDiv = R850_XTAL_DIV1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//Xtal divider setting
|
|
//R850_XtalDiv = XTAL_DIV2; //div 1, 2, 4
|
|
if(priv->R850_XtalDiv==R850_XTAL_DIV1)
|
|
{
|
|
PLL_Ref = priv->cfg->R850_Xtal;
|
|
priv->regs[34] = (priv->regs[34] & 0xFC) | 0x00; //b7:2nd_div2=0, b6:1st_div2=0 R32[7:6] => R34[1:0]
|
|
}
|
|
else if(priv->R850_XtalDiv==R850_XTAL_DIV1_2)
|
|
{
|
|
PLL_Ref = priv->cfg->R850_Xtal/2;
|
|
priv->regs[34] = (priv->regs[34] & 0xFC) | 0x02; //1st_div2=0(R34[0]), 2nd_div2=1(R34[1])
|
|
}
|
|
else if(priv->R850_XtalDiv==R850_XTAL_DIV2_1)
|
|
{
|
|
PLL_Ref = priv->cfg->R850_Xtal/2;
|
|
priv->regs[34] = (priv->regs[34] & 0xFC) | 0x01; //1st_div2=1(R34[0]), 2nd_div2=0(R34[1])
|
|
}
|
|
else if(priv->R850_XtalDiv==R850_XTAL_DIV4) //24MHz
|
|
{
|
|
PLL_Ref = priv->cfg->R850_Xtal/4;
|
|
priv->regs[34] = (priv->regs[34] & 0xFC) | 0x03; //b7:2nd_div2=1, b6:1st_div2=1 R32[7:6] => R34[1:0]
|
|
}
|
|
|
|
|
|
//IQ gen current R10[7] => R11[0]
|
|
priv->regs[11] = (priv->regs[11] & 0xFE) | (IQGen_Cur);
|
|
|
|
//Out Buf Bias R10[6:5] => R45[3:2]
|
|
priv->regs[45] = (priv->regs[45] & 0xF3) | (OutBuf_Bias<<2);
|
|
|
|
//BiasI R29[2] => R46[0]
|
|
priv->regs[46] = (priv->regs[46] & 0xFE) | (IQBias);
|
|
|
|
//IQLoad R36[5] => R46[1]
|
|
priv->regs[46] = (priv->regs[46] & 0xFD) | (IQLoad<<1);
|
|
|
|
//BiasHF R29[7:6] => R32[1:0]
|
|
priv->regs[32] = (priv->regs[32] & 0xFC) | (BiasHf);
|
|
|
|
//SDM_RES R30[7] => R32[4]
|
|
priv->regs[32] = (priv->regs[32] & 0xEF) | (SDM_RES<<4);
|
|
|
|
//NS_RES R36[0] => R17[7]
|
|
priv->regs[17] = (priv->regs[17] & 0x7F) | (NS_RES<<7);
|
|
|
|
//Divider num R35[5:3] => R30[4:2]
|
|
priv->regs[30] = (priv->regs[30] & 0xE3) | (DivNum << 2);
|
|
|
|
VCO_Freq = LO_Freq * MixDiv;
|
|
Nint = (u16) (VCO_Freq / 2 / PLL_Ref);
|
|
VCO_Fra = (u16) (VCO_Freq - 2 * PLL_Ref * Nint);
|
|
|
|
//Boundary spur prevention
|
|
if (VCO_Fra < PLL_Ref/64) //2*PLL_Ref/128
|
|
VCO_Fra = 0;
|
|
else if (VCO_Fra > PLL_Ref*127/64) //2*PLL_Ref*127/128
|
|
{
|
|
VCO_Fra = 0;
|
|
Nint ++;
|
|
}
|
|
else if((VCO_Fra > PLL_Ref*127/128) && (VCO_Fra < PLL_Ref)) //> 2*PLL_Ref*127/256, < 2*PLL_Ref*128/256
|
|
VCO_Fra = PLL_Ref*127/128; // VCO_Fra = 2*PLL_Ref*127/256
|
|
else if((VCO_Fra > PLL_Ref) && (VCO_Fra < PLL_Ref*129/128)) //> 2*PLL_Ref*128/256, < 2*PLL_Ref*129/256
|
|
VCO_Fra = PLL_Ref*129/128; // VCO_Fra = 2*PLL_Ref*129/256
|
|
else
|
|
VCO_Fra = VCO_Fra;
|
|
|
|
//Ni & Si
|
|
Ni = (u8) ((Nint - 13) / 4);
|
|
Si = (u8) (Nint - 4 *Ni - 13);
|
|
|
|
|
|
priv->regs[27] = (priv->regs[27] & 0x80) | Ni; //R26[6:0] => R27[6:0]
|
|
priv->regs[30] = (priv->regs[30] & 0xFC) | Si; //R35[7:6] => R30[1:0]
|
|
|
|
//pw_sdm & pw_dither
|
|
priv->regs[32] &= 0x3F; //R29[1:0] => R32[7:6]
|
|
if(VCO_Fra == 0)
|
|
{
|
|
priv->regs[32] |= 0xC0;
|
|
}
|
|
|
|
//SDM calculator
|
|
while(VCO_Fra > 1)
|
|
{
|
|
if (VCO_Fra > (2*PLL_Ref / Nsdm))
|
|
{
|
|
SDM = SDM + 32768 / (Nsdm/2);
|
|
VCO_Fra = VCO_Fra - 2*PLL_Ref / Nsdm;
|
|
if (Nsdm >= 0x8000)
|
|
break;
|
|
}
|
|
Nsdm = Nsdm << 1;
|
|
}
|
|
|
|
SDM16to9 = SDM >> 8;
|
|
SDM8to1 = SDM - (SDM16to9 << 8);
|
|
|
|
|
|
priv->regs[29] = (u8) SDM16to9; //R28 => R29
|
|
priv->regs[28] = (u8) SDM8to1; //R27 => R28
|
|
|
|
|
|
ret = r850_wrm(priv,8,&priv->regs[8],40);
|
|
if(ret!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
|
|
if(priv->R850_XtalDiv == R850_XTAL_DIV1)
|
|
msleep( R850_PLL_LOCK_DELAY); //correct gx_msleep ecos, don't modify delay function!
|
|
else if((priv->R850_XtalDiv == R850_XTAL_DIV1_2) || (priv->R850_XtalDiv == R850_XTAL_DIV2_1))
|
|
msleep( R850_PLL_LOCK_DELAY*2);
|
|
else
|
|
msleep( R850_PLL_LOCK_DELAY*4);
|
|
|
|
//set pll autotune = 1khz (2'b10)
|
|
|
|
priv->regs[47] = (priv->regs[47] & 0xFD) | 0x02;
|
|
if(r850_wr(priv,47,priv->regs[47])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
return R850_Success;
|
|
|
|
}
|
|
|
|
|
|
R850_ErrCode R850_MUX( struct r850_priv *priv ,u32 LO_KHz, u32 RF_KHz, enum R850_Standard_Type R850_Standard)
|
|
{
|
|
u8 Reg_IMR_Gain = 0;
|
|
u8 Reg_IMR_Phase = 0;
|
|
u8 Reg_IMR_Iqcap = 0;
|
|
struct R850_Freq_Info_Type Freq_Info1;
|
|
|
|
//Freq_Info_Type Freq_Info1;
|
|
Freq_Info1 = R850_Freq_Sel(LO_KHz, RF_KHz, R850_Standard);
|
|
|
|
|
|
// TF_DIPLEXER
|
|
priv->regs[14] = (priv->regs[14] & 0xF3) | (Freq_Info1.TF_DIPLEXER<<2); //LPF => R14[3:2]
|
|
if(r850_wr(priv,14,priv->regs[14])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
|
|
//TF_HPF_BPF => R16[2:0] TF_HPF_CNR => R16[4:3]
|
|
priv->regs[16] = (priv->regs[16] & 0xE0) | (Freq_Info1.TF_HPF_BPF) | (Freq_Info1.TF_HPF_CNR << 3); // R16[2:0], R16[4:3]
|
|
if(r850_wr(priv,16,priv->regs[16])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
// RF Polyfilter
|
|
priv->regs[18] = (priv->regs[18] & 0xFC) | (Freq_Info1.RF_POLY); //R17[6:5] => R18[1:0]
|
|
if(r850_wr(priv,18,priv->regs[18])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
// LNA Cap
|
|
priv->regs[14] = (priv->regs[14] & 0x0F) | (Freq_Info1.LPF_CAP<<4); //R16[3:0] => R14[7:4]
|
|
if(r850_wr(priv,14,priv->regs[14])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
// LNA Notch
|
|
priv->regs[15] = (priv->regs[15] & 0xF0) | (Freq_Info1.LPF_NOTCH); //R16[7:4] => R15[3:0]
|
|
if(r850_wr(priv,15,priv->regs[15])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
|
|
|
|
//Set_IMR
|
|
if( (priv->R850_IMR_done_flag == TRUE) && (priv->R850_IMR_Cal_Result==0))
|
|
{
|
|
|
|
Reg_IMR_Gain = priv->imr_data[Freq_Info1.IMR_MEM_NOR].Gain_X & 0x2F; //R20[4:0] => R20[3:0]
|
|
Reg_IMR_Phase = priv->imr_data[Freq_Info1.IMR_MEM_NOR].Phase_Y & 0x2F; //R21[4:0] => R21[3:0]
|
|
Reg_IMR_Iqcap = priv->imr_data[Freq_Info1.IMR_MEM_NOR].Iqcap; //0,1,2
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
Reg_IMR_Gain = 0;
|
|
Reg_IMR_Phase = 0;
|
|
Reg_IMR_Iqcap = 0;
|
|
}
|
|
|
|
//Gain, R20[4:0]
|
|
priv->regs[R850_IMR_GAIN_REG] = (priv->regs[R850_IMR_GAIN_REG] & 0xD0) | (Reg_IMR_Gain & 0x2F);
|
|
if(r850_wr(priv,R850_IMR_GAIN_REG,priv->regs[R850_IMR_GAIN_REG])!=0)
|
|
return R850_Fail;
|
|
|
|
//Phase, R21[4:0]
|
|
priv->regs[R850_IMR_PHASE_REG] = (priv->regs[R850_IMR_PHASE_REG] & 0xD0) | (Reg_IMR_Phase & 0x2F);
|
|
if(r850_wr(priv,R850_IMR_PHASE_REG,priv->regs[R850_IMR_PHASE_REG])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
//Iqcap, R21[7:6]
|
|
priv->regs[R850_IMR_IQCAP_REG] = (priv->regs[R850_IMR_IQCAP_REG] & 0x3F) | (Reg_IMR_Iqcap<<6);
|
|
if(r850_wr(priv,R850_IMR_IQCAP_REG,priv->regs[R850_IMR_IQCAP_REG])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------------/
|
|
// Purpose: compare IMR result aray [0][1][2], find min value and store to CorArry[0]
|
|
// input: CorArry: three IMR data array
|
|
// output: TRUE or FALSE
|
|
//-----------------------------------------------------------------------------------/
|
|
R850_ErrCode R850_CompreCor(struct R850_SectType* CorArry)
|
|
{
|
|
u8 CompCunt = 0;
|
|
struct R850_SectType CorTemp;
|
|
|
|
for(CompCunt=3; CompCunt > 0; CompCunt --)
|
|
{
|
|
if(CorArry[0].Value > CorArry[CompCunt - 1].Value) //compare IMR result [0][1][2], find min value
|
|
{
|
|
CorTemp = CorArry[0];
|
|
CorArry[0] = CorArry[CompCunt - 1];
|
|
CorArry[CompCunt - 1] = CorTemp;
|
|
}
|
|
}
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------------------//
|
|
// Purpose: if (Gain<9 or Phase<9), Gain+1 or Phase+1 and compare with min value
|
|
// new < min => update to min and continue
|
|
// new > min => Exit
|
|
// input: StepArry: three IMR data array
|
|
// Pace: gain or phase register
|
|
// output: TRUE or FALSE
|
|
//-------------------------------------------------------------------------------------//
|
|
R850_ErrCode R850_CompreStep(struct r850_priv*priv, struct R850_SectType* StepArry, u8 Pace)
|
|
{
|
|
struct R850_SectType StepTemp;
|
|
|
|
//min value already saved in StepArry[0]
|
|
StepTemp.Phase_Y = StepArry[0].Phase_Y; //whole byte data
|
|
StepTemp.Gain_X = StepArry[0].Gain_X;
|
|
//StepTemp.Iqcap = StepArry[0].Iqcap;
|
|
|
|
while(((StepTemp.Gain_X & 0x0F) < R850_IMR_TRIAL) && ((StepTemp.Phase_Y & 0x0F) < R850_IMR_TRIAL))
|
|
{
|
|
if(Pace == R850_IMR_GAIN_REG)
|
|
StepTemp.Gain_X ++;
|
|
else
|
|
StepTemp.Phase_Y ++;
|
|
|
|
if(r850_wr(priv,R850_IMR_GAIN_REG,StepTemp.Gain_X)!=0)
|
|
return R850_Fail;
|
|
|
|
if(r850_wr(priv,R850_IMR_PHASE_REG,StepTemp.Phase_Y)!=0)
|
|
return R850_Fail;
|
|
|
|
if(R850_Muti_Read(priv, &StepTemp.Value) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if(StepTemp.Value <= StepArry[0].Value)
|
|
{
|
|
StepArry[0].Gain_X = StepTemp.Gain_X;
|
|
StepArry[0].Phase_Y = StepTemp.Phase_Y;
|
|
//StepArry[0].Iqcap = StepTemp.Iqcap;
|
|
StepArry[0].Value = StepTemp.Value;
|
|
}
|
|
else if((StepTemp.Value - 2*R850_ADC_READ_COUNT) > StepArry[0].Value)
|
|
{
|
|
break;
|
|
}
|
|
|
|
} //end of while()
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
// Purpose: record IMR results by input gain/phase location
|
|
// then adjust gain or phase positive 1 step and negtive 1 step, both record results
|
|
// input: FixPot: phase or gain
|
|
// FlucPot phase or gain
|
|
// PotReg: Reg20 or Reg21
|
|
// CompareTree: 3 IMR trace and results
|
|
// output: TREU or FALSE
|
|
//--------------------------------------------------------------------------------------------
|
|
R850_ErrCode R850_IQ_Tree( struct r850_priv *priv,u8 FixPot, u8 FlucPot, u8 PotReg, struct R850_SectType* CompareTree)
|
|
{
|
|
u8 TreeCunt = 0;
|
|
u8 PntReg = 0;
|
|
|
|
//PntReg is reg to change; FlucPot is change value
|
|
if(PotReg == R850_IMR_GAIN_REG)
|
|
PntReg = R850_IMR_PHASE_REG; //phase control
|
|
else
|
|
PntReg = R850_IMR_GAIN_REG; //gain control
|
|
|
|
for(TreeCunt = 0; TreeCunt<3; TreeCunt ++)
|
|
{
|
|
|
|
if(r850_wr(priv,PotReg,FixPot)!=0)
|
|
return R850_Fail;
|
|
if(r850_wr(priv,PntReg,FlucPot)!=0)
|
|
return R850_Fail;
|
|
|
|
if(R850_Muti_Read(priv, &CompareTree[TreeCunt].Value) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if(PotReg == R850_IMR_GAIN_REG)
|
|
{
|
|
CompareTree[TreeCunt].Gain_X = FixPot;
|
|
CompareTree[TreeCunt].Phase_Y = FlucPot;
|
|
}
|
|
else
|
|
{
|
|
CompareTree[TreeCunt].Phase_Y = FixPot;
|
|
CompareTree[TreeCunt].Gain_X = FlucPot;
|
|
}
|
|
|
|
if(TreeCunt == 0) //try right-side point
|
|
{
|
|
FlucPot ++;
|
|
}
|
|
else if(TreeCunt == 1) //try left-side point
|
|
{
|
|
if((FlucPot & 0x0F) == 1) //if absolute location is 1, change I/Q direction
|
|
{
|
|
if(FlucPot & 0x20) //b[5]:I/Q selection. 0:Q-path, 1:I-path
|
|
{
|
|
//FlucPot = (FlucPot & 0xE0) | 0x01;
|
|
FlucPot = (FlucPot & 0xD0) | 0x01;
|
|
}
|
|
else
|
|
{
|
|
//FlucPot = (FlucPot & 0xE0) | 0x11;
|
|
FlucPot = (FlucPot & 0xD0) | 0x21;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FlucPot = FlucPot - 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
R850_ErrCode R850_IQ_Tree5(struct r850_priv*priv, u8 FixPot, u8 FlucPot, u8 PotReg, struct R850_SectType* CompareTree)
|
|
{
|
|
u8 TreeCunt = 0;
|
|
u8 TreeTimes = 5;
|
|
u8 TempPot = 0;
|
|
u8 PntReg = 0;
|
|
u8 CompCunt = 0;
|
|
struct R850_SectType CorTemp[5];
|
|
struct R850_SectType Compare_Temp;
|
|
u8 CuntTemp = 0;
|
|
|
|
memset(&Compare_Temp,0, sizeof(struct R850_SectType));
|
|
Compare_Temp.Value = 255;
|
|
|
|
for(CompCunt=0; CompCunt<3; CompCunt++)
|
|
{
|
|
CorTemp[CompCunt].Gain_X = CompareTree[CompCunt].Gain_X;
|
|
CorTemp[CompCunt].Phase_Y = CompareTree[CompCunt].Phase_Y;
|
|
CorTemp[CompCunt].Value = CompareTree[CompCunt].Value;
|
|
}
|
|
|
|
/*
|
|
if(PotReg == 0x08)
|
|
PntReg = 0x09; //phase control
|
|
else
|
|
PntReg = 0x08; //gain control
|
|
*/
|
|
|
|
//PntReg is reg to change; FlucPot is change value
|
|
if(PotReg == R850_IMR_GAIN_REG)
|
|
PntReg = R850_IMR_PHASE_REG; //phase control
|
|
else
|
|
PntReg = R850_IMR_GAIN_REG; //gain control
|
|
|
|
|
|
|
|
|
|
for(TreeCunt = 0;TreeCunt < TreeTimes;TreeCunt++)
|
|
{
|
|
if(r850_wr(priv,PotReg,FixPot) != 0)
|
|
return R850_Fail;
|
|
if(r850_wr(priv,PntReg,FlucPot) != 0)
|
|
return R850_Fail;
|
|
|
|
if(R850_Muti_Read( priv,&CorTemp[TreeCunt].Value) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if(PotReg == R850_IMR_GAIN_REG)
|
|
{
|
|
CorTemp[TreeCunt].Gain_X = FixPot;
|
|
CorTemp[TreeCunt].Phase_Y = FlucPot;
|
|
}
|
|
else
|
|
{
|
|
CorTemp[TreeCunt].Phase_Y = FixPot;
|
|
CorTemp[TreeCunt].Gain_X = FlucPot;
|
|
}
|
|
|
|
if(TreeCunt == 0) //next try right-side 1 point
|
|
{
|
|
FlucPot ++; //+1
|
|
}
|
|
else if(TreeCunt == 1) //next try right-side 2 point
|
|
{
|
|
FlucPot ++; //1+1=2
|
|
}
|
|
else if(TreeCunt == 2) //next try left-side 1 point
|
|
{
|
|
if((FlucPot & 0x0F) == 0x02) //if absolute location is 2, change I/Q direction and set to 1
|
|
{
|
|
TempPot = 1;
|
|
if((FlucPot & 0x20)==0x20) //b[5]:I/Q selection. 0:Q-path, 1:I-path
|
|
{
|
|
FlucPot = (FlucPot & 0xD0) | 0x01; //Q1
|
|
}
|
|
else
|
|
{
|
|
FlucPot = (FlucPot & 0xD0) | 0x21; //I1
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FlucPot -= 3; //+2-3=-1
|
|
}
|
|
}
|
|
else if(TreeCunt == 3) //next try left-side 2 point
|
|
{
|
|
if(TempPot==1) //been chnaged I/Q
|
|
{
|
|
FlucPot += 1;
|
|
}
|
|
else if((FlucPot & 0x0F) == 0x00) //if absolute location is 0, change I/Q direction
|
|
{
|
|
TempPot = 1;
|
|
if((FlucPot & 0x20)==0x20) //b[5]:I/Q selection. 0:Q-path, 1:I-path
|
|
{
|
|
FlucPot = (FlucPot & 0xD0) | 0x01; //Q1
|
|
}
|
|
else
|
|
{
|
|
FlucPot = (FlucPot & 0xD0) | 0x21; //I1
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FlucPot -= 1; //-1-1=-2
|
|
}
|
|
}
|
|
|
|
if(CorTemp[TreeCunt].Value < Compare_Temp.Value)
|
|
{
|
|
Compare_Temp.Value = CorTemp[TreeCunt].Value;
|
|
Compare_Temp.Gain_X = CorTemp[TreeCunt].Gain_X;
|
|
Compare_Temp.Phase_Y = CorTemp[TreeCunt].Phase_Y;
|
|
CuntTemp = TreeCunt;
|
|
}
|
|
}
|
|
|
|
|
|
//CompareTree[0].Gain_X = CorTemp[CuntTemp].Gain_X;
|
|
//CompareTree[0].Phase_Y = CorTemp[CuntTemp].Phase_Y;
|
|
//CompareTree[0].Value = CorTemp[CuntTemp].Value;
|
|
|
|
for(CompCunt=0; CompCunt<3; CompCunt++)
|
|
{
|
|
if(CuntTemp==3 || CuntTemp==4)
|
|
{
|
|
CompareTree[CompCunt].Gain_X = CorTemp[2+CompCunt].Gain_X; //2,3,4
|
|
CompareTree[CompCunt].Phase_Y = CorTemp[2+CompCunt].Phase_Y;
|
|
CompareTree[CompCunt].Value = CorTemp[2+CompCunt].Value;
|
|
}
|
|
else
|
|
{
|
|
CompareTree[CompCunt].Gain_X = CorTemp[CompCunt].Gain_X; //0,1,2
|
|
CompareTree[CompCunt].Phase_Y = CorTemp[CompCunt].Phase_Y;
|
|
CompareTree[CompCunt].Value = CorTemp[CompCunt].Value;
|
|
}
|
|
|
|
}
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
R850_ErrCode R850_Section(struct r850_priv*priv, struct R850_SectType* IQ_Pont)
|
|
{
|
|
struct R850_SectType Compare_IQ[3];
|
|
struct R850_SectType Compare_Bet[3];
|
|
|
|
//Try X-1 column and save min result to Compare_Bet[0]
|
|
if((IQ_Pont->Gain_X & 0x0F) == 0x00)
|
|
{
|
|
Compare_IQ[0].Gain_X = ((IQ_Pont->Gain_X) & 0xDF) + 1; //Q-path, Gain=1
|
|
}
|
|
else
|
|
{
|
|
Compare_IQ[0].Gain_X = IQ_Pont->Gain_X - 1; //left point
|
|
}
|
|
Compare_IQ[0].Phase_Y = IQ_Pont->Phase_Y;
|
|
|
|
if(R850_IQ_Tree(priv, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, R850_IMR_GAIN_REG, &Compare_IQ[0]) != R850_Success) // y-direction
|
|
return R850_Fail;
|
|
|
|
if(R850_CompreCor(&Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
Compare_Bet[0].Gain_X = Compare_IQ[0].Gain_X;
|
|
Compare_Bet[0].Phase_Y = Compare_IQ[0].Phase_Y;
|
|
Compare_Bet[0].Value = Compare_IQ[0].Value;
|
|
|
|
//Try X column and save min result to Compare_Bet[1]
|
|
Compare_IQ[0].Gain_X = IQ_Pont->Gain_X;
|
|
Compare_IQ[0].Phase_Y = IQ_Pont->Phase_Y;
|
|
|
|
if(R850_IQ_Tree(priv, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, R850_IMR_GAIN_REG, &Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if(R850_CompreCor(&Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
Compare_Bet[1].Gain_X = Compare_IQ[0].Gain_X;
|
|
Compare_Bet[1].Phase_Y = Compare_IQ[0].Phase_Y;
|
|
Compare_Bet[1].Value = Compare_IQ[0].Value;
|
|
|
|
//Try X+1 column and save min result to Compare_Bet[2]
|
|
if((IQ_Pont->Gain_X & 0x0F) == 0x00)
|
|
Compare_IQ[0].Gain_X = ((IQ_Pont->Gain_X) | 0x20) + 1; //I-path, Gain=1
|
|
else
|
|
Compare_IQ[0].Gain_X = IQ_Pont->Gain_X + 1;
|
|
Compare_IQ[0].Phase_Y = IQ_Pont->Phase_Y;
|
|
|
|
if(R850_IQ_Tree(priv, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, R850_IMR_GAIN_REG, &Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if(R850_CompreCor(&Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
Compare_Bet[2].Gain_X = Compare_IQ[0].Gain_X;
|
|
Compare_Bet[2].Phase_Y = Compare_IQ[0].Phase_Y;
|
|
Compare_Bet[2].Value = Compare_IQ[0].Value;
|
|
|
|
if(R850_CompreCor(&Compare_Bet[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
*IQ_Pont = Compare_Bet[0];
|
|
|
|
return R850_Success;
|
|
}
|
|
R850_ErrCode R850_IMR_Iqcap(struct r850_priv*priv, struct R850_SectType* IQ_Point)
|
|
{
|
|
struct R850_SectType Compare_Temp;
|
|
int i = 0;
|
|
|
|
//Set Gain/Phase to right setting
|
|
if(r850_wr( priv,R850_IMR_GAIN_REG,IQ_Point->Gain_X) != 0)
|
|
return R850_Fail;
|
|
|
|
if(r850_wr( priv,R850_IMR_PHASE_REG,IQ_Point->Phase_Y) != 0)
|
|
return R850_Fail;
|
|
|
|
//try iqcap
|
|
for(i=0; i<3; i++)
|
|
{
|
|
Compare_Temp.Iqcap = (u8) i;
|
|
priv->regs[R850_IMR_IQCAP_REG] = (priv->regs[R850_IMR_IQCAP_REG] & 0x3F) | (Compare_Temp.Iqcap<<6);
|
|
if(r850_wr( priv,R850_IMR_IQCAP_REG,priv->regs[R850_IMR_IQCAP_REG]) != 0)
|
|
return R850_Fail;
|
|
|
|
|
|
|
|
if(R850_Muti_Read(priv, &(Compare_Temp.Value)) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if(Compare_Temp.Value < IQ_Point->Value)
|
|
{
|
|
IQ_Point->Value = Compare_Temp.Value;
|
|
IQ_Point->Iqcap = Compare_Temp.Iqcap; //0, 1, 2
|
|
}
|
|
else if(Compare_Temp.Value == IQ_Point->Value)
|
|
{
|
|
IQ_Point->Value = Compare_Temp.Value;
|
|
IQ_Point->Iqcap = Compare_Temp.Iqcap; //0, 1, 2
|
|
}
|
|
}
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
R850_ErrCode R850_IMR_Cross( struct r850_priv*priv,struct R850_SectType* IQ_Pont, u8* X_Direct)
|
|
{
|
|
|
|
struct R850_SectType Compare_Cross[9]; //(0,0)(0,Q-1)(0,I-1)(Q-1,0)(I-1,0)+(0,Q-2)(0,I-2)(Q-2,0)(I-2,0)
|
|
struct R850_SectType Compare_Temp;
|
|
u8 CrossCount = 0;
|
|
u8 RegGain = priv->regs[R850_IMR_GAIN_REG] & 0xD0;
|
|
u8 RegPhase = priv->regs[R850_IMR_PHASE_REG] & 0xD0;
|
|
|
|
//memset(&Compare_Temp,0, sizeof(R850_SectType));
|
|
Compare_Temp.Gain_X = 0;
|
|
Compare_Temp.Phase_Y = 0;
|
|
Compare_Temp.Iqcap = 0;
|
|
Compare_Temp.Value = 255;
|
|
|
|
for(CrossCount=0; CrossCount<9; CrossCount++)
|
|
{
|
|
|
|
if(CrossCount==0)
|
|
{
|
|
Compare_Cross[CrossCount].Gain_X = RegGain;
|
|
Compare_Cross[CrossCount].Phase_Y = RegPhase;
|
|
}
|
|
else if(CrossCount==1)
|
|
{
|
|
Compare_Cross[CrossCount].Gain_X = RegGain; //0
|
|
Compare_Cross[CrossCount].Phase_Y = RegPhase + 1; //Q-1
|
|
}
|
|
else if(CrossCount==2)
|
|
{
|
|
Compare_Cross[CrossCount].Gain_X = RegGain; //0
|
|
Compare_Cross[CrossCount].Phase_Y = (RegPhase | 0x20) + 1; //I-1
|
|
}
|
|
else if(CrossCount==3)
|
|
{
|
|
Compare_Cross[CrossCount].Gain_X = RegGain + 1; //Q-1
|
|
Compare_Cross[CrossCount].Phase_Y = RegPhase;
|
|
}
|
|
else if(CrossCount==4)
|
|
{
|
|
//Compare_Cross[CrossCount].Gain_X = (RegGain | 0x10) + 1; //I-1
|
|
Compare_Cross[CrossCount].Gain_X = (RegGain | 0x20) + 1; //I-1
|
|
Compare_Cross[CrossCount].Phase_Y = RegPhase;
|
|
}
|
|
else if(CrossCount==5)
|
|
{
|
|
Compare_Cross[CrossCount].Gain_X = RegGain; //0
|
|
Compare_Cross[CrossCount].Phase_Y = RegPhase + 2; //Q-2
|
|
}
|
|
else if(CrossCount==6)
|
|
{
|
|
Compare_Cross[CrossCount].Gain_X = RegGain; //0
|
|
Compare_Cross[CrossCount].Phase_Y = (RegPhase | 0x20) + 2; //I-2
|
|
}
|
|
else if(CrossCount==7)
|
|
{
|
|
Compare_Cross[CrossCount].Gain_X = RegGain + 2; //Q-2
|
|
Compare_Cross[CrossCount].Phase_Y = RegPhase;
|
|
}
|
|
else if(CrossCount==8)
|
|
{
|
|
Compare_Cross[CrossCount].Gain_X = (RegGain | 0x20) + 2; //I-2
|
|
Compare_Cross[CrossCount].Phase_Y = RegPhase;
|
|
}
|
|
|
|
// R850_I2C.RegAddr = R850_IMR_GAIN_REG;
|
|
// R850_I2C.Data = Compare_Cross[CrossCount].Gain_X;
|
|
if(r850_wr(priv,R850_IMR_GAIN_REG,Compare_Cross[CrossCount].Gain_X)!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
// R850_I2C.RegAddr = R850_IMR_PHASE_REG;
|
|
// R850_I2C.Data = Compare_Cross[CrossCount].Phase_Y;
|
|
if(r850_wr(priv,R850_IMR_PHASE_REG,Compare_Cross[CrossCount].Phase_Y)!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
if(R850_Muti_Read(priv, &Compare_Cross[CrossCount].Value) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if( Compare_Cross[CrossCount].Value < Compare_Temp.Value)
|
|
{
|
|
Compare_Temp.Value = Compare_Cross[CrossCount].Value;
|
|
Compare_Temp.Gain_X = Compare_Cross[CrossCount].Gain_X;
|
|
Compare_Temp.Phase_Y = Compare_Cross[CrossCount].Phase_Y;
|
|
}
|
|
} //end for loop
|
|
|
|
|
|
if(((Compare_Temp.Phase_Y & 0x2F)==0x01) || (Compare_Temp.Phase_Y & 0x2F)==0x02) //phase Q1 or Q2
|
|
{
|
|
*X_Direct = (u8) 0;
|
|
IQ_Pont[0].Gain_X = Compare_Cross[0].Gain_X; //0
|
|
IQ_Pont[0].Phase_Y = Compare_Cross[0].Phase_Y; //0
|
|
IQ_Pont[0].Value = Compare_Cross[0].Value;
|
|
|
|
IQ_Pont[1].Gain_X = Compare_Cross[1].Gain_X; //0
|
|
IQ_Pont[1].Phase_Y = Compare_Cross[1].Phase_Y; //Q1
|
|
IQ_Pont[1].Value = Compare_Cross[1].Value;
|
|
|
|
IQ_Pont[2].Gain_X = Compare_Cross[5].Gain_X; //0
|
|
IQ_Pont[2].Phase_Y = Compare_Cross[5].Phase_Y;//Q2
|
|
IQ_Pont[2].Value = Compare_Cross[5].Value;
|
|
}
|
|
else if(((Compare_Temp.Phase_Y & 0x2F)==0x21) || (Compare_Temp.Phase_Y & 0x2F)==0x22) //phase I1 or I2
|
|
{
|
|
*X_Direct = (u8) 0;
|
|
IQ_Pont[0].Gain_X = Compare_Cross[0].Gain_X; //0
|
|
IQ_Pont[0].Phase_Y = Compare_Cross[0].Phase_Y; //0
|
|
IQ_Pont[0].Value = Compare_Cross[0].Value;
|
|
|
|
IQ_Pont[1].Gain_X = Compare_Cross[2].Gain_X; //0
|
|
IQ_Pont[1].Phase_Y = Compare_Cross[2].Phase_Y; //Q1
|
|
IQ_Pont[1].Value = Compare_Cross[2].Value;
|
|
|
|
IQ_Pont[2].Gain_X = Compare_Cross[6].Gain_X; //0
|
|
IQ_Pont[2].Phase_Y = Compare_Cross[6].Phase_Y;//Q2
|
|
IQ_Pont[2].Value = Compare_Cross[6].Value;
|
|
}
|
|
else if(((Compare_Temp.Gain_X & 0x2F)==0x01) || (Compare_Temp.Gain_X & 0x2F)==0x02) //gain Q1 or Q2
|
|
{
|
|
*X_Direct = (u8) 1;
|
|
IQ_Pont[0].Gain_X = Compare_Cross[0].Gain_X; //0
|
|
IQ_Pont[0].Phase_Y = Compare_Cross[0].Phase_Y; //0
|
|
IQ_Pont[0].Value = Compare_Cross[0].Value;
|
|
|
|
IQ_Pont[1].Gain_X = Compare_Cross[3].Gain_X; //Q1
|
|
IQ_Pont[1].Phase_Y = Compare_Cross[3].Phase_Y; //0
|
|
IQ_Pont[1].Value = Compare_Cross[3].Value;
|
|
|
|
IQ_Pont[2].Gain_X = Compare_Cross[7].Gain_X; //Q2
|
|
IQ_Pont[2].Phase_Y = Compare_Cross[7].Phase_Y;//0
|
|
IQ_Pont[2].Value = Compare_Cross[7].Value;
|
|
}
|
|
else if(((Compare_Temp.Gain_X & 0x2F)==0x21) || (Compare_Temp.Gain_X & 0x2F)==0x22) //gain I1 or I2
|
|
{
|
|
*X_Direct = (u8) 1;
|
|
IQ_Pont[0].Gain_X = Compare_Cross[0].Gain_X; //0
|
|
IQ_Pont[0].Phase_Y = Compare_Cross[0].Phase_Y; //0
|
|
IQ_Pont[0].Value = Compare_Cross[0].Value;
|
|
|
|
IQ_Pont[1].Gain_X = Compare_Cross[4].Gain_X; //I1
|
|
IQ_Pont[1].Phase_Y = Compare_Cross[4].Phase_Y; //0
|
|
IQ_Pont[1].Value = Compare_Cross[4].Value;
|
|
|
|
IQ_Pont[2].Gain_X = Compare_Cross[8].Gain_X; //I2
|
|
IQ_Pont[2].Phase_Y = Compare_Cross[8].Phase_Y;//0
|
|
IQ_Pont[2].Value = Compare_Cross[8].Value;
|
|
}
|
|
else //(0,0)
|
|
{
|
|
*X_Direct = (u8) 1;
|
|
IQ_Pont[0].Gain_X = Compare_Cross[0].Gain_X;
|
|
IQ_Pont[0].Phase_Y = Compare_Cross[0].Phase_Y;
|
|
IQ_Pont[0].Value = Compare_Cross[0].Value;
|
|
|
|
IQ_Pont[1].Gain_X = Compare_Cross[3].Gain_X; //Q1
|
|
IQ_Pont[1].Phase_Y = Compare_Cross[3].Phase_Y; //0
|
|
IQ_Pont[1].Value = Compare_Cross[3].Value;
|
|
|
|
IQ_Pont[2].Gain_X = Compare_Cross[4].Gain_X; //I1
|
|
IQ_Pont[2].Phase_Y = Compare_Cross[4].Phase_Y; //0
|
|
IQ_Pont[2].Value = Compare_Cross[4].Value;
|
|
}
|
|
return R850_Success;
|
|
}
|
|
|
|
|
|
R850_ErrCode R850_IQ( struct r850_priv*priv, struct R850_SectType* IQ_Pont)
|
|
{
|
|
struct R850_SectType Compare_IQ[3];
|
|
u8 X_Direction; // 1:X, 0:Y
|
|
|
|
//------- increase Filter gain max to let ADC read value significant ---------//
|
|
|
|
priv->regs[41] = (priv->regs[41] | 0xF0);
|
|
if(r850_wr(priv,41,priv->regs[41])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
|
|
//give a initial value, no useful
|
|
Compare_IQ[0].Gain_X = priv->regs[R850_IMR_GAIN_REG] & 0xD0;
|
|
Compare_IQ[0].Phase_Y = priv->regs[R850_IMR_PHASE_REG] & 0xD0;
|
|
|
|
|
|
// Determine X or Y
|
|
if(R850_IMR_Cross( priv,&Compare_IQ[0], &X_Direction) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if(X_Direction==1)
|
|
{
|
|
//compare and find min of 3 points. determine I/Q direction
|
|
if(R850_CompreCor(&Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
//increase step to find min value of this direction
|
|
if(R850_CompreStep(priv, &Compare_IQ[0], R850_IMR_GAIN_REG) != R850_Success) //X
|
|
return R850_Fail;
|
|
}
|
|
else
|
|
{
|
|
//compare and find min of 3 points. determine I/Q direction
|
|
if(R850_CompreCor(&Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
//increase step to find min value of this direction
|
|
if(R850_CompreStep(priv, &Compare_IQ[0], R850_IMR_PHASE_REG) != R850_Success) //Y
|
|
return R850_Fail;
|
|
}
|
|
|
|
//Another direction
|
|
if(X_Direction==1) //Y-direct
|
|
{
|
|
// if(R850_IQ_Tree( Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, R850_IMR_GAIN_REG, &Compare_IQ[0]) != R850_Success) //Y
|
|
if(R850_IQ_Tree5( priv,Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, R850_IMR_GAIN_REG, &Compare_IQ[0]) != R850_Success) //Y
|
|
|
|
return R850_Fail;
|
|
|
|
//compare and find min of 3 points. determine I/Q direction
|
|
if(R850_CompreCor(&Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
//increase step to find min value of this direction
|
|
if(R850_CompreStep(priv, &Compare_IQ[0], R850_IMR_PHASE_REG) != R850_Success) //Y
|
|
return R850_Fail;
|
|
}
|
|
else //X-direct
|
|
{
|
|
// if(R850_IQ_Tree( Compare_IQ[0].Phase_Y, Compare_IQ[0].Gain_X, R850_IMR_PHASE_REG, &Compare_IQ[0]) != R850_Success) //X
|
|
if(R850_IQ_Tree5(priv,Compare_IQ[0].Phase_Y, Compare_IQ[0].Gain_X, R850_IMR_PHASE_REG, &Compare_IQ[0]) != R850_Success) //X
|
|
return R850_Fail;
|
|
|
|
//compare and find min of 3 points. determine I/Q direction
|
|
if(R850_CompreCor(&Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
//increase step to find min value of this direction
|
|
if(R850_CompreStep(priv, &Compare_IQ[0], R850_IMR_GAIN_REG) != R850_Success) //X
|
|
return R850_Fail;
|
|
}
|
|
|
|
|
|
//--- Check 3 points again---//
|
|
if(X_Direction==1) //X-direct
|
|
{
|
|
if(R850_IQ_Tree(priv, Compare_IQ[0].Phase_Y, Compare_IQ[0].Gain_X, R850_IMR_PHASE_REG, &Compare_IQ[0]) != R850_Success) //X
|
|
return R850_Fail;
|
|
}
|
|
else //Y-direct
|
|
{
|
|
if(R850_IQ_Tree(priv, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, R850_IMR_GAIN_REG, &Compare_IQ[0]) != R850_Success) //Y
|
|
return R850_Fail;
|
|
}
|
|
|
|
if(R850_CompreCor(&Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
//Section-9 check
|
|
if(R850_Section(priv, &Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
//clear IQ_Cap = 0
|
|
//Compare_IQ[0].Iqcap = priv->regs[R850_IMR_IQCAP_REG] & 0x3F;
|
|
Compare_IQ[0].Iqcap = 0;
|
|
|
|
if(R850_IMR_Iqcap(priv, &Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
*IQ_Pont = Compare_IQ[0];
|
|
|
|
//reset gain/phase/iqcap control setting
|
|
//R850_I2C.RegAddr = R850_IMR_GAIN_REG;
|
|
priv->regs[R850_IMR_GAIN_REG] = priv->regs[R850_IMR_GAIN_REG] & 0xD0;
|
|
if(r850_wr(priv,R850_IMR_GAIN_REG,priv->regs[R850_IMR_GAIN_REG])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
priv->regs[R850_IMR_PHASE_REG] = priv->regs[R850_IMR_PHASE_REG] & 0xD0;
|
|
if(r850_wr(priv,R850_IMR_PHASE_REG,priv->regs[R850_IMR_PHASE_REG])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
priv->regs[R850_IMR_IQCAP_REG] = priv->regs[R850_IMR_IQCAP_REG] & 0x3F;
|
|
if(r850_wr(priv,R850_IMR_IQCAP_REG,priv->regs[R850_IMR_IQCAP_REG])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------------------//
|
|
// purpose: search surrounding points from previous point
|
|
// try (x-1), (x), (x+1) columns, and find min IMR result point
|
|
// input: IQ_Pont: previous point data(IMR Gain, Phase, ADC Result, RefRreq)
|
|
// will be updated to final best point
|
|
// output: TRUE or FALSE
|
|
//----------------------------------------------------------------------------------------//
|
|
R850_ErrCode R850_F_IMR(struct r850_priv *priv, struct R850_SectType* IQ_Pont)
|
|
{
|
|
struct R850_SectType Compare_IQ[3];
|
|
struct R850_SectType Compare_Bet[3];
|
|
|
|
//------- increase Filter gain max to let ADC read value significant ---------//
|
|
priv->regs[41] = (priv->regs[41] | 0xF0);
|
|
if(r850_wr(priv,41,priv->regs[41]) != 0)
|
|
return R850_Fail;
|
|
|
|
//Try X-1 column and save min result to Compare_Bet[0]
|
|
if((IQ_Pont->Gain_X & 0x0F) == 0x00)
|
|
{
|
|
Compare_IQ[0].Gain_X = ((IQ_Pont->Gain_X) & 0xDF) + 1; //Q-path, Gain=1
|
|
}
|
|
else
|
|
{
|
|
Compare_IQ[0].Gain_X = IQ_Pont->Gain_X - 1; //left point
|
|
}
|
|
Compare_IQ[0].Phase_Y = IQ_Pont->Phase_Y;
|
|
|
|
if(R850_IQ_Tree(priv, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, R850_IMR_GAIN_REG, &Compare_IQ[0]) != R850_Success) // y-direction
|
|
return R850_Fail;
|
|
|
|
if(R850_CompreCor(&Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
Compare_Bet[0].Gain_X = Compare_IQ[0].Gain_X;
|
|
Compare_Bet[0].Phase_Y = Compare_IQ[0].Phase_Y;
|
|
Compare_Bet[0].Value = Compare_IQ[0].Value;
|
|
|
|
//Try X column and save min result to Compare_Bet[1]
|
|
Compare_IQ[0].Gain_X = IQ_Pont->Gain_X;
|
|
Compare_IQ[0].Phase_Y = IQ_Pont->Phase_Y;
|
|
|
|
if(R850_IQ_Tree(priv, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, R850_IMR_GAIN_REG, &Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if(R850_CompreCor(&Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
Compare_Bet[1].Gain_X = Compare_IQ[0].Gain_X;
|
|
Compare_Bet[1].Phase_Y = Compare_IQ[0].Phase_Y;
|
|
Compare_Bet[1].Value = Compare_IQ[0].Value;
|
|
|
|
//Try X+1 column and save min result to Compare_Bet[2]
|
|
if((IQ_Pont->Gain_X & 0x0F) == 0x00)
|
|
Compare_IQ[0].Gain_X = ((IQ_Pont->Gain_X) | 0x20) + 1; //I-path, Gain=1
|
|
else
|
|
Compare_IQ[0].Gain_X = IQ_Pont->Gain_X + 1;
|
|
Compare_IQ[0].Phase_Y = IQ_Pont->Phase_Y;
|
|
|
|
if(R850_IQ_Tree(priv, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, R850_IMR_GAIN_REG, &Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if(R850_CompreCor(&Compare_IQ[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
Compare_Bet[2].Gain_X = Compare_IQ[0].Gain_X;
|
|
Compare_Bet[2].Phase_Y = Compare_IQ[0].Phase_Y;
|
|
Compare_Bet[2].Value = Compare_IQ[0].Value;
|
|
|
|
if(R850_CompreCor(&Compare_Bet[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
//clear IQ_Cap = 0
|
|
//Compare_Bet[0].Iqcap = priv->regs[3] & 0xFC;
|
|
Compare_Bet[0].Iqcap = 0;
|
|
|
|
if(R850_IMR_Iqcap(priv, &Compare_Bet[0]) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
*IQ_Pont = Compare_Bet[0];
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
|
|
|
|
R850_ErrCode R850_InitReg(struct r850_priv *priv)//ok
|
|
{
|
|
u8 InitArrayCunt = 0;
|
|
|
|
|
|
//Write Full Table, Set Xtal Power = highest at initial
|
|
//R850_I2C_Len.RegAddr = 0;
|
|
//R850_I2C_Len.Len = R850_REG_NUM;
|
|
u8 XtalCap;
|
|
u8 Capx;
|
|
u8 Capx_3_0, Capxx;
|
|
int ret=0;
|
|
|
|
if(priv->R850_clock_out==1)
|
|
{
|
|
if(priv->R850_Xtal_cap>31)
|
|
{
|
|
XtalCap = 1; //10
|
|
Capx = priv->R850_Xtal_cap-10;
|
|
}
|
|
else
|
|
{
|
|
XtalCap = 0; //0
|
|
Capx = priv->R850_Xtal_cap;
|
|
}
|
|
|
|
Capxx = Capx & 0x01;
|
|
Capx_3_0 = Capx >> 1;
|
|
|
|
// Set Xtal Cap R33[6:3], R34[3] XtalCap => R33[7]
|
|
R850_iniArray[0][33] = 0x01 | (Capx_3_0 << 3) | ( XtalCap << 7);
|
|
R850_iniArray[1][33] = 0x01 | (Capx_3_0 << 3) | ( XtalCap << 7);
|
|
R850_iniArray[2][33] = 0x01 | (Capx_3_0 << 3) | ( XtalCap << 7);
|
|
// Set GM=strong
|
|
R850_iniArray[0][34] = 0x04 | (Capxx << 3);
|
|
R850_iniArray[1][34] = 0x04 | (Capxx << 3);
|
|
R850_iniArray[2][34] = 0x04 | (Capxx << 3);
|
|
}
|
|
else
|
|
{
|
|
R850_iniArray[0][33]= 0x01;
|
|
R850_iniArray[1][33]= 0x01;
|
|
R850_iniArray[2][33]= 0x01;
|
|
|
|
R850_iniArray[0][34]= 0x74;
|
|
R850_iniArray[1][34]= 0x74;
|
|
R850_iniArray[2][34]= 0x74;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(priv->cfg->R850_Xtal == 24000)
|
|
{
|
|
for(InitArrayCunt = 8; InitArrayCunt<R850_REG_NUM; InitArrayCunt ++)
|
|
{
|
|
//R850_I2C_Len.Data[InitArrayCunt] = R850_iniArray[0][InitArrayCunt];
|
|
priv->regs[InitArrayCunt] = R850_iniArray[0][InitArrayCunt];
|
|
}
|
|
}
|
|
else if(priv->cfg->R850_Xtal == 16000)
|
|
{
|
|
for(InitArrayCunt = 8; InitArrayCunt<R850_REG_NUM; InitArrayCunt ++)
|
|
{
|
|
//R850_I2C_Len.Data[InitArrayCunt] = R850_iniArray[1][InitArrayCunt];
|
|
priv->regs[InitArrayCunt] = R850_iniArray[1][InitArrayCunt];
|
|
}
|
|
}
|
|
else if(priv->cfg->R850_Xtal == 27000)
|
|
{
|
|
for(InitArrayCunt = 8; InitArrayCunt<R850_REG_NUM; InitArrayCunt ++)
|
|
{
|
|
//R850_I2C_Len.Data[InitArrayCunt] = R850_iniArray[2][InitArrayCunt];
|
|
priv->regs[InitArrayCunt] = R850_iniArray[2][InitArrayCunt];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//no support now
|
|
return R850_Fail;
|
|
}
|
|
|
|
|
|
//Xtal cap
|
|
|
|
if(priv->R850_clock_out == 1)
|
|
{
|
|
R850_SetXtalPW( priv, R850_XTAL_HIGHEST);
|
|
R850_SetXtalCap_No_Write(priv, priv->R850_Xtal_cap);
|
|
}
|
|
else if(priv->R850_clock_out == 0)
|
|
{
|
|
R850_SetXtalPW(priv, R850_XTAL_LOWEST);
|
|
R850_SetXtalCap_No_Write(priv, 0);
|
|
//gm off
|
|
R850_Set_XTAL_GM(priv, 1); //3:xtal gm off
|
|
}
|
|
else
|
|
{
|
|
R850_SetXtalCap_No_Write(priv, priv->R850_Xtal_cap);
|
|
}
|
|
|
|
ret = r850_wrm(priv,8,&priv->regs[8],40);
|
|
if(ret!=0)
|
|
return R850_Fail;
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
R850_ErrCode R850_Cal_Prepare(struct r850_priv *priv,u8 u1CalFlag)
|
|
{
|
|
//R850_Cal_Info_Type Cal_Info;
|
|
u8 InitArrayCunt = 0;
|
|
|
|
//Write Full Table, include PLL & RingPLL all settings
|
|
//R850_I2C_Len.RegAddr = 0;
|
|
//R850_I2C_Len.Len = R850_REG_NUM;
|
|
|
|
int ret = 0;
|
|
|
|
switch(u1CalFlag)
|
|
{
|
|
case R850_IMR_CAL:
|
|
if(priv->cfg->R850_Xtal == 24000)
|
|
{
|
|
//542MHz
|
|
for(InitArrayCunt = 8; InitArrayCunt<R850_REG_NUM; InitArrayCunt ++)
|
|
{
|
|
// R850_I2C_Len.Data[InitArrayCunt] = R850_IMR_CAL_Array[0][InitArrayCunt];
|
|
priv->regs[InitArrayCunt] = R850_IMR_CAL_Array[0][InitArrayCunt];
|
|
}
|
|
}
|
|
else if(priv->cfg->R850_Xtal == 16000)
|
|
{
|
|
//542MHz
|
|
for(InitArrayCunt = 8; InitArrayCunt<R850_REG_NUM; InitArrayCunt ++)
|
|
{
|
|
// R850_I2C_Len.Data[InitArrayCunt] = R850_IMR_CAL_Array[1][InitArrayCunt];
|
|
priv->regs[InitArrayCunt] = R850_IMR_CAL_Array[1][InitArrayCunt];
|
|
}
|
|
}
|
|
else if(priv->cfg->R850_Xtal == 27000)
|
|
{
|
|
//542MHz
|
|
for(InitArrayCunt = 8; InitArrayCunt<R850_REG_NUM; InitArrayCunt ++)
|
|
{
|
|
// R850_I2C_Len.Data[InitArrayCunt] = R850_IMR_CAL_Array[2][InitArrayCunt];
|
|
priv->regs[InitArrayCunt] = R850_IMR_CAL_Array[2][InitArrayCunt];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//no support now
|
|
return R850_Fail;
|
|
}
|
|
break;
|
|
|
|
case R850_IMR_LNA_CAL:
|
|
|
|
break;
|
|
|
|
case R850_LPF_CAL:
|
|
|
|
if(priv->cfg->R850_Xtal == 24000)
|
|
{
|
|
for(InitArrayCunt = 8; InitArrayCunt<R850_REG_NUM; InitArrayCunt ++)
|
|
{
|
|
// R850_I2C_Len.Data[InitArrayCunt] = R850_LPF_CAL_Array[0][InitArrayCunt];
|
|
priv->regs[InitArrayCunt] = R850_LPF_CAL_Array[0][InitArrayCunt];
|
|
}
|
|
}
|
|
else if(priv->cfg->R850_Xtal == 16000)
|
|
{
|
|
for(InitArrayCunt = 8; InitArrayCunt<R850_REG_NUM; InitArrayCunt ++)
|
|
{
|
|
// R850_I2C_Len.Data[InitArrayCunt] = R850_LPF_CAL_Array[1][InitArrayCunt];
|
|
priv->regs[InitArrayCunt] = R850_LPF_CAL_Array[1][InitArrayCunt];
|
|
}
|
|
}
|
|
else if(priv->cfg->R850_Xtal == 27000)
|
|
{
|
|
for(InitArrayCunt = 8; InitArrayCunt<R850_REG_NUM; InitArrayCunt ++)
|
|
{
|
|
// R850_I2C_Len.Data[InitArrayCunt] = R850_LPF_CAL_Array[2][InitArrayCunt];
|
|
priv->regs[InitArrayCunt] = R850_LPF_CAL_Array[2][InitArrayCunt];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//no support 27MHz now
|
|
return R850_Fail;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
//Xtal cap
|
|
if(priv->R850_clock_out == 1)
|
|
{
|
|
R850_SetXtalPW(priv, R850_XTAL_HIGHEST);
|
|
R850_SetXtalCap_No_Write( priv, priv->R850_Xtal_cap);
|
|
}
|
|
else if(priv->R850_clock_out == 0)
|
|
{
|
|
R850_SetXtalPW(priv, R850_XTAL_LOWEST);
|
|
R850_SetXtalCap_No_Write(priv, 0);
|
|
//gm off
|
|
R850_Set_XTAL_GM(priv, 1); //3:xtal gm off
|
|
}
|
|
else
|
|
{
|
|
R850_SetXtalCap_No_Write(priv, priv->R850_Xtal_cap);
|
|
}
|
|
|
|
ret = r850_wrm(priv,8,&priv->regs[8],40);
|
|
if(ret)
|
|
return R850_Fail;
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
|
|
R850_ErrCode R850_IMR(struct r850_priv* priv, u8 IMR_MEM, u8 IM_Flag)
|
|
{
|
|
|
|
//-------------------------------------------------------------------
|
|
//to do
|
|
u32 RingVCO = 0;
|
|
u32 RingFreq = 0;
|
|
u32 RingRef = priv->cfg->R850_Xtal;
|
|
u8 divnum_ring = 0;
|
|
//u8 u1MixerGain = 6; //fix at initial test
|
|
|
|
u8 IMR_Gain = 0;
|
|
u8 IMR_Phase = 0;
|
|
struct R850_SectType IMR_POINT;
|
|
|
|
//priv->regs[24] &= 0x3F; //clear ring_div1, R24[7:6]
|
|
//priv->regs[25] &= 0xFC; //clear ring_div2, R25[1:0]
|
|
|
|
if(priv->cfg->R850_Xtal==24000) //24M
|
|
{
|
|
divnum_ring = 17;
|
|
}
|
|
else if(priv->cfg->R850_Xtal==16000) //16M
|
|
{
|
|
divnum_ring = 25; //3200/8/16. 32>divnum>7
|
|
}
|
|
else if(priv->cfg->R850_Xtal==27000) //27M
|
|
{
|
|
divnum_ring = 15; //3200/8/16. 32>divnum>7
|
|
}
|
|
else //not support
|
|
{
|
|
return R850_Fail;
|
|
}
|
|
|
|
RingVCO = (divnum_ring)* 8 * RingRef;
|
|
RingFreq = RingVCO/48;
|
|
|
|
switch(IMR_MEM)
|
|
{
|
|
case 0: // RingFreq = 136.0M (16M, 24M) ; RingFreq = 135.0M (27M) ;
|
|
RingFreq = RingVCO/24;
|
|
priv->regs[36] = (priv->regs[36] & 0xFC) | 0x02; // ring_div1 /6 (2) R34[6:5] => R36[1:0]
|
|
priv->regs[36] = (priv->regs[36] & 0xF3) | 0x08; // ring_div2 /4 (2) R35[1:0] => R36[3:2]
|
|
break;
|
|
case 1: // RingFreq = 326M (16M, 24M) ; RingFreq = 324.0M (27M) ;
|
|
RingFreq = RingVCO/10;
|
|
priv->regs[36] = (priv->regs[36] & 0xFC) | 0x01; // ring_div1 /5 (1) R34[6:5] => R36[1:0]
|
|
priv->regs[36] = (priv->regs[36] & 0xF3) | 0x04; // ring_div2 /2 (1) R35[1:0] => R36[3:2]
|
|
break;
|
|
case 2: // RingFreq = 544M (16M, 24M) ; RingFreq = 540.0M (27M) ;
|
|
RingFreq = RingVCO/6;
|
|
priv->regs[36] = (priv->regs[36] & 0xFC) | 0x02; // ring_div1 /6 (2) R34[6:5] => R36[1:0]
|
|
priv->regs[36] = (priv->regs[36] & 0xF3) | 0x00; // ring_div2 /1 (0) R35[1:0] => R36[3:2]
|
|
break;
|
|
case 3: // RingFreq = 816M (16M, 24M) ; RingFreq = 810.0M (27M) ;
|
|
RingFreq = RingVCO/4;
|
|
priv->regs[36] = (priv->regs[36] & 0xFC) | 0x00; // ring_div1 /4 (0) R34[6:5] => R36[1:0]
|
|
priv->regs[36] = (priv->regs[36] & 0xF3) | 0x00; // ring_div2 /1 (0) R35[1:0] => R36[3:2]
|
|
break;
|
|
case 4: // RingFreq = 200M (16M, 24M) ; RingFreq = 202M (27M) ;
|
|
RingFreq = RingVCO/16;
|
|
priv->regs[36] = (priv->regs[36] & 0xFC) | 0x00; // ring_div1 /4 (0) R34[6:5] => R36[1:0]
|
|
priv->regs[36] = (priv->regs[36] & 0xF3) | 0x08; // ring_div2 /4 (2) R35[1:0] => R36[3:2]
|
|
break;
|
|
case 5: // RingFreq = 136M (16M, 24M) ; RingFreq = 135.0M (27M) ;
|
|
RingFreq = RingVCO/24;
|
|
priv->regs[36] = (priv->regs[36] & 0xFC) | 0x02; // ring_div1 /6 (2) R34[6:5] => R36[1:0]
|
|
priv->regs[36] = (priv->regs[36] & 0xF3) | 0x08; // ring_div2 /4 (2) R35[1:0] => R36[3:2]
|
|
break;
|
|
case 6: // RingFreq = 326M (16M, 24M) ; RingFreq = 324.0M (27M) ;
|
|
RingFreq = RingVCO/10;
|
|
priv->regs[36] = (priv->regs[36] & 0xFC) | 0x01; // ring_div1 /5 (1) R34[6:5] => R36[1:0]
|
|
priv->regs[36] = (priv->regs[36] & 0xF3) | 0x04; // ring_div2 /2 (1) R35[1:0] => R36[3:2]
|
|
break;
|
|
case 7: // RingFreq = 544M (16M, 24M) ; RingFreq = 540.0M (27M) ;
|
|
RingFreq = RingVCO/6;
|
|
priv->regs[36] = (priv->regs[36] & 0xFC) | 0x02; // ring_div1 /6 (2) R34[6:5] => R36[1:0]
|
|
priv->regs[36] = (priv->regs[36] & 0xF3) | 0x00; // ring_div2 /1 (0) R35[1:0] => R36[3:2]
|
|
break;
|
|
case 8: // RingFreq = 816M (16M, 24M) ; RingFreq = 810.0M (27M) ;
|
|
RingFreq = RingVCO/4;
|
|
priv->regs[36] = (priv->regs[36] & 0xFC) | 0x00; // ring_div1 /4 (0) R34[6:5] => R36[1:0]
|
|
priv->regs[36] = (priv->regs[36] & 0xF3) | 0x00; // ring_div2 /1 (0) R35[1:0] => R36[3:2]
|
|
break;
|
|
case 9: // RingFreq = 200M (16M, 24M) ; RingFreq = 202M (27M) ;
|
|
RingFreq = RingVCO/16;
|
|
priv->regs[36] = (priv->regs[36] & 0xFC) | 0x00; // ring_div1 /4 (0) R34[6:5] => R36[1:0]
|
|
priv->regs[36] = (priv->regs[36] & 0xF3) | 0x08; // ring_div2 /4 (2) R35[1:0] => R36[3:2]
|
|
break;
|
|
default: // RingFreq = 544M (16M, 24M) ; RingFreq = 540.0M (27M) ;
|
|
RingFreq = RingVCO/6;
|
|
priv->regs[36] = (priv->regs[36] & 0xFC) | 0x02; // ring_div1 /6 (2) R34[6:5] => R36[1:0]
|
|
priv->regs[36] = (priv->regs[36] & 0xF3) | 0x00; // ring_div2 /1 (0) R35[1:0] => R36[3:2]
|
|
break;
|
|
}
|
|
|
|
//write RingPLL setting, R34[4:0] => R35[4:0]
|
|
priv->regs[35] = (priv->regs[35] & 0xE0) | divnum_ring; //ring_div_num, R34[4:0]
|
|
|
|
if(RingVCO>=3200000)
|
|
priv->regs[35] = (priv->regs[35] & 0xBF); //vco_band=high, R34[7]=0 => R35[6]
|
|
else
|
|
priv->regs[35] = (priv->regs[35] | 0x40); //vco_band=low, R34[7]=1 => R35[6]
|
|
|
|
//write RingPLL setting, R35
|
|
if(r850_wr(priv,35,priv->regs[35])!=0)
|
|
return R850_Fail;
|
|
|
|
//write RingPLL setting, R36
|
|
if(r850_wr(priv,36,priv->regs[36])!=0)
|
|
return R850_Fail;
|
|
|
|
//Ring PLL power initial at "min_lp"
|
|
/*
|
|
//Ring PLL power, R25[2:1]
|
|
if((RingFreq>0) && (RingFreq<R850_RING_POWER_FREQ))
|
|
priv->regs[25] = (priv->regs[25] & 0xF9) | 0x04; //R25[2:1]=2'b10; min_lp
|
|
else
|
|
priv->regs[25] = (priv->regs[25] & 0xF9) | 0x00; //R25[2:1]=2'b00; min
|
|
|
|
R850_I2C.RegAddr = 0x19;
|
|
R850_I2C.Data = priv->regs[25];
|
|
if(I2C_Write( &R850_I2C) != R850_Success)
|
|
return R850_Fail;
|
|
*/
|
|
|
|
{
|
|
//Must do MUX before PLL()
|
|
if(R850_MUX( priv,RingFreq - R850_IMR_IF, RingFreq, R850_STD_SIZE) != R850_Success) //IMR MUX (LO, RF)
|
|
return R850_Fail;
|
|
|
|
priv->R850_IF_GOLOBAL = R850_IMR_IF;
|
|
if(R850_PLL(priv, (RingFreq - R850_IMR_IF), R850_STD_SIZE) != R850_Success) //IMR PLL
|
|
return R850_Fail;
|
|
|
|
//Img_R = normal
|
|
priv->regs[19] = (priv->regs[19] & 0xEF); //R20[7]=0 => R19[4]=0
|
|
// Mixer Amp LPF=7 (0 is widest)
|
|
priv->regs[19] = (priv->regs[19] & 0xF8) | (7);
|
|
if(r850_wr(priv,19,priv->regs[19])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
if(IMR_MEM==4)
|
|
{
|
|
//output atten
|
|
priv->regs[36] = (priv->regs[36] & 0xCF) | (0x10); // R41[3:0]=0
|
|
}
|
|
else
|
|
{
|
|
//output atten
|
|
priv->regs[36] = (priv->regs[36] & 0xCF) | (0x30); // R41[3:0]=0
|
|
|
|
}
|
|
if(r850_wr(priv,36,priv->regs[36])!=0)
|
|
return R850_Fail;
|
|
|
|
//Mixer Gain = 8
|
|
priv->regs[41] = (priv->regs[41] & 0xF0) | (8); //R41[3:0]=0
|
|
if(r850_wr(priv,41,priv->regs[41])!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
//clear IQ_cap
|
|
//IMR_POINT.Iqcap = priv->regs[19] & 0x3F;
|
|
IMR_POINT.Iqcap = 0;
|
|
|
|
if(IM_Flag == TRUE)
|
|
{
|
|
if(R850_IQ( priv, &IMR_POINT) != R850_Success)
|
|
return R850_Fail;
|
|
}
|
|
else //IMR_MEM 1, 0, 3, 4
|
|
{
|
|
if((IMR_MEM==1) || (IMR_MEM==3))
|
|
{
|
|
IMR_POINT.Gain_X = priv->imr_data[2].Gain_X; //node 3
|
|
IMR_POINT.Phase_Y = priv->imr_data[2].Phase_Y;
|
|
IMR_POINT.Value = priv->imr_data[2].Value;
|
|
}
|
|
else if((IMR_MEM==0) || (IMR_MEM==4))
|
|
{
|
|
IMR_POINT.Gain_X = priv->imr_data[1].Gain_X;
|
|
IMR_POINT.Phase_Y = priv->imr_data[1].Phase_Y;
|
|
IMR_POINT.Value = priv->imr_data[1].Value;
|
|
}
|
|
|
|
if(R850_F_IMR(priv,&IMR_POINT) != R850_Success)
|
|
return R850_Fail;
|
|
}
|
|
}
|
|
|
|
//Save IMR Value
|
|
priv->imr_data[IMR_MEM].Gain_X = IMR_POINT.Gain_X;
|
|
priv->imr_data[IMR_MEM].Phase_Y = IMR_POINT.Phase_Y;
|
|
priv->imr_data[IMR_MEM].Value = IMR_POINT.Value;
|
|
priv->imr_data[IMR_MEM].Iqcap = IMR_POINT.Iqcap;
|
|
|
|
IMR_Gain = priv->imr_data[IMR_MEM].Gain_X & 0x2F; //R20[3:0]
|
|
IMR_Phase = priv->imr_data[IMR_MEM].Phase_Y & 0x2F; //R21[3:0]
|
|
|
|
|
|
if(((IMR_Gain & 0x0F)>6) || ((IMR_Phase & 0x0F)>6))
|
|
{
|
|
priv->R850_IMR_Cal_Result = 1; //fail
|
|
}
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
//----------------------------------------------------------------------//
|
|
// R850_GetRfRssi( ): Get RF RSSI //
|
|
// 1st parameter: input RF Freq (KHz) //
|
|
// 2nd parameter: input Standard //
|
|
// 3rd parameter: output signal level (dBm*1000) //
|
|
// 4th parameter: output RF max gain indicator (1:max gain) //
|
|
//-----------------------------------------------------------------------//
|
|
R850_ErrCode R850_GetRfRssi( struct r850_priv*priv,u32 RF_Freq_Khz, enum R850_Standard_Type RT_Standard, s32 *RfLevelDbm, u8 *fgRfMaxGain)
|
|
{
|
|
//u8 bPulseFlag;
|
|
struct R850_RF_Gain_Info rf_gain_info;
|
|
u16 acc_lna_gain;
|
|
u16 acc_rfbuf_gain;
|
|
u16 acc_mixer_gain;
|
|
u16 rf_total_gain;
|
|
u8 u1FreqIndex;
|
|
s16 u2FreqFactor=0;
|
|
u8 u1LnaGainqFactorIdx;
|
|
s32 rf_rssi;
|
|
s32 fine_tune = 0; //for find tune
|
|
u8 rf_limit;
|
|
u8 mixer_limit;
|
|
u8 mixer_1315_gain = 0;
|
|
u8 filter_limit;
|
|
//{50~135, 135~215, 215~265, 265~315, 315~325, 325~345, 345~950}
|
|
s8 R850_Start_Gain_Cal_By_Freq[7] = {10, -10, -30, -10, 20, 20, 20};
|
|
u8 buf[6];
|
|
|
|
|
|
r850_rd(priv,0,buf,6);
|
|
|
|
//bPulseFlag = ((R850_I2C_Len.Data[1] & 0x40) >> 6);
|
|
|
|
rf_gain_info.RF_gain1 = (buf[3] & 0x1F); //lna
|
|
rf_gain_info.RF_gain2 = (buf[4] & 0x0F); //rf
|
|
rf_gain_info.RF_gain3 = (buf[4] & 0xF0)>>4; //mixer
|
|
rf_gain_info.RF_gain4 = (buf[5] & 0x0F); //filter
|
|
|
|
|
|
//max gain indicator
|
|
if((rf_gain_info.RF_gain1==31) && (rf_gain_info.RF_gain2==15) && (rf_gain_info.RF_gain3==15) && (rf_gain_info.RF_gain4==15))
|
|
*fgRfMaxGain = 1;
|
|
else
|
|
*fgRfMaxGain = 0;
|
|
rf_limit = (((priv->regs[18]&0x04)>>1) + ((priv->regs[16]&0x40)>>6));
|
|
|
|
if(rf_limit==0)
|
|
rf_limit = 15;
|
|
else if(rf_limit==1)
|
|
rf_limit = 11;
|
|
else if(rf_limit==2)
|
|
rf_limit = 13;
|
|
else
|
|
rf_limit = 9;
|
|
|
|
mixer_limit = (((priv->regs[22]&0xC0)>>6)*2)+6; //0=6, 1=8, 2=10, 3=12
|
|
mixer_1315_gain = ((priv->regs[25]&0x02)>>1); //0:original, 1:ctrl by mixamp (>10)
|
|
|
|
if( rf_gain_info.RF_gain2 > rf_limit)
|
|
rf_gain_info.RF_gain2 = rf_limit;
|
|
|
|
if((rf_gain_info.RF_gain3 > 12)&&(mixer_1315_gain==1))
|
|
mixer_1315_gain = rf_gain_info.RF_gain3; //save 0 or 13 or 14 or 15
|
|
|
|
if( rf_gain_info.RF_gain3 > mixer_limit)
|
|
rf_gain_info.RF_gain3 = mixer_limit;
|
|
|
|
|
|
filter_limit = (priv->regs[22]&0x01);
|
|
if(filter_limit==1)
|
|
filter_limit = 15;
|
|
else
|
|
filter_limit = 13;
|
|
|
|
if( rf_gain_info.RF_gain4 > filter_limit)
|
|
rf_gain_info.RF_gain4 = filter_limit;
|
|
|
|
|
|
//coarse adjustment
|
|
if(RF_Freq_Khz<135000) //<135M
|
|
{
|
|
u1FreqIndex = 0;
|
|
u2FreqFactor = R850_Start_Gain_Cal_By_Freq[0];
|
|
}
|
|
else if((RF_Freq_Khz>=135000)&&(RF_Freq_Khz<215000)) //135~215M
|
|
{
|
|
u1FreqIndex = 0;
|
|
u2FreqFactor = R850_Start_Gain_Cal_By_Freq[1];
|
|
}
|
|
else if((RF_Freq_Khz>=215000)&&(RF_Freq_Khz<265000)) //215~265M
|
|
{
|
|
u1FreqIndex = 1;
|
|
u2FreqFactor = R850_Start_Gain_Cal_By_Freq[2];
|
|
}
|
|
else if((RF_Freq_Khz>=265000)&&(RF_Freq_Khz<315000)) //265~315M
|
|
{
|
|
u1FreqIndex = 1;
|
|
u2FreqFactor = R850_Start_Gain_Cal_By_Freq[3];
|
|
}
|
|
else if((RF_Freq_Khz>=315000)&&(RF_Freq_Khz<325000)) //315~325M
|
|
{
|
|
u1FreqIndex = 1;
|
|
u2FreqFactor = R850_Start_Gain_Cal_By_Freq[4];
|
|
}
|
|
else if((RF_Freq_Khz>=325000)&&(RF_Freq_Khz<345000)) //325~345M
|
|
{
|
|
u1FreqIndex = 1;
|
|
u2FreqFactor = R850_Start_Gain_Cal_By_Freq[5];
|
|
}
|
|
else if((RF_Freq_Khz>=345000)&&(RF_Freq_Khz<420000)) //345~420M
|
|
{
|
|
u1FreqIndex = 1;
|
|
u2FreqFactor = R850_Start_Gain_Cal_By_Freq[6];
|
|
}
|
|
else if((RF_Freq_Khz>=420000)&&(RF_Freq_Khz<710000)) //420~710M
|
|
{
|
|
u1FreqIndex = 2;
|
|
u2FreqFactor = R850_Start_Gain_Cal_By_Freq[6];
|
|
|
|
}
|
|
else // >=710
|
|
{
|
|
u1FreqIndex = 3;
|
|
u2FreqFactor = R850_Start_Gain_Cal_By_Freq[6];
|
|
}
|
|
|
|
|
|
//LNA Gain
|
|
acc_lna_gain = R850_Lna_Acc_Gain[u1FreqIndex][rf_gain_info.RF_gain1];
|
|
|
|
|
|
|
|
//fine adjustment
|
|
//Cal LNA Gain by Freq
|
|
|
|
//Method 2 : All frequencies are finely adjusted..
|
|
|
|
|
|
if(rf_gain_info.RF_gain1 >= 10)
|
|
{
|
|
u1LnaGainqFactorIdx = (u8) ((RF_Freq_Khz-50000) / 10000);
|
|
|
|
if( ((RF_Freq_Khz-50000) - (u1LnaGainqFactorIdx * 10000))>=5000)
|
|
u1LnaGainqFactorIdx +=1;
|
|
acc_lna_gain += (u16)(Lna_Acc_Gain_offset[u1LnaGainqFactorIdx]);
|
|
|
|
}
|
|
|
|
//RF buf
|
|
acc_rfbuf_gain = R850_Rf_Acc_Gain[rf_gain_info.RF_gain2];
|
|
if(RF_Freq_Khz<=300000)
|
|
acc_rfbuf_gain += (rf_gain_info.RF_gain2 * 1);
|
|
else if (RF_Freq_Khz>=600000)
|
|
acc_rfbuf_gain -= (rf_gain_info.RF_gain2 * 1);
|
|
|
|
//Mixer
|
|
acc_mixer_gain = R850_Mixer_Acc_Gain [rf_gain_info.RF_gain3] ;
|
|
|
|
if((mixer_1315_gain!=0) && (mixer_1315_gain!=1)) //Gain 13 or 14 or 15
|
|
acc_mixer_gain = acc_mixer_gain + (R850_Mixer_Acc_Gain[mixer_1315_gain] - R850_Mixer_Acc_Gain[12]);
|
|
|
|
|
|
|
|
//Add Rf Buf and Mixer Gain
|
|
rf_total_gain = acc_lna_gain + acc_rfbuf_gain + acc_mixer_gain + rf_gain_info.RF_gain4*153/10;
|
|
|
|
rf_rssi = fine_tune - (s32) (rf_total_gain - u2FreqFactor);
|
|
|
|
|
|
*RfLevelDbm = rf_rssi*100;
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------//
|
|
// R850_GetIfRssi( ): Get IF VGA GAIN //
|
|
// 1st parameter: return IF VGA Gain (dB*100) //
|
|
//-----------------------------------------------------------------------//
|
|
R850_ErrCode R850_GetIfRssi(struct r850_priv*priv,s32 *VgaGain)
|
|
{
|
|
u8 adc_read;
|
|
u8 buf[2];
|
|
//Optimize value
|
|
u16 vga_table[64] = { //*100
|
|
0, 0, 20, 20, 30, 50, 60, 80, 110, 130, 130, 160, //0~11
|
|
200, 240, 280, 330, 380, 410, 430, 480, 530, 590, //12~21
|
|
640, 690, 730, 760, 780, 810, 840, 890, 930, 950, //22~31
|
|
980, 1010, 1010, 1030, 1060, 1100, 1120, 1140, 1170, 1180, //32~41
|
|
1190, 1210, 1220, 1260, 1270, 1300, 1320, 1320, 1340, 1340, //42~51
|
|
1360, 1390, 1400, 1420, 1440, 1450, 1460, 1480, 1490, 1510, //52~61
|
|
1550, 1600 //62~63
|
|
};
|
|
|
|
//ADC sel : vagc, R22[3:2]=2
|
|
priv->regs[22] = (priv->regs[22] & 0xF3) | 0x08;
|
|
if(r850_wr(priv,22,priv->regs[22]) != 0)
|
|
return R850_Fail;
|
|
|
|
//IF_AGC read, R18[5]=1
|
|
priv->regs[18] = priv->regs[18] | 0x20;
|
|
if(r850_wr(priv,18,priv->regs[18]) != 0)
|
|
return R850_Fail;
|
|
|
|
//ADC power on, R11[1]=0
|
|
priv->regs[11] = priv->regs[11] & 0xFD;
|
|
if(r850_wr(priv,11,priv->regs[11]) != 0)
|
|
return R850_Fail;
|
|
|
|
//read adc value
|
|
r850_rd(priv,0x00,buf,2);
|
|
adc_read = (buf[1] & 0x3F);
|
|
|
|
*VgaGain = vga_table[adc_read];
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
|
|
// R850_GetRfRssi( ): Get RF RSSI //
|
|
// 1st parameter: input RF Freq (KHz) //
|
|
// 2nd parameter: input Standard //
|
|
// 3rd parameter: return signal level indicator (dBm) //
|
|
//-----------------------------------------------------------------------//
|
|
R850_ErrCode R850_GetTotalRssi( struct r850_priv*priv, u32 RF_Freq_Khz, enum R850_Standard_Type RT_Standard, s32 *RssiDbm)
|
|
{
|
|
s32 rf_rssi;
|
|
s32 if_rssi;
|
|
s32 rem, total_rssi;
|
|
s32 ssi_offset = 0; //need to fine tune by platform
|
|
s32 total_rssi_dbm;
|
|
u8 rf_max_gain_flag;
|
|
|
|
R850_GetRfRssi(priv, RF_Freq_Khz, RT_Standard, &rf_rssi, &rf_max_gain_flag);
|
|
|
|
R850_GetIfRssi(priv, &if_rssi); //vga gain
|
|
|
|
total_rssi = rf_rssi - (if_rssi*10);
|
|
rem = total_rssi - (total_rssi/1000)*1000; //for rounding
|
|
if((rem>-500) && (rem<500))
|
|
total_rssi_dbm = (total_rssi/1000);
|
|
else if(rem<=-500)
|
|
total_rssi_dbm = (total_rssi/1000)-1;
|
|
else
|
|
total_rssi_dbm = (total_rssi/1000)+1;
|
|
|
|
//for different platform, need to fine tune offset value
|
|
*RssiDbm = total_rssi_dbm + ssi_offset+8;
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
u8 R850_Filt_Cal_ADC(struct r850_priv *priv, u32 IF_Freq, u8 R850_BW, u8 FilCal_Gap)
|
|
{
|
|
u8 u1FilterCodeResult = 0;
|
|
u8 u1FilterCode = 0;
|
|
u8 u1FilterCalValue = 0;
|
|
u8 u1FilterCalValuePre = 0;
|
|
u8 initial_cnt = 0;
|
|
u8 i = 0;
|
|
//u32 RingVCO = 0;
|
|
u32 RingFreq = 72000;
|
|
u8 ADC_Read_Value = 0;
|
|
u8 ADC_Read_Value_8M5Hz = 0;
|
|
u8 LPF_Count = 0;
|
|
//u32 RingRef = R850_Xtal;
|
|
//u8 divnum_ring = 0;
|
|
//u8 VGA_Count = 0;
|
|
|
|
|
|
if(R850_Cal_Prepare(priv, R850_LPF_CAL) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
priv->R850_IF_GOLOBAL = IF_Freq;
|
|
//Set PLL (TBD, normal)
|
|
if(R850_PLL(priv, (RingFreq - IF_Freq), R850_STD_SIZE) != R850_Success) //FilCal PLL
|
|
return R850_Fail;
|
|
|
|
//------- increase Filter gain to let ADC read value significant ---------//
|
|
for(LPF_Count=5; LPF_Count < 16; LPF_Count ++)
|
|
{
|
|
|
|
priv->regs[41] = (priv->regs[41] & 0x0F) | (LPF_Count<<4);
|
|
if(r850_wr(priv,41,priv->regs[41]) != 0)
|
|
return R850_Fail;
|
|
|
|
msleep( R850_FILTER_GAIN_DELAY); //
|
|
|
|
if(R850_Muti_Read(priv, &ADC_Read_Value) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if(ADC_Read_Value > 40*R850_ADC_READ_COUNT)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//If IF_Freq>10MHz, need to compare 8.5MHz ADC Value,
|
|
//If the ADC values greater than 8 in the same gain,the filter corner select 8M / 0
|
|
if(IF_Freq>=10000)
|
|
{
|
|
priv->R850_IF_GOLOBAL = 8500;
|
|
//Set PLL (TBD, normal)
|
|
if(R850_PLL( priv,(RingFreq - 8500), R850_STD_SIZE) != R850_Success) //FilCal PLL
|
|
return R850_Fail;
|
|
|
|
msleep( R850_FILTER_GAIN_DELAY); //
|
|
|
|
if(R850_Muti_Read( priv,&ADC_Read_Value_8M5Hz) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if(ADC_Read_Value_8M5Hz > (ADC_Read_Value + 8) )
|
|
{
|
|
//priv->bw = 0; //8M
|
|
u1FilterCodeResult = 0;
|
|
return u1FilterCodeResult;
|
|
}
|
|
else
|
|
{
|
|
priv->R850_IF_GOLOBAL = IF_Freq;
|
|
//Set PLL (TBD, normal)
|
|
if(R850_PLL(priv, (RingFreq - IF_Freq), R850_STD_SIZE) != R850_Success) //FilCal PLL
|
|
return R850_Fail;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//------- Try suitable BW --------//
|
|
if(R850_BW==2) //6M
|
|
initial_cnt = 1; //try 7M first
|
|
else
|
|
initial_cnt = 0; //try 8M first
|
|
|
|
for(i=initial_cnt; i<3; i++)
|
|
{
|
|
|
|
//Set BW R22[5:4] => R23[6:5]
|
|
priv->regs[23] = (priv->regs[23] & 0xCF);
|
|
if(r850_wr(priv,23,priv->regs[23]) != 0)
|
|
return R850_Fail;
|
|
|
|
// read code 0 R22[4:1] => R23[4:1]
|
|
priv->regs[23] = (priv->regs[23] & 0xE1); //code 0
|
|
if(r850_wr(priv,23,priv->regs[23]) != 0)
|
|
return R850_Fail;
|
|
|
|
msleep( R850_FILTER_CODE_DELAY); //delay ms
|
|
|
|
if(R850_Muti_Read(priv, &u1FilterCalValuePre) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
//read code 26 R22[4:1] => R23[4:1]
|
|
priv->regs[23] = (priv->regs[23] & 0xE1) | (13<<1); //code 26
|
|
if(r850_wr(priv,23,priv->regs[23]) != 0)
|
|
return R850_Fail;
|
|
|
|
msleep( R850_FILTER_CODE_DELAY); //delay ms
|
|
|
|
if(R850_Muti_Read(priv, &u1FilterCalValue) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if(u1FilterCalValuePre > (u1FilterCalValue+16)) //suitable BW found
|
|
break;
|
|
}
|
|
|
|
//-------- Try LPF filter code ---------//
|
|
u1FilterCalValuePre = 0;
|
|
for(u1FilterCode=0; u1FilterCode<16; u1FilterCode++)
|
|
{
|
|
priv->regs[23] = (priv->regs[23] & 0xE1) | (u1FilterCode<<1);
|
|
if(r850_wr(priv,23,priv->regs[23]) != 0)
|
|
|
|
return R850_Fail;
|
|
|
|
msleep( R850_FILTER_CODE_DELAY); //delay ms
|
|
|
|
if(R850_Muti_Read(priv, &u1FilterCalValue) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if((IF_Freq>=10000)&&(u1FilterCode==0))
|
|
{
|
|
u1FilterCalValuePre = ADC_Read_Value_8M5Hz;
|
|
}
|
|
else if(u1FilterCode==0)
|
|
{
|
|
u1FilterCalValuePre = u1FilterCalValue;
|
|
}
|
|
|
|
if((u1FilterCalValue+FilCal_Gap*R850_ADC_READ_COUNT) < u1FilterCalValuePre)
|
|
{
|
|
u1FilterCodeResult = u1FilterCode;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Try LSB bit
|
|
if(u1FilterCodeResult>0) //try code-1 & lsb=1
|
|
{
|
|
|
|
priv->regs[23] = (priv->regs[23] & 0xE0) | ((u1FilterCodeResult-1)<<1) | 0x01;
|
|
if(r850_wr(priv,23,priv->regs[23]) != 0)
|
|
return R850_Fail;
|
|
|
|
msleep( R850_FILTER_GAIN_DELAY); //delay ms
|
|
|
|
if(R850_Muti_Read( priv,&u1FilterCalValue) != R850_Success)
|
|
return R850_Fail;
|
|
|
|
if((u1FilterCalValue+FilCal_Gap*R850_ADC_READ_COUNT) < u1FilterCalValuePre)
|
|
{
|
|
u1FilterCodeResult = u1FilterCodeResult - 1;
|
|
}
|
|
|
|
}
|
|
|
|
if(u1FilterCode==16)
|
|
u1FilterCodeResult = 15;
|
|
|
|
return u1FilterCodeResult;
|
|
|
|
}
|
|
|
|
R850_ErrCode R850_SetStandard(struct r850_priv *priv, enum R850_Standard_Type RT_Standard)
|
|
{
|
|
u8 u1FilCalGap = 16;
|
|
|
|
//HPF ext protection
|
|
if(priv->fc.flag== 0)
|
|
{
|
|
priv->fc.code = R850_Filt_Cal_ADC(priv, priv->R850_Sys_Info.FILT_CAL_IF, priv->R850_Sys_Info.BW, u1FilCalGap);
|
|
priv->fc.bw = 0;
|
|
priv->fc.flag = 1;
|
|
priv->fc.lpflsb = 0;
|
|
|
|
//Reset register and Array
|
|
if(R850_InitReg(priv) != R850_Success)
|
|
return R850_Fail;
|
|
}
|
|
// Set LPF Lsb bit
|
|
priv->regs[23] = (priv->regs[23] & 0xFE) ; //R23[0]
|
|
// Set LPF fine code
|
|
priv->regs[23] = (priv->regs[23] & 0xE1) | (priv->fc.code<<1); //R23[4:1]
|
|
// Set LPF coarse BW
|
|
priv->regs[23] = (priv->regs[23] & 0x9F) | (priv->fc.bw<<5); //R23[6:5]
|
|
//Set HPF notch R23[7]
|
|
priv->regs[23] = (priv->regs[23] & 0x7F) | (priv->R850_Sys_Info.HPF_NOTCH<<7);
|
|
if(r850_wr(priv,23,priv->regs[23]) != 0)
|
|
return R850_Fail;
|
|
|
|
|
|
// Set HPF corner
|
|
priv->regs[24] = (priv->regs[24] & 0x0F) | (priv->R850_Sys_Info.HPF_COR<<4); //R24[3:0] => R24[7:4]
|
|
if(r850_wr(priv,24,priv->regs[24]) != 0)
|
|
return R850_Fail;
|
|
|
|
|
|
// Set Filter Auto Ext
|
|
priv->regs[18] = (priv->regs[18] & 0xBF) | (priv->R850_Sys_Info.FILT_EXT_ENA<<6); // =>R18[6]
|
|
if(r850_wr(priv,18,priv->regs[18]) != 0)
|
|
return R850_Fail;
|
|
|
|
//set Filter Comp //R24[3:2]
|
|
priv->regs[24] = (priv->regs[24] & 0xF3) | (priv->R850_Sys_Info.FILT_COMP<<2);
|
|
if(r850_wr(priv,24,priv->regs[24]) != 0)
|
|
return R850_Fail;
|
|
|
|
// Set AGC clk R47[3:2]
|
|
priv->regs[47] = (priv->regs[47] & 0xF3) | (priv->R850_Sys_Info.AGC_CLK<<2);
|
|
if(r850_wr(priv,47,priv->regs[47]) != 0)
|
|
return R850_Fail;
|
|
|
|
priv->regs[44] = (priv->regs[44] & 0xFE) | ((priv->R850_Sys_Info.IMG_GAIN & 0x02)>>1);
|
|
if(r850_wr(priv,44,priv->regs[44]) != 0)
|
|
return R850_Fail;
|
|
|
|
priv->regs[46] = (priv->regs[46] & 0xEF) | ((priv->R850_Sys_Info.IMG_GAIN & 0x01)<<4);
|
|
if(r850_wr(priv,46,priv->regs[46]) != 0)
|
|
return R850_Fail;
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
|
|
|
|
R850_ErrCode R850_SetFrequency(struct r850_priv *priv, struct R850_Set_Info R850_INFO) //Write Multi byte
|
|
{
|
|
|
|
u32 LO_KHz;
|
|
u8 Img_R;
|
|
u8 SetFreqArrayCunt;
|
|
int ret = 0;
|
|
|
|
struct R850_SysFreq_Info_Type SysFreq_Info1;
|
|
|
|
//Get Sys-Freq parameter
|
|
|
|
SysFreq_Info1 = R850_SysFreq_NrbDetOn_Sel( R850_INFO.R850_Standard, R850_INFO.RF_KHz);
|
|
|
|
//R850_IMR_point_num = Freq_Info1.IMR_MEM_NOR;
|
|
|
|
// Check Input Frequency Range
|
|
if((R850_INFO.RF_KHz<40000) || (R850_INFO.RF_KHz>1002000))
|
|
{
|
|
return R850_Fail;
|
|
}
|
|
|
|
|
|
|
|
LO_KHz = R850_INFO.RF_KHz + priv->R850_Sys_Info.IF_KHz;
|
|
Img_R = 0;
|
|
|
|
priv->regs[19] = (priv->regs[19] & 0xEF) | (Img_R<<4); //R20[7] => R19[4]
|
|
if(r850_wr(priv,19,priv->regs[19]))
|
|
return R850_Fail;
|
|
|
|
|
|
//Set MUX dependent var. Must do before PLL()
|
|
if(R850_MUX( priv,LO_KHz, R850_INFO.RF_KHz, R850_INFO.R850_Standard) != R850_Success) //normal MUX
|
|
return R850_Fail;
|
|
|
|
priv->R850_IF_GOLOBAL = priv->R850_Sys_Info.IF_KHz;
|
|
//Set PLL
|
|
if(R850_PLL(priv, LO_KHz, R850_INFO.R850_Standard) != R850_Success) //noraml PLL
|
|
return R850_Fail;
|
|
|
|
// PW
|
|
// Set NA det power R10[6]
|
|
//if(R850_External_LNA == 0) //External LNA Disable => depend on setting
|
|
priv->regs[10] = (priv->regs[10] & 0xBF) | (SysFreq_Info1.NA_PWR_DET<<6);
|
|
// else //External LNA Enable => fixed
|
|
// priv->regs[R850_I2C.RegAddr] = (priv->regs[R850_I2C.RegAddr] & 0xBF);
|
|
|
|
//Set Man Buf Cur R16[5]
|
|
// if(R850_External_LNA == 0) //External LNA Disable => depend on initial value
|
|
priv->regs[16] = (priv->regs[16] & 0xDF) | (R850_iniArray[0][16] & 0x20);
|
|
// else //External LNA Enable => fixed
|
|
// priv->regs[R850_I2C.RegAddr] = (priv->regs[R850_I2C.RegAddr] | 0x20);
|
|
|
|
|
|
//LNA_NRB_DET R11[7]
|
|
priv->regs[11] = (priv->regs[11] & 0x7F) | (SysFreq_Info1.LNA_NRB_DET<<7);
|
|
|
|
//LNA
|
|
// LNA_TOP R38[2:0]
|
|
priv->regs[38] = (priv->regs[38] & 0xF8) | (7 - SysFreq_Info1.LNA_TOP);
|
|
|
|
// LNA VTL/H R39[7:0]
|
|
priv->regs[39] = (priv->regs[39 ] & 0x00) | SysFreq_Info1.LNA_VTL_H;
|
|
|
|
// RF_LTE_PSG R17[4]
|
|
priv->regs[17] = (priv->regs[17 ] & 0xEF) | (SysFreq_Info1.RF_LTE_PSG<<4);
|
|
|
|
//RF
|
|
// RF TOP R38[6:4]
|
|
priv->regs[38] = (priv->regs[38] & 0x8F) | ((7 - SysFreq_Info1.RF_TOP)<<4);
|
|
|
|
// RF VTL/H R42[7:0]
|
|
priv->regs[42] = (priv->regs[42] & 0x00) | SysFreq_Info1.RF_VTL_H;
|
|
|
|
// RF Gain Limt (MSB:R18[2] & LSB:R16[6])
|
|
switch(SysFreq_Info1.RF_GAIN_LIMIT)
|
|
{
|
|
case 0://'b00
|
|
priv->regs[18] = (priv->regs[18] & 0xFB);
|
|
priv->regs[16] = (priv->regs[16] & 0xBF);
|
|
break;
|
|
case 1://'b01
|
|
priv->regs[18] = (priv->regs[18] & 0xFB);
|
|
priv->regs[16] = (priv->regs[16] | 0x40);
|
|
break;
|
|
case 2://'b10
|
|
priv->regs[18] = (priv->regs[18] | 0x02);
|
|
priv->regs[16] = (priv->regs[16] & 0xBF);
|
|
break;
|
|
case 3://'b11
|
|
priv->regs[18] = (priv->regs[18] | 0x02);
|
|
priv->regs[16] = (priv->regs[16] | 0x40);
|
|
break;
|
|
}
|
|
|
|
//MIXER & FILTER
|
|
//MIXER_AMP_LPF R19[2:0]
|
|
priv->regs[19] = (priv->regs[19] & 0xF8) | SysFreq_Info1.MIXER_AMP_LPF;
|
|
|
|
// MIXER TOP R40[3:0]
|
|
priv->regs[40] = (priv->regs[40] & 0xF0) | (15 - SysFreq_Info1.MIXER_TOP);
|
|
|
|
// Filter TOP R44[3:0] for MP, R44[3:1] for MT1
|
|
priv->regs[44] = (priv->regs[44] & 0xF1) | ((7-SysFreq_Info1.FILTER_TOP)<<1);
|
|
|
|
//FILT_3TH_LPF_CUR=0; //R10[4] [high (0), low (1)]
|
|
priv->regs[10] = (priv->regs[10] & 0xEF) | (SysFreq_Info1.FILT_3TH_LPF_CUR<<4);
|
|
|
|
// 3th_LPF_Gain R24[1:0]
|
|
priv->regs[24] = (priv->regs[24] & 0xFC) | SysFreq_Info1.FILT_3TH_LPF_GAIN;
|
|
|
|
priv->regs[19] = (priv->regs[19] & 0x7F) | 0x80;
|
|
// MIXER VTH & Filter VTH R41[7:0]
|
|
priv->regs[41] = ((priv->regs[41] & 0x00) | SysFreq_Info1.MIXER_VTH | SysFreq_Info1.FILTER_VTH);
|
|
|
|
// MIXER VTL & Filter VTL R43[7:0]
|
|
priv->regs[43] = ((priv->regs[43] & 0x00) | SysFreq_Info1.MIXER_VTL | SysFreq_Info1.FILTER_VTL);
|
|
|
|
// Mixer Gain Limt R22[7:6]
|
|
priv->regs[22] = (priv->regs[22] & 0x3F) | (SysFreq_Info1.MIXER_GAIN_LIMIT << 6);
|
|
|
|
// MIXER_DETBW_LPF R46[7]
|
|
priv->regs[46] = (priv->regs[46] & 0x7F) | (SysFreq_Info1.MIXER_DETBW_LPF << 7);
|
|
|
|
//Discharge
|
|
//LNA_RF Discharge Mode (R45[1:0]=2'b01; R9[6]=1) => (R45[1:0]=0'b00; R31[0]=1 ;R32[5]=1)
|
|
if(SysFreq_Info1.LNA_RF_DIS_MODE==0) //auto (normal)
|
|
{
|
|
priv->regs[45] = (priv->regs[45] & 0xFC) | 0x00; //00
|
|
priv->regs[31] = (priv->regs[31] & 0xFE) | 0x01; //1
|
|
priv->regs[32] = (priv->regs[32] & 0xDF) | 0x20; //1
|
|
}
|
|
else if(SysFreq_Info1.LNA_RF_DIS_MODE==1) //both(fast+slow)
|
|
{
|
|
priv->regs[45] = (priv->regs[45] & 0xFC) | 0x03; //11
|
|
priv->regs[31] = (priv->regs[31] & 0xFE) | 0x01; //1
|
|
priv->regs[32] = (priv->regs[32] & 0xDF) | 0x20; //1
|
|
}
|
|
else if(SysFreq_Info1.LNA_RF_DIS_MODE==2) //both(slow)
|
|
{
|
|
priv->regs[45] = (priv->regs[45] & 0xFC) | 0x03; //11
|
|
priv->regs[31] = (priv->regs[31] & 0xFE) | 0x00; //0
|
|
priv->regs[32] = (priv->regs[32] & 0xDF) | 0x00; //0
|
|
}
|
|
else if(SysFreq_Info1.LNA_RF_DIS_MODE==3) //LNA(slow)
|
|
{
|
|
priv->regs[45] = (priv->regs[45] & 0xFC) | 0x03; //11
|
|
priv->regs[31] = (priv->regs[31] & 0xFE) | 0x01; //1
|
|
priv->regs[32] = (priv->regs[32] & 0xDF) | 0x00; //0
|
|
}
|
|
else if(SysFreq_Info1.LNA_RF_DIS_MODE==4) //RF(slow)
|
|
{
|
|
priv->regs[45] = (priv->regs[45] & 0xFC) | 0x03; //11
|
|
priv->regs[31] = (priv->regs[31] & 0xFE) | 0x00; //0
|
|
priv->regs[32] = (priv->regs[32] & 0xDF) | 0x20; //1
|
|
}
|
|
else
|
|
{
|
|
priv->regs[45] = (priv->regs[45] & 0xFC) | 0x00; //00
|
|
priv->regs[31] = (priv->regs[31] & 0xFE) | 0x01; //1
|
|
priv->regs[32] = (priv->regs[32] & 0xDF) | 0x20; //1
|
|
}
|
|
|
|
//LNA_RF_CHARGE_CUR R31[1]
|
|
priv->regs[31] = (priv->regs[31] & 0xFD) | (SysFreq_Info1.LNA_RF_CHARGE_CUR<<1);
|
|
|
|
//LNA_RF_dis current R13[5]
|
|
priv->regs[13] = (priv->regs[13] & 0xDF) | (SysFreq_Info1.LNA_RF_DIS_CURR<<5);
|
|
|
|
//RF_slow disch(5:4) / fast disch(7:6) //(R45[7:4])
|
|
priv->regs[45] = (priv->regs[45] & 0x0F) | (SysFreq_Info1.RF_DIS_SLOW_FAST<<4);
|
|
|
|
//LNA slow disch(5:4) / fast disch(7:6) => R44[7:4]
|
|
priv->regs[44] = (priv->regs[44] & 0x0F) | (SysFreq_Info1.LNA_DIS_SLOW_FAST<<4);
|
|
|
|
//BB disch current R25[6]
|
|
priv->regs[25] = (priv->regs[25] & 0xBF) | (SysFreq_Info1.BB_DIS_CURR<<6);
|
|
|
|
//Mixer/Filter disch R37[7:6]
|
|
priv->regs[37] = (priv->regs[37] & 0x3F) | (SysFreq_Info1.MIXER_FILTER_DIS<<6);
|
|
|
|
//BB Det Mode R37[2]
|
|
priv->regs[37] = (priv->regs[37] & 0xFB) | (SysFreq_Info1.BB_DET_MODE<<2);
|
|
|
|
//Polyphase
|
|
//ENB_POLY_GAIN R25[1]
|
|
priv->regs[25] = (priv->regs[25] & 0xFD) | (SysFreq_Info1.ENB_POLY_GAIN<<1);
|
|
|
|
//NRB
|
|
// NRB TOP R40[7:4]
|
|
priv->regs[40] = (priv->regs[40] & 0x0F) | ((15 - SysFreq_Info1.NRB_TOP)<<4);
|
|
|
|
//NRB LPF & HPF BW R26[7:6 & 3:2]
|
|
priv->regs[26] = (priv->regs[26] & 0x33) | (SysFreq_Info1.NRB_BW_HPF<<2) | (SysFreq_Info1.NRB_BW_LPF<<6);
|
|
|
|
//NBR Image TOP adder R46[3:2]
|
|
priv->regs[46] = (priv->regs[46] & 0xF3) | (SysFreq_Info1.IMG_NRB_ADDER<<2);
|
|
|
|
//VGA
|
|
//HPF_COMP R13[2:1]
|
|
priv->regs[13] = (priv->regs[13] & 0xF9) | (SysFreq_Info1.HPF_COMP<<1);
|
|
|
|
//FB_RES_1ST //R21[4]
|
|
priv->regs[21] = (priv->regs[21] & 0xEF) | (SysFreq_Info1.FB_RES_1ST<<4);
|
|
|
|
//DEGLITCH_CLK; R38[3]
|
|
priv->regs[38] = (priv->regs[38] & 0xF7) | (SysFreq_Info1.DEGLITCH_CLK<<3);
|
|
|
|
//NAT_HYS; R35[6]
|
|
priv->regs[35] = (priv->regs[35] & 0xBF) | (SysFreq_Info1.NAT_HYS<<6);
|
|
|
|
//NAT_CAIN; R31[4:5]
|
|
priv->regs[31] = (priv->regs[31] & 0xCF) | (SysFreq_Info1.NAT_CAIN<<4);
|
|
|
|
//PULSE_HYS; R26[1:0]
|
|
priv->regs[26] = (priv->regs[26] & 0xFC) | (SysFreq_Info1.PULSE_HYS);
|
|
|
|
//FAST_DEGLITCH; R36[3:2]
|
|
priv->regs[36] = (priv->regs[36] & 0xF3) | (SysFreq_Info1.FAST_DEGLITCH<<2);
|
|
|
|
//PUL_RANGE_SEL; R31[2]
|
|
priv->regs[31] = (priv->regs[31] & 0xFB) | (SysFreq_Info1.PUL_RANGE_SEL<<2);
|
|
|
|
//PUL_FLAG_RANGE; R35[1:0]
|
|
priv->regs[35] = (priv->regs[35] & 0xFC) | (SysFreq_Info1.PUL_FLAG_RANGE);
|
|
|
|
//PULG_CNT_THRE; R17[1]
|
|
priv->regs[17] = (priv->regs[17] & 0xFD) | (SysFreq_Info1.PULG_CNT_THRE<<1);
|
|
|
|
//FORCE_PULSE; R46[5]
|
|
priv->regs[46] = (priv->regs[46] & 0xDF) | (SysFreq_Info1.FORCE_PULSE<<5);
|
|
|
|
//FLG_CNT_CLK; R47[7:6]
|
|
priv->regs[47] = (priv->regs[47] & 0x3F) | (SysFreq_Info1.FLG_CNT_CLK<<6);
|
|
|
|
//NATG_OFFSET; R36[5:4]
|
|
priv->regs[36] = (priv->regs[36] & 0xCF) | (SysFreq_Info1.NATG_OFFSET<<4);
|
|
//other setting
|
|
|
|
// Set AGC clk R47[3:2] only for isdbt 4.063 (set 1Khz because Div/4, original agc clk is 512Hz)
|
|
if( (R850_INFO.RF_KHz >= 478000) && (R850_INFO.RF_KHz < 482000) && (R850_INFO.R850_Standard == R850_ISDB_T_4063) )
|
|
{
|
|
priv->regs[47] = (priv->regs[47] & 0xF3);
|
|
}
|
|
|
|
|
|
//IF AGC1
|
|
priv->regs[25] = priv->regs[25] & 0xDF;
|
|
|
|
|
|
//Set LT
|
|
if(R850_INFO.R850_LT==R850_LT_ON)
|
|
{
|
|
//LT Sel: active LT(after LNA) R8[6]=1 ; acLT PW: ON R8[7]=1
|
|
priv->regs[8] = (priv->regs[8] | 0xC0 );
|
|
//Pulse LT on R10[1]=1
|
|
priv->regs[10] = (priv->regs[10] | 0x02);
|
|
}
|
|
else
|
|
{
|
|
//LT Sel: active LT(after LNA) R8[6]=1 ; acLT PW: OFF R8[7]=0
|
|
priv->regs[8] = ((priv->regs[8] | 0x40) & 0x7F);
|
|
//Pulse LT on R10[1]=0
|
|
priv->regs[10] = (priv->regs[10] & 0xFD);
|
|
}
|
|
|
|
|
|
//Set Clk Out
|
|
if(R850_INFO.R850_ClkOutMode==R850_CLK_OUT_OFF)
|
|
{
|
|
priv->regs[34] = (priv->regs[34] | 0x04); //no clk out R34[2] = 1
|
|
}
|
|
else
|
|
{
|
|
priv->regs[34] = (priv->regs[34] & 0xFB); //clk out R34[2] = 0
|
|
}
|
|
|
|
ret = r850_wrm(priv,8,&priv->regs[8],40);
|
|
if(ret!=0)
|
|
return R850_Fail;
|
|
|
|
|
|
return R850_Success;
|
|
}
|
|
|
|
|
|
static int r850_init(struct dvb_frontend *fe)
|
|
{
|
|
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
|
struct r850_priv *priv = fe->tuner_priv;
|
|
|
|
int ret = 0;
|
|
|
|
if(priv->inited)
|
|
return ret;
|
|
|
|
priv->fc.bw = 0x00;
|
|
priv->fc.code = 0;
|
|
priv->fc.lpflsb = 0;
|
|
priv->fc.flag =0;
|
|
|
|
priv->R850_Sys_Info.IF_KHz=5000;
|
|
priv->R850_Sys_Info.BW=0; //BW=8M R23[6:5] [8M(0), 7M(1), 6M(2)]
|
|
priv->R850_Sys_Info.FILT_CAL_IF=8800; //CAL IF
|
|
priv->R850_Sys_Info.HPF_COR=11; //R24[7:4] [0~15 ; input: "0~15"]
|
|
priv->R850_Sys_Info.FILT_EXT_ENA=0; //R18[6] filter ext disable [off(0), on(1)]
|
|
priv->R850_Sys_Info.FILT_COMP=2; //R24[3:2] [0~3 ; input: "0~3"]
|
|
priv->R850_Sys_Info.AGC_CLK = 1; //R47[3:2] 1k [1kHz(0), 512Hz(1), 4kHz(2), 64Hz(3)]
|
|
priv->R850_Sys_Info.IMG_GAIN = 2; ////MSB:R44[0] , LSB:R46[4] highest [lowest(0), high(1), low(2), highest(3)]
|
|
|
|
priv->R850_clock_out = 0;
|
|
priv->R850_IMR_Cal_Result = 0;
|
|
|
|
priv->R850_Xtal_cap = 29;
|
|
priv->R850_IF_GOLOBAL = 6000;
|
|
priv->R850_XtalDiv = R850_XTAL_DIV1;
|
|
|
|
priv->R850_IMR_done_flag = 0;
|
|
priv->R850_IMR_Cal_Result = 0;
|
|
|
|
|
|
if(R850_Cal_Prepare(priv, R850_IMR_CAL) != R850_Success)
|
|
ret=-1;
|
|
|
|
|
|
if(R850_IMR(priv,2, TRUE) != R850_Success) //Full K node 2
|
|
ret=-1;
|
|
|
|
if(R850_IMR(priv, 1, FALSE) != R850_Success)
|
|
ret=-1;
|
|
|
|
if(R850_IMR(priv, 0, FALSE) != R850_Success)
|
|
ret=-1;
|
|
|
|
if(R850_IMR(priv, 3, FALSE) != R850_Success)
|
|
ret=-1;
|
|
|
|
if(R850_IMR(priv, 4, FALSE) != R850_Success)
|
|
ret=-1;
|
|
|
|
priv->R850_IMR_done_flag = 1;
|
|
|
|
//do Xtal check
|
|
|
|
if(priv->R850_clock_out == 1)
|
|
{
|
|
priv->R850_Xtal_Pwr = R850_XTAL_HIGHEST;
|
|
}
|
|
else //==0
|
|
{
|
|
priv->R850_Xtal_Pwr = R850_XTAL_LOWEST;
|
|
}
|
|
|
|
//write initial reg
|
|
if(R850_InitReg(priv) != R850_Success)
|
|
ret=-1;
|
|
|
|
priv->inited = 1;
|
|
|
|
/* init statistics in order signal app which are supported */
|
|
c->strength.len = 1;
|
|
c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
static int r850_set_params(struct dvb_frontend *fe)
|
|
{
|
|
struct r850_priv *priv = fe->tuner_priv;
|
|
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
|
struct R850_Set_Info tuner_parameters;
|
|
|
|
int ret = 0;
|
|
|
|
if(!priv->inited)
|
|
r850_init(fe);
|
|
|
|
tuner_parameters.RF_KHz = c->frequency /1000;
|
|
|
|
tuner_parameters.R850_LT=R850_LT_ON;
|
|
tuner_parameters.R850_ClkOutMode=R850_CLK_OUT_OFF;
|
|
tuner_parameters.R850_Standard = R850_DTMB_8M_IF_5M;
|
|
|
|
|
|
|
|
if(R850_SetStandard(priv,R850_DTMB_8M_IF_5M) != R850_Success)
|
|
ret=-1;
|
|
|
|
if(R850_SetFrequency(priv, tuner_parameters) != R850_Success)
|
|
ret=-1;
|
|
|
|
return ret;
|
|
}
|
|
static int r850_get_rf_strength(struct dvb_frontend *fe, u16 *rssi)
|
|
{
|
|
struct r850_priv *priv = fe->tuner_priv;
|
|
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
|
s32 RSSI_Value = 0;
|
|
int strength;
|
|
|
|
R850_GetTotalRssi(priv,c->frequency/1000,R850_DTMB_8M_IF_5M,&RSSI_Value);
|
|
|
|
if(RSSI_Value>-70)
|
|
RSSI_Value+=8;
|
|
|
|
c->strength.len = 2;
|
|
c->strength.stat[0].scale = FE_SCALE_DECIBEL;
|
|
c->strength.stat[0].svalue = (s8)RSSI_Value * 1000;
|
|
|
|
if(RSSI_Value<-85)
|
|
RSSI_Value = -80;
|
|
if(RSSI_Value> -50)
|
|
RSSI_Value = -20;
|
|
|
|
strength = (85+RSSI_Value)*100/65+20;
|
|
|
|
if(strength>100)
|
|
strength=100;
|
|
|
|
c->strength.stat[1].scale = FE_SCALE_RELATIVE;
|
|
c->strength.stat[1].uvalue = strength*655;
|
|
|
|
*rssi =(u16)(strength*655);
|
|
|
|
return 0;
|
|
}
|
|
static void r850_release(struct dvb_frontend *fe)
|
|
{
|
|
struct r850_priv *priv = fe->tuner_priv;
|
|
dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
|
|
|
|
kfree(fe->tuner_priv);
|
|
fe->tuner_priv = NULL;
|
|
}
|
|
|
|
static int r850_sleep(struct dvb_frontend *fe)
|
|
{
|
|
struct r850_priv *priv = fe->tuner_priv;
|
|
int ret = 0;
|
|
dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
|
|
|
|
//if (ret)
|
|
// dev_dbg(&priv->i2c->dev, "%s() failed\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
static const struct dvb_tuner_ops r850_tuner_ops = {
|
|
.info = {
|
|
.name = "Rafael R850",
|
|
// .frequency_min_hz = 250 * MHz,
|
|
// .frequency_max_hz = 2300 * MHz,
|
|
},
|
|
|
|
.release = r850_release,
|
|
|
|
.init = r850_init,
|
|
.sleep = r850_sleep,
|
|
.set_params = r850_set_params,
|
|
.get_rf_strength = r850_get_rf_strength,
|
|
};
|
|
|
|
struct dvb_frontend *r850_attach(struct dvb_frontend *fe,
|
|
struct r850_config *cfg, struct i2c_adapter *i2c)
|
|
{
|
|
struct r850_priv *priv = NULL;
|
|
u8 chip_id;
|
|
u8 buf[50];
|
|
int ret = 0;
|
|
|
|
priv = kzalloc(sizeof(struct r850_priv), GFP_KERNEL);
|
|
if (priv == NULL) {
|
|
dev_dbg(&i2c->dev, "%s() attach failed\n", __func__);
|
|
return NULL;
|
|
}
|
|
|
|
priv->cfg = cfg;
|
|
priv->i2c = i2c;
|
|
|
|
priv->inited = 0;
|
|
|
|
ret = r850_rd(priv,0x00,buf,48);
|
|
if(ret!=0)
|
|
return NULL;
|
|
|
|
dev_info(&priv->i2c->dev,
|
|
"%s: Rafael R850 successfully attached,id is 0x%x\n",
|
|
KBUILD_MODNAME,buf[0]);
|
|
|
|
memcpy(&fe->ops.tuner_ops, &r850_tuner_ops,
|
|
sizeof(struct dvb_tuner_ops));
|
|
|
|
fe->tuner_priv = priv;
|
|
return fe;
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(r850_attach);
|
|
|
|
MODULE_DESCRIPTION("Rafael R850 tuner driver");
|
|
MODULE_AUTHOR("Davin<Davin@tbsdtv.com>");
|
|
MODULE_LICENSE("GPL");
|
|
|