📄 saa7112.c
字号:
/*
* Copyright (c) 1995 - 1999 by TriMedia Technologies.
*
* +------------------------------------------------------------------+
* | This software is furnished under a license and may only be used |
* | and copied in accordance with the terms and conditions of such |
* | a license and with the inclusion of this copyright notice. This |
* | software or any other copies of this software may not be provided|
* | or otherwise made available to any other person. The ownership |
* | and title of this software is not transferred. |
* | |
* | The information in this software is subject to change without |
* | any prior notice and should not be construed as a commitment by |
* | TriMedia Technologies. |
* | |
* | this code and information is provided "as is" without any |
* | warranty of any kind, either expressed or implied, including but |
* | not limited to the implied warranties of merchantability and/or |
* | fitness for any particular purpose. |
* +------------------------------------------------------------------+
*
* Module name : saa7112.c 1.14
*
* Last update : 18:43:43 - 00/11/09
*
* Description :
*
* Initialize and control routines for saa7112.
*
*
* Revision :
*
*
*/
#include <stdio.h>
#include <tm1/tmIIC.h>
#include <tm1/tmAvFormats.h>
#include <tmlib/dprintf.h>
#include <tm1/tmVIboard.h>
#include <tm1/tmVImmio.h>
#include <saa7112.h>
#define SAA7112_NREGS 0x18
#define VIDEO_CONFIG_NREGS 10 /* number of 7112 registers */
/******************************************************************************/
/* Default structures for video decoder configuration (supports 1 default instance) */
#define NUM_OF_DEF_ADAPTER 2
static boardVIAdapterEntry_t defAdapters[NUM_OF_DEF_ADAPTER] = {
{ vaaCVBS, 0, 1 },
{ vaaSvideo, 0, 9 }
};
static boardVIDec_t defaultVD [1] =
{
{ 0x40, /* I2C slave address of first decoder */
NUM_OF_DEF_ADAPTER, /* Number of adapters */
defAdapters } /* mapping of adapters to inputs */
};
static unsigned char saa7112_regs[SAA7112_NREGS] = {
0x00, 0x00, 0xc4, 0x23, 0x00, 0x00, 0x00, 0x00,
0x88, 0x10, 0x80, 0x47, 0x40, 0x00, 0x01, 0x00,
0xc8, 0xf9, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00
};
static unsigned char video_config_regs[VIDEO_CONFIG_NREGS] = {
0x01, 0x40, 0x08, 0x40, 0x01, 0xC0, 0x41, 0x08, 0x10, 0x80
};
typedef enum
{
ChipVersion= 0x00,
/* front-end part */
IncrementDelay= 0x01,
AnalogInputControl1= 0x02,
AnalogInputControl2= 0x03,
AnalogInputControl3= 0x04,
AnalogInputControl4= 0x05,
/* decoder part */
HorzSyncStart= 0x06,
HorzSyncStop= 0x07,
SyncControl= 0x08,
LuminanceControl= 0x09,
LuminanceBrightness= 0x0A,
LuminanceContrast= 0x0B,
ChromaSaturation= 0x0C,
ChromaHueControl= 0x0D,
ChromaControl1= 0x0E,
ChromaGainControl= 0x0F,
ChromaControl2= 0x10,
ModeDelayControl= 0x11,
RTSignalControl= 0x12,
RTOutputControl= 0x13,
CompatibilityControl= 0x14,
VGateStart= 0x15,
VGateStop= 0x16,
VGateMSB= 0x17,
RawDataGain= 0x18,
RawDataOffset= 0x19,
StatusByte= 0x1F,
/* Textslicer */
AC1= 0x40,
LCR2= 0x41,
LCR3= 0x42,
LCR4= 0x43,
LCR5= 0x44,
LCR6= 0x45,
LCR7= 0x46,
LCR8= 0x47,
LCR9= 0x48,
LCR10= 0x49,
LCR11= 0x4A,
LCR12= 0x4B,
LCR13= 0x4C,
LCR14= 0x4D,
LCR15= 0x4E,
LCR16= 0x4F,
LCR17= 0x50,
LCR18= 0x51,
LCR19= 0x52,
LCR20= 0x53,
LCR21= 0x54,
LCR22= 0x55,
LCR23= 0x56,
LCR24= 0x57,
FC= 0x58,
HOFF= 0x59,
VOFF= 0x5A,
HVOFF= 0x5B,
DID= 0x5D,
SDID= 0x5E,
DR= 0x60,
LN1= 0x61,
LN2= 0x62,
LineFlagsEven1= 0x63,
LineFlagsEven2= 0x64,
LineFlagsEven3= 0x65,
LineFlagsOdd1= 0x66,
LineFlagsOdd2= 0x67,
LineFlagsOdd3= 0x68,
} decoderRegs_t;
static tmVideoAnalogAdapter_t gAdapterType;
static UInt lastI2cError = 0;
/******************************************************************************/
static tmLibdevErr_t
mapAdapterInput (pboardVIDec_t pVD, pboardVIParam_t param, UInt *mode)
{
UInt i;
/* If this is vaaNone then use the default adapter */
if (param->adapterType == vaaNone)
{
*mode = pVD->adapterTable[0].decInput;
return TMLIBDEV_OK;
}
for (i = 0; i < pVD->numAdapters; i++)
{
/* Find the right instance of the adapter */
if ((pVD->adapterTable[i].instNum == param->adapterInstance) &&
(pVD->adapterTable[i].adapterType == param->adapterType))
{
*mode = pVD->adapterTable[i].decInput;
return TMLIBDEV_OK;
}
}
/* No adapter instance found. If it's unqual to zero */
/* -> try with instance zero... */
if (param->adapterInstance != 0)
{
param->adapterInstance = 0;
return mapAdapterInput (pVD, param, mode);
}
/* Right adapter was not found -> return error */
return BOARD_ERR_UNSUPPORTED_ADAPTER;
}
/*****************************************************************************/
tmLibdevErr_t
saa7112InitM (pboardVIDec_t pVD, pboardVIParam_t param)
{
UInt i, rval = 0;
UInt inputMode;
viSetSELFCLOCKM(param->mmioBase, 0);
gAdapterType = param->adapterType;
/* Return, if NIM board is not connected */
if (gAdapterType == vaaNone)
{
return TMLIBDEV_OK;
}
/* Copy video standard to internal variable */
pVD->curVideoStandard = param->videoStandard;
/* Software reset to saa7112 */
rval |= iicWriteReg(pVD->slaveAddr, 0x80, 0x10);
for (i = 0; i < SAA7112_NREGS; i++) {
rval |= iicWriteReg(pVD->slaveAddr, i, saa7112_regs[i]);
}
if (gAdapterType == vaaSvideo) {
rval |= iicWriteReg(pVD->slaveAddr, 0x2, 0xF7);
rval |= iicWriteReg(pVD->slaveAddr, 0x9, 0x80);
}
for (i = 0; i < VIDEO_CONFIG_NREGS; i++) {
rval |= iicWriteReg(pVD->slaveAddr, (i + 0x83), video_config_regs[i]);
}
/* TextSlicer I/O configuration */
rval |= iicWriteReg(pVD->slaveAddr, 0x40, 0x02);
rval |= iicWriteReg(pVD->slaveAddr, 0x59, 0x54);
rval |= iicWriteReg(pVD->slaveAddr, 0x5A, 0x07);
rval |= iicWriteReg(pVD->slaveAddr, 0x5B, 0x03);
rval |= iicWriteReg(pVD->slaveAddr, 0x81, 0x00);
rval |= iicWriteReg(pVD->slaveAddr, 0x82, 0x00);
/* Scalar configuration */
rval |= iicWriteReg(pVD->slaveAddr, 0x94, 0x10);
rval |= iicWriteReg(pVD->slaveAddr, 0x95, 0x00);
rval |= iicWriteReg(pVD->slaveAddr, 0x96, 0xD0);
rval |= iicWriteReg(pVD->slaveAddr, 0x97, 0x02);
rval |= iicWriteReg(pVD->slaveAddr, 0x98, 0x0A);
rval |= iicWriteReg(pVD->slaveAddr, 0x99, 0x00);
rval |= iicWriteReg(pVD->slaveAddr, 0x9A, 0xF2);
rval |= iicWriteReg(pVD->slaveAddr, 0x9B, 0x00);
rval |= iicWriteReg(pVD->slaveAddr, 0x9C, 0xD0);
rval |= iicWriteReg(pVD->slaveAddr, 0x9D, 0x02);
rval |= iicWriteReg(pVD->slaveAddr, 0x9E, 0xF0);
rval |= iicWriteReg(pVD->slaveAddr, 0x9F, 0x00);
/* Start saa7112 task */
rval |= iicWriteReg(pVD->slaveAddr, 0x80, 0x90);
/* Map the adapter's instance to a valid mode */
if (mapAdapterInput (pVD, param, &inputMode) != TMLIBDEV_OK)
return BOARD_ERR_INVALID_ADAPTER_INSTANCE;
/* Set input of video accordingly */
saa7112SetAnalogInput (pVD, inputMode);
return (tmLibdevErr_t) rval;
}
tmLibdevErr_t
saa7112Init (pboardVIParam_t param)
{
return saa7112InitM(&defaultVD[0], param);
}
/******************************************************************************/
#define A_STATUS_CTL 0x1F
#define A_HLCK_MASK 0x40
#define A_FIDT_MASK 0x20
#define A_CSTD_DETECTED_MASK 0x01
#define A_CHROMA_CTL 0x0E
tmLibdevErr_t
saa7112GetStandardM(pboardVIDec_t pVD, tmVideoAnalogStandard_t * std)
{
unsigned int stat, chroma;
int notDetected = True;
int err = 0;
int i, j;
unsigned char colorStandard[5] = {0x01, 0x11, 0x21, 0x31, 0x51};
if(gAdapterType == vaaNone)
{
*std = vasNone;
return TMLIBDEV_OK;
}
microsleep(400000); /* This stupid routine need to sleep a lot. */
for (j = 0; ( (j<2) && notDetected ); j++) {
for ( *std = vasNone, i = 0; ( (i<5) && notDetected ); i++) {
err |= iicWriteReg(pVD->slaveAddr, A_CHROMA_CTL, colorStandard[i]);
microsleep(100000);
err |= iicReadReg(pVD->slaveAddr, A_CHROMA_CTL, &chroma);
err |= iicReadReg(pVD->slaveAddr, A_STATUS_CTL, &stat);
if (err) {
/* iic read write err */
return ( (tmLibdevErr_t) err);
}
if (stat & A_HLCK_MASK) {
microsleep(5000000); /* not in sync err, give it a long nap */
}
if (stat & A_CSTD_DETECTED_MASK) { /* color standard detected */
if (stat & A_FIDT_MASK) { /* 60 Hz */
switch (i) {
case 0: /* NTSC M */
*std = vasNTSC;
break;
case 1: /* PAL 4.43 */
*std = vasPAL;
break;
case 2: /* NTSC 4.43 */
*std = vasNTSC;
break;
case 3: /* NTSC N */
*std = vasNTSC;
break;
case 4: /* PAL 4.43 */
*std = vasPAL;
break;
default:
*std = vasNone; /* should not come here */
break;
} /* end of switch */
} else { /* 50Hz */
switch (i) {
case 0: /* PAL BGHI */
*std = vasPAL;
break;
case 1: /* NTSC 4.43 */
*std = vasNTSC;
break;
case 2: /* PAL N */
*std = vasPAL;
break;
case 3: /* PAL M */
*std = vasPAL;
break;
case 4: /* SECAM */
*std = vasSECAM;
break;
default:
*std = vasNone; /* should not come here */
break;
} /* end of switch */
}
notDetected = False;
}
} /* end of i for loop */
} /* end of j for loop */
if (stat & A_HLCK_MASK) {
/* not in sync err, message may be obscure */
return BOARD_ERR_VAL_OUT_OF_RANGE;
}
if (notDetected) {
return BOARD_ERR_COLOR_STANDARD_NOT_DETECTED;
}
/* Store detected standard in internal variable */
pVD->curVideoStandard = *std;
return TMLIBDEV_OK;
}
tmLibdevErr_t
saa7112GetStandard(tmVideoAnalogStandard_t * std)
{
return saa7112GetStandardM (&defaultVD[0], std);
}
tmLibdevErr_t
saa7112GetAdapterVideoStandard(pboardVIDec_t pVD, tmVideoAnalogAdapter_t adapter, UInt adapterNum, tmVideoAnalogStandard_t *std)
{
UInt inputMode;
/* Build up fake param structure to use available map function */
boardVIParam_t param;
param.adapterInstance = adapterNum;
param.adapterType = adapter;
/* Map the adapter's instance to a valid mode */
if (mapAdapterInput (pVD, ¶m, &inputMode) != TMLIBDEV_OK)
return BOARD_ERR_INVALID_ADAPTER_INSTANCE;
/* Set input of video accordingly */
saa7112SetAnalogInput (pVD, inputMode);
return saa7112GetStandardM (pVD, std);
}
/**********************************************************************/
tmLibdevErr_t
saa7112ConfigureM(pboardVIDec_t pVD, UInt32 subaddr, UInt32 value)
{
int rval = 0;
if (gAdapterType == vaaNone)
{
return TMLIBDEV_OK;
}
rval |= iicWriteReg(pVD->slaveAddr, subaddr, value);
DP(("SAA7112 is configured \n"));
return (tmLibdevErr_t) rval;
}
tmLibdevErr_t
saa7112Configure(UInt32 subaddr, UInt32 value)
{
return saa7112ConfigureM(&defaultVD[0], subaddr, value);
}
/******************************************************************************/
#define SAA711_LUMINANCE_REG 0x0a /* 8 bits */
#define SAA711_CONTRAST_REG 0x0b /* 7 bits */
#define SAA711_SATURATION_REG 0x0c /* 8 bits */
#define SAA711_HUE_REG 0x0d /* 8 bits */
extern tmLibdevErr_t
saa7112GetBrightnessM(pboardVIDec_t pVD, UInt * val)
{
if(gAdapterType == vaaNone)
{
return TMLIBDEV_OK;
}
return iicReadReg(pVD->slaveAddr, SAA711_LUMINANCE_REG, val);
}
extern tmLibdevErr_t
saa7112GetBrightness(UInt * val)
{
return saa7112GetBrightnessM(&defaultVD[0], val);
}
/******************************************************************************/
extern tmLibdevErr_t
saa7112SetBrightnessM(pboardVIDec_t pVD, UInt val)
{
if(gAdapterType == vaaNone)
{
return TMLIBDEV_OK;
}
if (val > 255)
return BOARD_ERR_VAL_OUT_OF_RANGE;
return iicWriteReg(pVD->slaveAddr, SAA711_LUMINANCE_REG, val);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -