📄 nscc_tuner.c
字号:
//*****************************************************************************// FILENAME: initFrontend.c// REVISIONS: 1.0.7 (support 8G54) // // DESCRIPTION: Initialize and other related functions to // Tuner ADMTV102 and Demod LGS8934/LGS8GL5/LGS8G54// Update History: Add related code supporting LGS8G54 chip // //-----------------------------------------------------------------------------// Copyright (c) Analog Devices 2006~2008 All Rights Reserved.//*****************************************************************************#include <linux/module.h>#include <linux/init.h>#include <linux/kdev_t.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/ioport.h>#include <linux/miscdevice.h>#include <linux/devfs_fs_kernel.h>#include <linux/cdev.h>#include <asm/uaccess.h>#include <linux/device.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <asm/hardware/clock.h>#include <media/davinci_vpfe.h>#include <asm/arch/gio.h>#include <asm/io.h>#include "nscc_tuner.h"/* define the register address and data of Tuner that need to be initialized when power on */ m_BYTE AddrDataMemADMTV102_UHF[100]={//Addr Data 0x10,0x6A, // LNA current, 0x4C will degrade 1 dB performance but get better power consumption. 0x11,0xD8, // Mixer current 0x12,0xC0, // Mixer gain 0x15,0x3D, // TOP and ADJ to optimize SNR and ACI 0x17,0x97, // TOP and ADJ to optimize SNR and ACI //*9A->97,Changed TOP and ADJ to optimize SNR and ACI 0x18,0x03, // Changed power detector saturation voltage point and warning voltage point //* new insert 0x1F,0x17, // VCOSEL,PLLF RFPGA amp current 0x20,0xFF, // RFPGA amp current 0x21,0xA4, // RFPGA amp current 0x22,0xA4, // RFPGA amp current 0x23,0xDF, // Mixer Bias control 0x26,0xFA, // PLL BUFFER CURRENT 0x27,0x00, // CONVCOL/H for VCO current control 0x28,0xFF, // CONVCOBUFL/H for VCO buffer amplifier current control 0x29,0xFF, // CONDIV1/2 for first and second divider current control 0x2A,0xFF, // CONDIV3/4 for third and last divider current control 0x2B,0xE7, // CONDIV5 for third and last divider current control 0X2C,0xFF, // CONBUF0/1 for L-Band Buffer amp and first Buffer amp current control 0x2E,0xFB, // CONBUF4 for forth Buffer amp current control 0x30,0x80, // LFSW(Internal Loop Filter) to improve phase noise //* F8->80 0x32,0xc2, // LOOP filter boundary 0x33,0x80, // DC offset control 0x34,0xEC, // DC offset control 0x39,0x96, // AGCHM AGC compensation value when LNA changes 0x3A,0xA0, // AGCHM AGC compensation value when LNA changes 0x3B,0x05, // AGCHM AGC compensation value when LNA changes 0x3C,0xD0, // AGCHM AGC compensation value when LNA changes 0x44,0xDF, // BBPGA needs to stay on for current silicon revision 0x48,0x23, // current for output buffer amp //*23->21 0x49,0x08, // gain mode for output buffer amp 0x4A,0xA0, // trip point for BBVGA 0x4B,0x9D, // trip point for RFPGA 0x4C,0x9D, // ADJRSSI warning point 0x4D,0xC3, // PLL current for stability PLL lock 0xff,0xff}; m_BYTE AddrDataMemADMTV102_VHF[100]={//Addr Data 0x10,0x08, // LNA current 0x11,0xc2, // Mixer current 0x12,0xC0, // Mixer gain 0x17,0x98, // TOP and ADJ to optimize SNR and ACI //* 9A->98 0x1F,0x17, // VCOSEL,PLLF RFPGA amp current 0x20,0x9b, // RFPGA amp current 0x21,0xA4, // RFPGA amp current 0x22,0xA4, // RFPGA amp current 0x23,0x9F, // Mixer Bias control 0x26,0xF9, // PLL BUFFER CURRENT 0x27,0x11, // CONVCOL/H for VCO current control 0x28,0x92, // CONVCOBUFL/H for VCO buffer amplifier current control 0x29,0xBC, // CONDIV1/2 for first and second divider current control 0x2B,0xE7, // CONDIV5 for third and last divider current control 0x2D,0x9C, 0x2E,0xCE, // CONBUF4 for forth Buffer amp current control 0x2F,0x1F, 0x30,0x80, // LFSW(Internal Loop Filter) to improve phase noise 0x32,0xc2, // LOOP filter boundary 0x33,0x80, // DC offset control 0x34,0xEC, // DC offset control 0x48,0x29, // current for output buffer amp 0x49,0x08, // gain mode for output buffer amp 0x4A,0xA0, // trip point for BBVGA 0x4B,0x9D, // trip point for RFPGA 0x4C,0x9D, // ADJRSSI warning point 0x4D,0xC3, // PLL current for stability PLL lock 0xff,0xff}; m_BYTE PLLRegSetTable [10][3]={ // 0x24,0x31,0x38 {0x0F,0x04,0x50}, //13MHz //0x24: 0xnB-> 0xnF {0x1F,0x04,0x50}, //16.384MHz {0x2F,0x04,0x50}, //19.2MHz {0x3F,0x04,0x50}, //20.48MHz {0x4F,0x15,0x51}, //24.576MHz {0x5F,0x15,0x51}, //26MHz {0x5F,0x15,0x51}, //30.4MHz // 0x24 register value is changed from 0x5A to 0x5F {0x6F,0x15,0x51}, //36MHz {0x7F,0x15,0x51}, //38.4MHz {0x3F,0x04,0x50}, //20MHz};//*****************************************************************************// Function: Configure Tuner chip registers // Input: target -- Device I2C address // AddrData -- Register address and Config data array // Output: None//*****************************************************************************void ConfigTuner(m_BYTE target, m_BYTE *AddrData){ int i=0; m_BYTE addr, data; while (AddrData[i]!=0xFF) { addr = AddrData[i++]; data = AddrData[i++]; swrite(target, addr, data); } }//*****************************************************************************// Function: Set Tuner LPF configuration // Input: target -- Tuner I2C device Address // refClkType -- Tuner PLL Type // lpfBW -- Band width , in MHz unit// Return: None//*****************************************************************************void SetLPF(m_BYTE target,m_WORD refClkType,m_BYTE lpfBW){ m_BYTE tuneval; I2C_READ ReadResult; swrite(target,0x15, (m_BYTE)( 0x38| ((lpfBW-3)& 0x07) )); swrite(target, 0x25 , (_EXTUNEOFF << 2) | (_TUNEEN<<1) ); Sleep(10); //change from 1 to 10 tuneval=0x10; //default value ReadResult=sread(target,0x0F); if(ReadResult.ACK_status==1) tuneval = ReadResult.read_data; swrite(target, 0x25 , (_EXTUNEON << 2) | (_TUNEEN << 1) ); //change Tuning mode : auto-tune => manual tune(hold mode). if (refClkType==REFCLK30400) swrite(target, 0x25 , (m_BYTE)(((tuneval+g_CTUNE_CLKOFS)<<3) | (_EXTUNEON << 2) | (_TUNEEN << 1)) ); //Write CTUNE val. in order to store tuned value. else swrite(target, 0x25 , (m_BYTE)((tuneval<<3) | (_EXTUNEON << 2) | (_TUNEEN << 1)) ); //Write CTUNE val. in order to store tuned value. return;}//******************************************************************************// Function: Tuner PLL Register Setting // Input: target -- Tuner I2C device Address // RegDat -- Reg set value table // Return: None//******************************************************************************int TunerPLLRegSet(m_BYTE target, m_BYTE* RegDat,int TunerPLLType){ int i=0; m_BYTE addr, data; m_BYTE splitid; I2C_READ ReadData; if(REFCLK30400==TunerPLLType) { addr=0x24; ReadData=sread (target, 0x00); if(ReadData.ACK_status==1) splitid = ReadData.read_data; else return(-1); if (0x0E==splitid) data=REFCLK30400_CLKSEL_REG_SPLITID0E; // 0x5A else if(0x0F==splitid) data=REFCLK30400_CLKSEL_REG_SPLITID0F; // 0x6A, for mass product else data=RegDat[i]; swrite (target, addr, data); i++; } else { addr=0x24; data=RegDat[i++]; swrite (target, addr, data); } addr=0x31; data=RegDat[i++]; swrite (target, addr, data); addr=0x38; data=RegDat[i++]; swrite (target, addr, data); return 1; }//*****************************************************************************// Function: Distinguish Tuner Chip type by read SplidID // Input: target -- Device I2C address // // Return: Tuner Type, MTV102 or ADMTV102 , -1 means error.//*****************************************************************************int GetTunerType(m_BYTE target){ m_BYTE splitid,RetTunerType; I2C_READ ReadData; ReadData=sread (target, 0x00); if(ReadData.ACK_status==1) splitid = ReadData.read_data; else return(-1); g_CTUNE_CLKOFS=CTUNE_CLKOFS_SPLIT0E; switch(splitid) { case 0x0E: { g_CTUNE_CLKOFS=CTUNE_CLKOFS_SPLIT0E; RetTunerType=Tuner_ADMTV102; break; } case 0x0F: { // for mass product version g_CTUNE_CLKOFS=CTUNE_CLKOFS_SPLIT0F; RetTunerType=Tuner_ADMTV102; break; } case 0x08: case 0x0A: { RetTunerType=Tuner_MTV102; break; } default: RetTunerType=Tuner_NewMTV102; break; } return(RetTunerType);}//*****************************************************************************// Function: Main Function for Tuner Initialization// only support ADMTV102 type, do not support MTV102 any more // Input: target -- Tuner I2C device Address // TunerPLLType -- Tuner PLL Type // Return: None//*****************************************************************************void TunerInit(m_BYTE target, int TunerPLLType){ GetTunerType(target); g_icp=0; g_convco=0; g_curTempState=HIGH_TEMP; if(TunerPLLType<0 || TunerPLLType>9 ) TunerPLLType=1; if(g_VHFSet== VHFSupport) ConfigTuner (target, &AddrDataMemADMTV102_VHF[0]); else ConfigTuner (target, &AddrDataMemADMTV102_UHF[0]); TunerPLLRegSet(target,&PLLRegSetTable[TunerPLLType][0],TunerPLLType); SetLPF(target,TunerPLLType,8); return;}//*****************************************************************************// Function: frequency setting for ADMTV102 // Input:// target : I2C address of tuner// frequency : Tuner center frequency in MHz// lpfBW : Channel Bandwidth in MHz (default: 8- 8MHZ)// refClkType: Tuner PLL reference clock type// frequency setting formula// LOfrequency=(Clockfrequency/PLLR*(PLLN+PLLF/2^20))/PLLS;// Return: None //*****************************************************************************void SetTunerFreq(m_BYTE target, m_WORD frequency, m_WORD lpfBW, int refClkType){ m_WORD MTV10x_REFCLK; m_WORD PLLFREQ,Freq; m_WORD DIVSEL=0,VCOSEL=0; m_BYTE PC4=0,PC8_16=0,DATA47,_temper; m_WORD Seg_num; m_BYTE PLLR; m_WORD lofreq; m_DWORD PLLN, PLLF,tmp; m_WORD MultiFactor,sub_exp,div_1,div_2; I2C_READ ReadData; // judge if the VFHset has conflict with frequency value or not if( frequency >400 && VHFSupport==g_VHFSet) // VHF is 174MHz ~ 245MHz { g_VHFSet=UHFSupport; TunerInit(lowTunerI2CAdr, refClkType ); } else if(frequency <400 && UHFSupport==g_VHFSet) { g_VHFSet=VHFSupport; TunerInit(lowTunerI2CAdr, refClkType ); } PLLR=1; lofreq = frequency*1000; DIVSEL = LO2PLL_Freq(lofreq); Seg_num = (0x01 << DIVSEL); if(Seg_num >=1 && Seg_num <=16) { PLLFREQ = lofreq* (16/Seg_num); Freq=frequency* (16/Seg_num); } else { PLLFREQ = lofreq*2; Freq=frequency*2; } switch(refClkType) { case REFCLK13000: { MTV10x_REFCLK = 130; // 13*MultiFactor MultiFactor=10; sub_exp=1; div_1=5; div_2=13; // 130=13*5*(2^1) break; } case REFCLK16384: { MTV10x_REFCLK = 16384; MultiFactor=1000; sub_exp=14; div_1=1; div_2=1; // 16384== 2^14 break; } case REFCLK19200: { MTV10x_REFCLK = 192; MultiFactor=10; sub_exp=6; div_1=1; div_2=3; // 192 = 2^6 *3 break;} case REFCLK20480: { MTV10x_REFCLK = 2048; MultiFactor=100; sub_exp=11; div_1=1; div_2=1; // 2048 = 2^11 break;} case REFCLK24576: { MTV10x_REFCLK = 24576; MultiFactor=1000; sub_exp=13; div_1=1; div_2=3; // 24576 = 2^13*3 break; } case REFCLK26000: { MTV10x_REFCLK = 260; MultiFactor=10; sub_exp=2; div_1=5; div_2=13; // 260=13*5*(2^2) break;} case REFCLK30400: { MTV10x_REFCLK = 304; MultiFactor=10; PLLR = 2 ; SetLPF(target,REFCLK30400,(unsigned char)lpfBW); swrite(target,0x19, PLLR); //Ref. Clock Divider PLL0 register , bit[7:4] is reserved, bit[3:0] is PLLR sub_exp=4; div_1=1; div_2=19; // 304 = 16*19 break; } case REFCLK36000: { MTV10x_REFCLK = 360; MultiFactor=10; sub_exp=3; div_1=5; div_2=9; // 360=2^3*9*5 break;} case REFCLK38400:{ MTV10x_REFCLK = 384; MultiFactor=10; sub_exp=7; div_1=1; div_2=3; // 384 = 2^7 *3 break;} case REFCLK20000:{ MTV10x_REFCLK = 200; MultiFactor=10; sub_exp=3; div_1=5; div_2=5; // 200=8*5*5 break;} default: {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -