提交SMOD ATSC IMX APP版本 V122

This commit is contained in:
2026-07-16 14:35:59 +08:00
commit 7601c270d5
485 changed files with 255032 additions and 0 deletions
+574
View File
@@ -0,0 +1,574 @@
/*------------------------------------------------------------------------------
Copyright 2012-2013 Sony Semiconductor Solutions Corporation
Last Updated : 2013/05/15
File Revision : 1.0.3.0
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
Based on HORUS3A(CXD2832A) application note 1.1.2
------------------------------------------------------------------------------*/
#include "sony_horus3a.h"
/*------------------------------------------------------------------------------
Definitions of static functions
------------------------------------------------------------------------------*/
/**
@brief Configure the HORUS3A tuner from Power On to Power Save state.
*/
static sony_result_t Initialize(sony_horus3a_t *pTuner);
/**
@brief Configure the HORUS3A tuner to Active state.
*/
static sony_result_t Tune(sony_horus3a_t *pTuner, uint32_t frequencykHz,
sony_horus3a_tv_system_t tvSystem, uint32_t symbolRateksps);
/**
@brief Configure the HORUS3A tuner to Power Save state.
*/
static sony_result_t EnterPowerSave(sony_horus3a_t *pTuner);
/**
@brief Configure the HORUS3A tuner to go out from Power Save state.
*/
static sony_result_t LeavePowerSave(sony_horus3a_t *pTuner);
/*------------------------------------------------------------------------------
Implementation
------------------------------------------------------------------------------*/
sony_result_t sony_horus3a_Create(sony_horus3a_t *pTuner, uint32_t xtalFreqMHz,
uint8_t i2cAddress, sony_i2c_t *pI2c, uint32_t flags)
{
SONY_TRACE_ENTER("sony_horus3a_Create");
if((!pTuner) || (!pI2c)){
SONY_TRACE_RETURN(SONY_RESULT_ERROR_ARG);
}
if((xtalFreqMHz != 16) && (xtalFreqMHz != 24) && (xtalFreqMHz != 27)){
SONY_TRACE_RETURN(SONY_RESULT_ERROR_ARG);
}
pTuner->state = SONY_HORUS3A_STATE_UNKNOWN; /* Chip is not accessed for now */
pTuner->xtalFreqMHz = xtalFreqMHz;
pTuner->pI2c = pI2c;
pTuner->i2cAddress = i2cAddress;
pTuner->flags = flags;
pTuner->frequencykHz = 0;
pTuner->tvSystem = SONY_HORUS3A_TV_SYSTEM_UNKNOWN;
pTuner->symbolRateksps = 0;
pTuner->user = NULL;
SONY_TRACE_RETURN(SONY_RESULT_OK);
}
sony_result_t sony_horus3a_Initialize(sony_horus3a_t *pTuner)
{
sony_result_t result = SONY_RESULT_OK;
SONY_TRACE_ENTER("sony_horus3a_Initialize");
if((!pTuner) || (!pTuner->pI2c)){
SONY_TRACE_RETURN(SONY_RESULT_ERROR_ARG);
}
/* Wait 4ms after power on */
SONY_SLEEP(4);
result = Initialize(pTuner);
if(result != SONY_RESULT_OK){ SONY_TRACE_RETURN(result); }
pTuner->state = SONY_HORUS3A_STATE_SLEEP;
pTuner->frequencykHz = 0;
pTuner->tvSystem = SONY_HORUS3A_TV_SYSTEM_UNKNOWN;
pTuner->symbolRateksps = 0;
SONY_TRACE_RETURN(SONY_RESULT_OK);
}
sony_result_t sony_horus3a_Tune(sony_horus3a_t *pTuner, uint32_t frequencykHz,
sony_horus3a_tv_system_t tvSystem, uint32_t symbolRateksps)
{
sony_result_t result = SONY_RESULT_OK;
SONY_TRACE_ENTER("sony_horus3a_Tune");
if((!pTuner) || (!pTuner->pI2c)){
SONY_TRACE_RETURN(SONY_RESULT_ERROR_ARG);
}
if((pTuner->state != SONY_HORUS3A_STATE_SLEEP) && (pTuner->state != SONY_HORUS3A_STATE_ACTIVE)){
SONY_TRACE_RETURN(SONY_RESULT_ERROR_SW_STATE);
}
/* Rough frequency range check */
if((frequencykHz < 500000) || (frequencykHz > 2500000)){
SONY_TRACE_RETURN(SONY_RESULT_ERROR_RANGE);
}
if(pTuner->state == SONY_HORUS3A_STATE_SLEEP){
result = LeavePowerSave(pTuner);
if(result != SONY_RESULT_OK){ SONY_TRACE_RETURN(result); }
}
result = Tune(pTuner, frequencykHz, tvSystem, symbolRateksps);
if(result != SONY_RESULT_OK){ SONY_TRACE_RETURN(result); }
pTuner->state = SONY_HORUS3A_STATE_ACTIVE;
/* pTuner->frequencykHz will be updated in Tune function */
pTuner->tvSystem = tvSystem;
pTuner->symbolRateksps = symbolRateksps;
SONY_TRACE_RETURN(SONY_RESULT_OK);
}
sony_result_t sony_horus3a_Sleep(sony_horus3a_t *pTuner)
{
sony_result_t result = SONY_RESULT_OK;
SONY_TRACE_ENTER("sony_horus3a_Sleep");
if((!pTuner) || (!pTuner->pI2c)){
SONY_TRACE_RETURN(SONY_RESULT_ERROR_ARG);
}
if((pTuner->state != SONY_HORUS3A_STATE_SLEEP) && (pTuner->state != SONY_HORUS3A_STATE_ACTIVE)){
SONY_TRACE_RETURN(SONY_RESULT_ERROR_SW_STATE);
}
result = EnterPowerSave(pTuner);
if(result != SONY_RESULT_OK){ SONY_TRACE_RETURN(result); }
pTuner->state = SONY_HORUS3A_STATE_SLEEP;
pTuner->frequencykHz = 0;
pTuner->tvSystem = SONY_HORUS3A_TV_SYSTEM_UNKNOWN;
pTuner->symbolRateksps = 0;
SONY_TRACE_RETURN(SONY_RESULT_OK);
}
sony_result_t sony_horus3a_SetGPO(sony_horus3a_t *pTuner, uint8_t output)
{
sony_result_t result = SONY_RESULT_OK;
SONY_TRACE_ENTER("sony_horus3a_SetGPO");
if((!pTuner) || (!pTuner->pI2c)){
SONY_TRACE_RETURN(SONY_RESULT_ERROR_ARG);
}
/* Write GPIO[1:0] */
result = sony_i2c_SetRegisterBits(pTuner->pI2c, pTuner->i2cAddress, 0x2D, (uint8_t)(output ? 0x40 : 0x00), 0xC0);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
SONY_TRACE_RETURN(SONY_RESULT_OK);
}
/*------------------------------------------------------------------------------
Implementation of static functions
------------------------------------------------------------------------------*/
static sony_result_t Initialize(sony_horus3a_t *pTuner)
{
sony_result_t result = SONY_RESULT_OK;
SONY_TRACE_ENTER("Initialize");
if((!pTuner) || (!pTuner->pI2c)){
SONY_TRACE_RETURN(SONY_RESULT_ERROR_ARG);
}
/* IQ Generator disable */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x2A, 0x79);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
/* 0x06 - 0x08 */
{
uint8_t data[3];
/* REF_R = Xtal Frequency */
data[0] = (uint8_t)(pTuner->xtalFreqMHz);
/* FIN = Xtal Frequency */
data[1] = (uint8_t)(pTuner->xtalFreqMHz);
data[2] = 0x00;
result = pTuner->pI2c->WriteRegister(pTuner->pI2c, pTuner->i2cAddress, 0x06, data, sizeof(data));
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
}
switch(pTuner->flags & SONY_HORUS3A_CONFIG_IQOUT_MASK){
case SONY_HORUS3A_CONFIG_IQOUT_DIFFERENTIAL:
/* IQ Out = Differential */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x0A, 0x00);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
break;
case SONY_HORUS3A_CONFIG_IQOUT_SINGLEEND:
/* IQ Out = Single Ended */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x0A, 0x40);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
break;
case SONY_HORUS3A_CONFIG_IQOUT_SINGLEEND_LOWGAIN:
/* IQ Out = Single Ended (Low Gain) */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x0A, 0xC0);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
break;
default:
SONY_TRACE_RETURN(SONY_RESULT_ERROR_OTHER);
}
{
uint8_t data = 0;
/* XOSC_SEL setting */
if(pTuner->flags & SONY_HORUS3A_CONFIG_EXT_REF){
data = 0x00;
}else{
switch(pTuner->xtalFreqMHz){
case 27:
data = 0x1F; break;
case 24:
data = 0x10; break;
case 16:
data = 0x0C; break;
default:
SONY_TRACE_RETURN(SONY_RESULT_ERROR_OTHER);
}
data <<= 2; /* XOSC_SEL is Bit[6:2] */
}
if(!(pTuner->flags & SONY_HORUS3A_CONFIG_REFOUT_OFF)){
/* REFOUT ON */
data |= 0x80;
}
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x0E, data);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
}
/* Power save setting */
result = EnterPowerSave(pTuner);
if(result != SONY_RESULT_OK){ SONY_TRACE_RETURN(result); }
SONY_SLEEP(3); /* Wait 3ms */
SONY_TRACE_RETURN(SONY_RESULT_OK);
}
static sony_result_t Tune(sony_horus3a_t *pTuner, uint32_t frequencykHz,
sony_horus3a_tv_system_t tvSystem, uint32_t symbolRateksps)
{
sony_result_t result = SONY_RESULT_OK;
uint8_t mixdiv = 0;
uint8_t mdiv = 0;
uint32_t ms = 0;
uint8_t f_ctl = 0;
uint8_t g_ctl = 0;
uint8_t fc_lpf = 0;
SONY_TRACE_ENTER("Tune");
/* frequency should be X MHz (X : integer) */
frequencykHz = ((frequencykHz + 500) / 1000) * 1000;
switch(tvSystem){
case SONY_HORUS3A_STV_ISDBS:
if(frequencykHz <= 1100000){
mixdiv = 4;
mdiv = 1;
}else{
mixdiv = 2;
mdiv = 0;
}
break;
case SONY_HORUS3A_STV_DVBS:
case SONY_HORUS3A_STV_DVBS2:
if(frequencykHz <= 1155000){
mixdiv = 4;
mdiv = 1;
}else{
mixdiv = 2;
mdiv = 0;
}
break;
default:
SONY_TRACE_RETURN(SONY_RESULT_ERROR_ARG); /* Invalid system */
}
/* Assumed that fREF == 1MHz (1000kHz) */
ms = ((frequencykHz * mixdiv)/2 + 1000/2) / 1000; /* Round */
if(ms > 0x7FFF){ /* 15 bit */
SONY_TRACE_RETURN(SONY_RESULT_ERROR_ARG); /* Invalid frequency */
}
/* Setup RF tracking filter */
if(pTuner->flags & SONY_HORUS3A_CONFIG_LNA_ENABLE){
if(frequencykHz < 975000){
/* F_CTL=11100 G_CTL=001 */
f_ctl = 0x1C; g_ctl = 0x01;
}else if(frequencykHz < 1050000){
/* F_CTL=11000 G_CTL=010 */
f_ctl = 0x18; g_ctl = 0x02;
}else if(frequencykHz < 1150000){
/* F_CTL=10100 G_CTL=010 */
f_ctl = 0x14; g_ctl = 0x02;
}else if(frequencykHz < 1250000){
/* F_CTL=10000 G_CTL=011 */
f_ctl = 0x10; g_ctl = 0x03;
}else if(frequencykHz < 1350000){
/* F_CTL=01100 G_CTL=100 */
f_ctl = 0x0C; g_ctl = 0x04;
}else if(frequencykHz < 1450000){
/* F_CTL=01010 G_CTL=100 */
f_ctl = 0x0A; g_ctl = 0x04;
}else if(frequencykHz < 1600000){
/* F_CTL=00111 G_CTL=101 */
f_ctl = 0x07; g_ctl = 0x05;
}else if(frequencykHz < 1800000){
/* F_CTL=00100 G_CTL=110 */
f_ctl = 0x04; g_ctl = 0x06;
}else if(frequencykHz < 2000000){
/* F_CTL=00010 G_CTL=110 */
f_ctl = 0x02; g_ctl = 0x06;
}else{
/* F_CTL=00000 G_CTL=111 */
f_ctl = 0x00; g_ctl = 0x07;
}
}else{
if(frequencykHz < 975000){
/* F_CTL=11100 G_CTL=001 */
f_ctl = 0x1C; g_ctl = 0x01;
}else if(frequencykHz < 1050000){
/* F_CTL=11000 G_CTL=010 */
f_ctl = 0x18; g_ctl = 0x02;
}else if(frequencykHz < 1150000){
/* F_CTL=10100 G_CTL=010 */
f_ctl = 0x14; g_ctl = 0x02;
}else if(frequencykHz < 1250000){
/* F_CTL=10000 G_CTL=011 */
f_ctl = 0x10; g_ctl = 0x03;
}else if(frequencykHz < 1350000){
/* F_CTL=01100 G_CTL=100 */
f_ctl = 0x0C; g_ctl = 0x04;
}else if(frequencykHz < 1450000){
/* F_CTL=01010 G_CTL=100 */
f_ctl = 0x0A; g_ctl = 0x04;
}else if(frequencykHz < 1600000){
/* F_CTL=00111 G_CTL=101 */
f_ctl = 0x07; g_ctl = 0x05;
}else if(frequencykHz < 1800000){
/* F_CTL=00100 G_CTL=010 */
f_ctl = 0x04; g_ctl = 0x02;
}else if(frequencykHz < 2000000){
/* F_CTL=00010 G_CTL=001 */
f_ctl = 0x02; g_ctl = 0x01;
}else{
/* F_CTL=00000 G_CTL=000 */
f_ctl = 0x00; g_ctl = 0x00;
}
}
/* LPF cutoff frequency setting */
switch(tvSystem){
case SONY_HORUS3A_STV_ISDBS:
fc_lpf = 22; /* 22MHz */
break;
case SONY_HORUS3A_STV_DVBS:
/*
rolloff = 0.35
SR <= 4.3
fc_lpf = 5
4.3 < SR <= 10
fc_lpf = SR * (1 + rolloff) / 2 + SR / 2 = SR * 1.175 = SR * (47/40)
10 < SR
fc_lpf = SR * (1 + rolloff) / 2 + 5 = SR * 0.675 + 5 = SR * (27/40) + 5
NOTE: The result should be round up.
*/
if(symbolRateksps <= 4300){
fc_lpf = 5;
}else if(symbolRateksps <= 10000){
fc_lpf = (uint8_t)((symbolRateksps * 47 + (40000-1)) / 40000);
}else{
fc_lpf = (uint8_t)((symbolRateksps * 27 + (40000-1)) / 40000 + 5);
}
if(fc_lpf > 36){
fc_lpf = 36; /* 5 <= fc_lpf <= 36 is valid */
}
break;
case SONY_HORUS3A_STV_DVBS2:
/*
rolloff = 0.2
SR <= 4.5
fc_lpf = 5
4.5 < SR <= 10
fc_lpf = SR * (1 + rolloff) / 2 + SR / 2 = SR * 1.1 = SR * (11/10)
10 < SR
fc_lpf = SR * (1 + rolloff) / 2 + 5 = SR * 0.6 + 5 = SR * (3/5) + 5
NOTE: The result should be round up.
*/
if(symbolRateksps <= 4500){
fc_lpf = 5;
}else if(symbolRateksps <= 10000){
fc_lpf = (uint8_t)((symbolRateksps * 11 + (10000-1)) / 10000);
}else{
fc_lpf = (uint8_t)((symbolRateksps * 3 + (5000-1)) / 5000 + 5);
}
if(fc_lpf > 36){
fc_lpf = 36; /* 5 <= fc_lpf <= 36 is valid */
}
break;
default:
SONY_TRACE_RETURN(SONY_RESULT_ERROR_ARG); /* Invalid system */
}
/* 0x00 - 0x04 */
{
uint8_t data[5];
data[0] = (uint8_t)((ms >> 7) & 0xFF);
data[1] = (uint8_t)((ms << 1) & 0xFF);
data[2] = 0x00;
data[3] = 0x00;
data[4] = (uint8_t)(mdiv << 7);
result = pTuner->pI2c->WriteRegister(pTuner->pI2c, pTuner->i2cAddress, 0x00, data, sizeof(data));
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
}
/* Write G_CTL, F_CTL */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x09, (uint8_t)((g_ctl << 5) | f_ctl));
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
/* Write LPF cutoff frequency */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x37, (uint8_t)(0x80 | (fc_lpf << 1)));
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
/* Start Calibration */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x05, 0x80);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
/* IQ Generator enable */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x2A, 0x7B);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
SONY_SLEEP(10);
/* Store tuned frequency to the struct */
pTuner->frequencykHz = ms * 2 * 1000 / mixdiv;
SONY_TRACE_RETURN(SONY_RESULT_OK);
}
static sony_result_t EnterPowerSave(sony_horus3a_t *pTuner)
{
sony_result_t result = SONY_RESULT_OK;
SONY_TRACE_ENTER("EnterPowerSave");
if((!pTuner) || (!pTuner->pI2c)){
SONY_TRACE_RETURN(SONY_RESULT_ERROR_ARG);
}
/* IQ Generator disable */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x2A, 0x79);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
/* MDIV_EN = 0 */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x29, 0x70);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
/* VCO disable preparation */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x28, 0x3E);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
/* VCO buffer disable */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x2A, 0x19);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
/* VCO calibration disable */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x1C, 0x00);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
/* 0x11 - 0x12 */
{
uint8_t data[2];
if(pTuner->flags & SONY_HORUS3A_CONFIG_POWERSAVE_ENABLEXTAL){
/* Power save setting (xtal is not stopped) */
data[0] = 0xC0;
}else{
/* Power save setting (xtal is stopped) */
data[0] = 0x80;
}
if(pTuner->flags & SONY_HORUS3A_CONFIG_LNA_ENABLE){
if(pTuner->flags & SONY_HORUS3A_CONFIG_POWERSAVE_STOPLNA){
/* LNA is stopped */
data[1] = 0x23;
}else{
/* LNA is not stopped */
data[1] = 0x27;
}
}else{
/* LNA is Disabled */
data[1] = 0xA7;
}
result = pTuner->pI2c->WriteRegister(pTuner->pI2c, pTuner->i2cAddress, 0x11, data, sizeof(data));
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
}
SONY_TRACE_RETURN(SONY_RESULT_OK);
}
static sony_result_t LeavePowerSave(sony_horus3a_t *pTuner)
{
sony_result_t result = SONY_RESULT_OK;
SONY_TRACE_ENTER("LeavePowerSave");
if((!pTuner) || (!pTuner->pI2c)){
SONY_TRACE_RETURN(SONY_RESULT_ERROR_ARG);
}
/* 0x11 - 0x12 */
{
uint8_t data[2];
/* Disable power save */
data[0] = 0x00;
if(pTuner->flags & SONY_HORUS3A_CONFIG_LNA_ENABLE){
/* LNA is Enabled */
data[1] = 0x27;
}else{
/* LNA is Disabled */
data[1] = 0xA7;
}
result = pTuner->pI2c->WriteRegister(pTuner->pI2c, pTuner->i2cAddress, 0x11, data, sizeof(data));
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
}
/* VCO buffer enable */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x2A, 0x79);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
/* VCO calibration enable */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x1C, 0xC0);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
/* MDIV_EN = 1 */
result = pTuner->pI2c->WriteOneRegister(pTuner->pI2c, pTuner->i2cAddress, 0x29, 0x71);
if(result != SONY_RESULT_OK) { SONY_TRACE_RETURN(SONY_RESULT_ERROR_I2C); }
if(!(pTuner->flags & SONY_HORUS3A_CONFIG_POWERSAVE_ENABLEXTAL)){
/* Wait Xtal stable */
SONY_SLEEP(5);
}
SONY_TRACE_RETURN(SONY_RESULT_OK);
}
+186
View File
@@ -0,0 +1,186 @@
/*------------------------------------------------------------------------------
Copyright 2012-2013 Sony Semiconductor Solutions Corporation
Last Updated : 2013/05/15
File Revision : 1.0.3.0
------------------------------------------------------------------------------*/
/**
@file sony_horus3a.h
This file provides the HORUS3A tuner control interface.
*/
/*----------------------------------------------------------------------------*/
#ifndef SONY_HORUS3A_H
#define SONY_HORUS3A_H
#include "sony_common.h"
#include "sony_i2c.h"
/*------------------------------------------------------------------------------
Defines
------------------------------------------------------------------------------*/
/**
@brief Version of this driver.
*/
#define SONY_HORUS3A_VERSION "1.0.3.0"
/**
@brief Default I2C slave address of the HORUS3A tuner.
*/
#define SONY_HORUS3A_ADDRESS 0xC0
/*------------------------------------------------------------------------------
Enums
------------------------------------------------------------------------------*/
/**
@brief HORUS3A tuner state.
*/
typedef enum {
SONY_HORUS3A_STATE_UNKNOWN,
SONY_HORUS3A_STATE_SLEEP,
SONY_HORUS3A_STATE_ACTIVE
} sony_horus3a_state_t;
/**
@brief Satellite broadcasting system definitions supported by HORUS3A.
*/
typedef enum {
SONY_HORUS3A_TV_SYSTEM_UNKNOWN,
SONY_HORUS3A_STV_ISDBS, /**< ISDB-S */
SONY_HORUS3A_STV_DVBS, /**< DVB-S */
SONY_HORUS3A_STV_DVBS2 /**< DVB-S2 */
} sony_horus3a_tv_system_t;
/*------------------------------------------------------------------------------
Structs
------------------------------------------------------------------------------*/
/**
@brief The HORUS3A tuner definition which allows control of the HORUS3A tuner device
through the defined set of functions.
*/
typedef struct sony_horus3a_t {
uint32_t xtalFreqMHz; /**< Xtal frequency for HORUS3A in MHz. */
uint8_t i2cAddress; /**< I2C slave address of the HORUS3A tuner (8-bit form - 8'bxxxxxxx0) */
sony_i2c_t* pI2c; /**< I2C API instance. */
uint32_t flags; /**< ORed value of SONY_HORUS3A_CONFIG_XXXX */
/* For saving current setting */
sony_horus3a_state_t state; /**< The driver operating state. */
uint32_t frequencykHz; /**< Currently RF frequency(kHz) tuned. */
sony_horus3a_tv_system_t tvSystem; /**< Current broadcasting system tuned. */
uint32_t symbolRateksps; /**< Current symbol rate(ksym/s) tuned. */
void* user; /**< User defined data. */
} sony_horus3a_t;
/*
Config flag definitions. (ORed value should be set to flags argument of Create API.)
*/
/**
@brief REFOUT output Off
*/
#define SONY_HORUS3A_CONFIG_REFOUT_OFF 0x80000000
/**
@brief Keep Xtal enable in power save state.
Should be used for Xtal shared system.
Not only for the master HORUS3A which has Xtal, but also slave HORUS3A which receive the clock signal.
*/
#define SONY_HORUS3A_CONFIG_POWERSAVE_ENABLEXTAL 0x40000000
/**
@brief Use external Xtal
Should be used for slave HORUS3A in Xtal shared system.
*/
#define SONY_HORUS3A_CONFIG_EXT_REF 0x20000000
/**
@brief Internal LNA enable
*/
#define SONY_HORUS3A_CONFIG_LNA_ENABLE 0x10000000
/**
@brief Stop internal LNA in power save state.
This flag is ignored if SONY_HORUS3A_CONFIG_LNA_ENABLE is not used.
*/
#define SONY_HORUS3A_CONFIG_POWERSAVE_STOPLNA 0x08000000
/**
@name IQ output setting.
One of following value should be used.
*/
/**@{*/
#define SONY_HORUS3A_CONFIG_IQOUT_DIFFERENTIAL 0x00000000 /**< IQ Output is Differential */
#define SONY_HORUS3A_CONFIG_IQOUT_SINGLEEND 0x01000000 /**< IQ Output is Single-Ended (+4.4dB) */
#define SONY_HORUS3A_CONFIG_IQOUT_SINGLEEND_LOWGAIN 0x02000000 /**< IQ Output is Single-Ended (-2.4dB) */
#define SONY_HORUS3A_CONFIG_IQOUT_MASK 0x03000000 /**< DON'T set this value. (Internal use only) */
/**@}*/
/*------------------------------------------------------------------------------
APIs
------------------------------------------------------------------------------*/
/**
@brief Set up the HORUS3A tuner driver.
This MUST be called before calling sony_horus3a_Initialize.
@param pTuner Reference to memory allocated for the HORUS3A instance.
The create function will setup this HORUS3A instance.
@param xtalFreqMHz The frequency of the HORUS3A crystal.
@param i2cAddress The HORUS3A tuner I2C slave address in 8-bit form.
@param pI2c The I2C APIs that the HORUS3A driver will use as the I2C interface.
@param flags Configuration flags. It should be ORed value of SONY_HORUS3A_CONFIG_XXXX.
@return SONY_RESULT_OK if successful.
*/
sony_result_t sony_horus3a_Create(sony_horus3a_t *pTuner, uint32_t xtalFreqMHz,
uint8_t i2cAddress, sony_i2c_t *pI2c, uint32_t flags);
/**
@brief Initialize the HORUS3A tuner.
This MUST be called before calling sony_horus3a_Tune.
@param pTuner The HORUS3A tuner instance.
@return SONY_RESULT_OK if successful.
*/
sony_result_t sony_horus3a_Initialize(sony_horus3a_t *pTuner);
/**
@brief Tune to a given RF frequency with broadcasting system.
@param pTuner The HORUS3A tuner instance.
@param frequencykHz RF frequency to tune. (kHz)
@param tvSystem The type of broadcasting system to tune.
@param symbolRateksps Symbol rate to tune. (ksps)
@return SONY_RESULT_OK if tuner successfully tuned.
*/
sony_result_t sony_horus3a_Tune(sony_horus3a_t *pTuner, uint32_t frequencykHz,
sony_horus3a_tv_system_t tvSystem, uint32_t symbolRateksps);
/**
@brief Put the HORUS3A tuner into Sleep state.
From this state the tuner can be directly tuned by calling sony_horus3a_Tune.
@param pTuner The HORUS3A tuner instance.
@return SONY_RESULT_OK if successful.
*/
sony_result_t sony_horus3a_Sleep(sony_horus3a_t *pTuner);
/**
@brief Write to GPO
@param pTuner The HORUS3A tuner instance.
@param output Output logic level, 0 = Low, 1 = High
@return SONY_RESULT_OK if successful.
*/
sony_result_t sony_horus3a_SetGPO(sony_horus3a_t *pTuner, uint8_t output);
#endif /* SONY_HORUS3A_H */
+273
View File
@@ -0,0 +1,273 @@
/*------------------------------------------------------------------------------
Copyright 2016-2018 Sony Semiconductor Solutions Corporation
Last Updated : 2018/07/05
Modification ID : c7c68d70868a4a9fb9e0f480d8b940e8a1e8f651
------------------------------------------------------------------------------*/
#include "sony_tuner_horus3a.h"
#include <string.h>
#include <stdlib.h>
/*------------------------------------------------------------------------------
Static Functions
------------------------------------------------------------------------------*/
static sony_result_t sony_tuner_horus3a_Initialize (sony_tuner_t * pTuner);
static sony_result_t sony_tuner_horus3a_Tune (sony_tuner_t * pTuner,
uint32_t centerFreqKHz,
sony_dtv_system_t system,
uint32_t symbolRateKSps);
static sony_result_t sony_tuner_horus3a_Sleep (sony_tuner_t * pTuner);
static sony_result_t sony_tuner_horus3a_Shutdown (sony_tuner_t * pTuner);
static sony_result_t sony_tuner_horus3a_CalcRFLevelFromAGC (sony_tuner_t * pTuner,
uint32_t agcValue,
int32_t * pRFLevel);
/*------------------------------------------------------------------------------
Functions
------------------------------------------------------------------------------*/
sony_result_t sony_tuner_horus3a_Create (sony_tuner_t * pTuner,
uint32_t xtalFreqMHz,
uint8_t i2cAddress,
sony_i2c_t * pI2c,
uint32_t configFlags,
sony_horus3a_t * pHorus3a)
{
sony_result_t result = SONY_RESULT_OK;
SONY_TRACE_ENTER ("sony_tuner_horus3a_Create");
if ((!pI2c) || (!pHorus3a) || (!pTuner)){
SONY_TRACE_RETURN (SONY_RESULT_ERROR_ARG);
}
memset (pTuner, 0, sizeof (sony_tuner_t)); /* Zero filled */
result = sony_horus3a_Create (pHorus3a, xtalFreqMHz, i2cAddress, pI2c, configFlags);
if (result != SONY_RESULT_OK){SONY_TRACE_RETURN (result);}
/* Populate / Initialize the sony_tuner_t structure */
pTuner->i2cAddress = i2cAddress;
pTuner->pI2c = pI2c;
pTuner->flags = configFlags;
pTuner->symbolRateKSpsForSpectrum = 45000;
pTuner->rfLevelFuncTerr = SONY_TUNER_RFLEVEL_FUNC_NOSUPPORT; /* Not supported for terrestrial */
pTuner->rfLevelFuncSat = SONY_TUNER_RFLEVEL_FUNC_CALCFROMAGC; /* Use CalcRFLevelFromAGC function for satellite */
pTuner->user = pHorus3a;
pTuner->Initialize = sony_tuner_horus3a_Initialize;
pTuner->TerrCableTune = NULL;
pTuner->SatTune = sony_tuner_horus3a_Tune;
pTuner->Shutdown = sony_tuner_horus3a_Shutdown;
pTuner->Sleep = sony_tuner_horus3a_Sleep;
pTuner->ReadRFLevel = NULL;
pTuner->CalcRFLevelFromAGC = sony_tuner_horus3a_CalcRFLevelFromAGC;
SONY_TRACE_RETURN (SONY_RESULT_OK);
}
sony_result_t sony_tuner_horus3a_SetGPO (sony_tuner_t * pTuner, uint8_t value)
{
sony_result_t result = SONY_RESULT_OK;
SONY_TRACE_ENTER ("sony_tuner_horus3a_SetGPO");
if (!pTuner || !pTuner->user) {
SONY_TRACE_RETURN (SONY_RESULT_ERROR_ARG);
}
result = sony_horus3a_SetGPO (((sony_horus3a_t *) pTuner->user), value);
SONY_TRACE_RETURN (result);
}
static sony_result_t sony_tuner_horus3a_Initialize (sony_tuner_t * pTuner)
{
sony_result_t result = SONY_RESULT_OK;
sony_horus3a_t * pHorus3a = NULL;
SONY_TRACE_ENTER ("sony_tuner_horus3a_Initialize");
if ((!pTuner) || (!pTuner->user)){
SONY_TRACE_RETURN (SONY_RESULT_ERROR_ARG);
}
pHorus3a = (sony_horus3a_t *)(pTuner->user);
result = sony_horus3a_Initialize (pHorus3a);
if (result != SONY_RESULT_OK){SONY_TRACE_RETURN (result);}
pTuner->frequencyKHz = 0;
pTuner->system = SONY_DTV_SYSTEM_UNKNOWN;
pTuner->bandwidth = SONY_DTV_BW_UNKNOWN;
pTuner->symbolRateKSps = 0;
SONY_TRACE_RETURN (result);
}
static sony_result_t sony_tuner_horus3a_Tune (sony_tuner_t * pTuner,
uint32_t centerFreqKHz,
sony_dtv_system_t system,
uint32_t symbolRateKSps)
{
sony_result_t result = SONY_RESULT_OK;
sony_horus3a_t * pHorus3a = NULL;
sony_horus3a_tv_system_t satSystem = SONY_HORUS3A_STV_DVBS2;
SONY_TRACE_ENTER ("sony_tuner_horus3a_Tune");
if ((!pTuner) || (!pTuner->user)){
SONY_TRACE_RETURN (SONY_RESULT_ERROR_ARG);
}
pHorus3a = (sony_horus3a_t *)(pTuner->user);
switch(system)
{
case SONY_DTV_SYSTEM_DVBS:
satSystem = SONY_HORUS3A_STV_DVBS;
break;
case SONY_DTV_SYSTEM_DVBS2:
satSystem = SONY_HORUS3A_STV_DVBS2;
break;
case SONY_DTV_SYSTEM_ISDBS:
case SONY_DTV_SYSTEM_ISDBS3:
satSystem = SONY_HORUS3A_STV_ISDBS;
break;
default:
SONY_TRACE_RETURN (SONY_RESULT_ERROR_ARG);
}
result = sony_horus3a_Tune (pHorus3a, centerFreqKHz, satSystem, symbolRateKSps);
if (result != SONY_RESULT_OK) {
SONY_TRACE_RETURN (result);
}
pTuner->frequencyKHz = pHorus3a->frequencykHz;
pTuner->system = system;
pTuner->bandwidth = SONY_DTV_BW_UNKNOWN;
pTuner->symbolRateKSps = symbolRateKSps;
/* Tuner stabillization time */
SONY_SLEEP (50);
SONY_TRACE_RETURN (result);
}
static sony_result_t sony_tuner_horus3a_Sleep (sony_tuner_t * pTuner)
{
sony_result_t result = SONY_RESULT_OK;
sony_horus3a_t * pHorus3a = NULL;
SONY_TRACE_ENTER ("sony_tuner_horus3a_Sleep");
if ((!pTuner) || (!pTuner->user)){
SONY_TRACE_RETURN (SONY_RESULT_ERROR_ARG);
}
pHorus3a = (sony_horus3a_t *)(pTuner->user);
result = sony_horus3a_Sleep (pHorus3a);
if (result != SONY_RESULT_OK){SONY_TRACE_RETURN (result);}
pTuner->frequencyKHz = 0;
pTuner->system = SONY_DTV_SYSTEM_UNKNOWN;
pTuner->bandwidth = SONY_DTV_BW_UNKNOWN;
pTuner->symbolRateKSps = 0;
SONY_TRACE_RETURN (result);
}
static sony_result_t sony_tuner_horus3a_Shutdown (sony_tuner_t * pTuner)
{
sony_result_t result = SONY_RESULT_OK;
sony_horus3a_t * pHorus3a = NULL;
SONY_TRACE_ENTER ("sony_tuner_horus3a_Shutdown");
if ((!pTuner) || (!pTuner->user)){
SONY_TRACE_RETURN (SONY_RESULT_ERROR_ARG);
}
pHorus3a = (sony_horus3a_t *)(pTuner->user);
result = sony_horus3a_Sleep (pHorus3a);
if (result != SONY_RESULT_OK){SONY_TRACE_RETURN (result);}
pTuner->frequencyKHz = 0;
pTuner->system = SONY_DTV_SYSTEM_UNKNOWN;
pTuner->bandwidth = SONY_DTV_BW_UNKNOWN;
pTuner->symbolRateKSps = 0;
SONY_TRACE_RETURN (result);
}
static sony_result_t sony_tuner_horus3a_CalcRFLevelFromAGC (sony_tuner_t * pTuner,
uint32_t agcValue,
int32_t * pRFLevel)
{
int32_t tempA = 0;
uint8_t isNegative = 0;
uint32_t tempDiv = 0;
uint32_t tempQ = 0;
uint32_t tempR = 0;
SONY_TRACE_ENTER("sony_tuner_horus3a_CalcRFLevelFromAGC");
if ((!pTuner) || (!pRFLevel)) {
SONY_TRACE_RETURN (SONY_RESULT_ERROR_ARG);
}
if (!SONY_DTV_SYSTEM_IS_SAT (pTuner->system)) {
/* Satellite Only */
SONY_TRACE_RETURN (SONY_RESULT_ERROR_SW_STATE);
}
/*------------------------------------------------
Gain_db = (AGCLevel - 8192) * (- 33/1024) - 142
Gain_db_x100 = (AGCLevel - 8192) * (-3300/1024) - 14200
= (AGCLevel - 8192) * (- 825/ 256) - 14200
------------------------------------------------*/
tempA = (int32_t)agcValue - 8192;
tempA *= -825;
tempDiv = 256;
if (tempA > 0) {
isNegative = 0;
tempQ = (uint32_t)tempA / tempDiv;
tempR = (uint32_t)tempA % tempDiv;
} else {
isNegative = 1;
tempQ = (uint32_t)(tempA * (-1)) / tempDiv;
tempR = (uint32_t)(tempA * (-1)) % tempDiv;
}
if (isNegative) {
if (tempR >= (tempDiv/2)) {
*pRFLevel = (int32_t)(tempQ + 1) * (int32_t)(-1);
} else {
*pRFLevel = (int32_t)tempQ * (int32_t)(-1);
}
} else {
if (tempR >= (tempDiv/2)) {
*pRFLevel = (int32_t)(tempQ + 1);
} else {
*pRFLevel = (int32_t)tempQ;
}
}
*pRFLevel -= 14200;
/*
* RF_Level = Input_Ref_Level - RF_Gain
* -> Input_Ref_Level = 0dB for this demodulator
*/
*pRFLevel *= -1;
SONY_TRACE_RETURN(SONY_RESULT_OK);
}
+67
View File
@@ -0,0 +1,67 @@
/*------------------------------------------------------------------------------
Copyright 2016-2018 Sony Semiconductor Solutions Corporation
Last Updated : 2018/07/05
Modification ID : c7c68d70868a4a9fb9e0f480d8b940e8a1e8f651
------------------------------------------------------------------------------*/
/**
@file sony_tuner_horus3a.h
This file provides the tuner control function for HORUS3A(CXD2832).
*/
/*----------------------------------------------------------------------------*/
#ifndef SONY_TUNER_HORUS3A_H
#define SONY_TUNER_HORUS3A_H
/*------------------------------------------------------------------------------
Includes
------------------------------------------------------------------------------*/
#include "sony_tuner.h"
#include "sony_horus3a.h"
/*------------------------------------------------------------------------------
Functions
------------------------------------------------------------------------------*/
/**
@brief Create a instance for HORUS3A driver.
@param pTuner The tuner driver instance to create.
Memory must have been allocated for this instance before creation.
@param xtalFreqMHz The crystal frequency of the tuner (MHz).
Supports 16MHz or 24MHz or 27MHz.
@param i2cAddress The I2C address of the HORUS3A device.
Typically 0xC0.
@param pI2c The I2C driver that the tuner driver will use for
communication.
@param configFlags See ::SONY_HORUS3A_CONFIG_REFOUT_OFF,
::SONY_HORUS3A_CONFIG_POWERSAVE_ENABLEXTAL,
::SONY_HORUS3A_CONFIG_EXT_REF,
::SONY_HORUS3A_CONFIG_LNA_ENABLE,
::SONY_HORUS3A_CONFIG_POWERSAVE_STOPLNA,
::SONY_HORUS3A_CONFIG_IQOUT_DIFFERENTIAL,
::SONY_HORUS3A_CONFIG_IQOUT_SINGLEEND,
::SONY_HORUS3A_CONFIG_IQOUT_SINGLEEND_LOWGAIN defined in
\link sony_horus3a.h \endlink
@param pHorus3a The HORUS3A tuner driver pointer to use.
Memory must have been allocated for the HORUS3A driver structure.
@return SONY_RESULT_OK if successful.
*/
sony_result_t sony_tuner_horus3a_Create (sony_tuner_t * pTuner,
uint32_t xtalFreqMHz,
uint8_t i2cAddress,
sony_i2c_t * pI2c,
uint32_t configFlags,
sony_horus3a_t * pHorus3a);
/**
@brief Write to GPO.
@param pTuner Instance of the tuner driver.
@param value Output logic level, 0 = Low, 1 = High
@return SONY_RESULT_OK if successful.
*/
sony_result_t sony_tuner_horus3a_SetGPO (sony_tuner_t * pTuner, uint8_t value);
#endif /* SONY_TUNER_HORUS3A_H */