📄 tmbslsaa7104.c
字号:
{
tmbslCorePrintf(1, 0, "%s, setting colorsystem to NTSC_J\n", __FILE__);
tmRetVal = saa7104WriteArray( avoUnit, SAA7104_REG_VIDEO,
(UInt8*)saa7104_ntsc_J, sizeof(saa7104_ntsc_J) );
}
}
else if(!(strcmp(pSetup->videoStandard, "pal")))
{
tmRetVal = saa7104WriteArray( avoUnit, SAA7104_REG_VIDEO,
(UInt8*)saa7104_pal, sizeof(saa7104_pal) );
}
else
{
tmRetVal = TMBSL_ERR_VENCANA_BAD_PARAMETER;
goto error;
}
} // endvof8bitYUV422
else if ( pSetup->videoSubtype == vof24bit444 )
{
saa7104SetReg(avoUnit, 0x97, 0x15); // h/v sync as input
saa7104SetReg(avoUnit, 0x2D, 0x08); // output control
switch ( pSetup->encodingType )
{
case tmbslVencAna_Vga: /* RGB & HV syncs */
saa7104SetReg(avoUnit, 0x3a, 0x29); // no embedded sync
saa7104SetReg(avoUnit, 0x54, 0x01); // vsm pin provide vertical sync
saa7104SetReg(avoUnit, 0xDC, 0x05); // HD sync engine disabled
saa7104SetReg(avoUnit, 0xFD, 0xC3); // mode 0
break;
case tmbslVencAna_Ext1: /* YPbPr & embedded syncs */
tmRetVal = saa7104ProgramSyncEngine(avoUnit, gSaa7104Inst[avoUnit].videoStandard);
if ( tmRetVal != TM_OK )
goto error;
saa7104SetReg(avoUnit, 0x3a, 0x20); // embedded sync
saa7104SetReg(avoUnit, 0xFD, 0xC1); // mode 0, RGB->YUV matrix active
saa7104SetReg(avoUnit, 0x70, 0x46);
saa7104SetReg(avoUnit, 0x71, 0x46);
saa7104SetReg(avoUnit, 0x72, 0x61);
//For Interlaced, it appears that CLI bit needs to be high. Datasheet is vague here.
if(strcmp(pSetup->videoStandard, "1920x1080x60i") == 0)
{
saa7104SetReg(avoUnit, 0x96, 0x32);
} else
{
saa7104SetReg(avoUnit, 0x96, 0x22);
}
saa7104SetReg(avoUnit, 0x97, 0x20);
saa7104SetReg(avoUnit, 0xdc, 0x0d);
// Enable blanking and setting register that become relevant accordingly.
// Solving the concrete PR only (bl18#261).
// The same fix might be required for other video sub types, video modes and/or encoding types also.
// Refer to the application note "Programming the SAA7104 for HD MODE".
{
Bool enableBlanking = False;
UInt32 xTotal, xActive, yOffsetOdd, yOffsetEven, xOffset, yActive;
//dumpTheseRegister(avoUnit);
if(strcmp(pSetup->videoStandard, "1920x1080x60i") == 0)
{
enableBlanking = True;
// To do: Retrieve these from the current video mode.
xTotal = 2200;
xActive = 1920;
xOffset = 192; //276;
yActive = 1080/2;
yOffsetOdd = 20;
yOffsetEven = 20;
}
else if(strcmp(pSetup->videoStandard, "1280x720x60p") == 0)
{
enableBlanking = True;
// To do: Retrieve these from the current video mode.
xTotal = 1650;
xActive = 1280;
xOffset = 337;
xOffset = 221; // Better
yActive = 720;
yOffsetOdd = 24;
yOffsetEven = 24;
}
else if(strcmp(pSetup->videoStandard, "720x480x60p") == 0)
{
enableBlanking = False;
// To do: Retrieve these from the current video mode.
xTotal = 858;
xActive = 720;
xOffset = 100;
yActive = 480;
yOffsetOdd = 33;
yOffsetEven = 33;
}
if (enableBlanking)
{
UInt8 byte;
// Set blanking enable (BLEN).
saa7104GetReg(avoUnit, 0xa1, &byte);
byte |= 0x80; // Blanking enable.
saa7104SetReg(avoUnit, 0xa1, byte);
// Set xTotal (HLEN).
byte = (xTotal-1) & 0xff;
saa7104SetReg(avoUnit, 0x98, byte);
saa7104GetReg(avoUnit, 0x99, &byte);
byte = byte & 0xf0;
byte = byte | (((xTotal-1) & 0x0f00) >> 8);
saa7104SetReg(avoUnit, 0x99, byte);
// Set xActive (XPIX)
byte = (xActive/2) & 0xff;
saa7104SetReg(avoUnit, 0x91, byte);
saa7104GetReg(avoUnit, 0x94, &byte);
byte = byte & 0xf3;
byte = byte | (((xActive/2) & 0x0300) >> 6);
saa7104SetReg(avoUnit, 0x94, byte);
// Set xOffset (XOFS)
byte = (xOffset) & 0xff;
saa7104SetReg(avoUnit, 0x90, byte);
saa7104GetReg(avoUnit, 0x94, &byte);
byte = byte & 0xfc;
byte = byte | (((xOffset) & 0x0300) >> 8);
saa7104SetReg(avoUnit, 0x94, byte);
// Set yActive (YPIX)
byte = (yActive) & 0xff;
saa7104SetReg(avoUnit, 0x95, byte);
saa7104GetReg(avoUnit, 0x96, &byte);
tmbslCorePrintf(1, 0, "%s ILC = 0x%x\n", __FILE__, byte);
byte = byte & 0xfc;
byte = byte | (((yActive) & 0x0300) >> 8);
saa7104SetReg(avoUnit, 0x96, byte);
// Set yOffsetOdd (YOFSO).
byte = (yOffsetOdd) & 0xff;
saa7104SetReg(avoUnit, 0x92, byte);
saa7104GetReg(avoUnit, 0x94, &byte);
byte = byte & 0xcf;
byte = byte | (((yOffsetOdd) & 0x0300) >> 4);
saa7104SetReg(avoUnit, 0x94, byte);
// Set yOffsetEven (YOFSE).
byte = (yOffsetEven) & 0xff;
saa7104SetReg(avoUnit, 0x93, byte);
saa7104GetReg(avoUnit, 0x94, &byte);
byte = byte & 0x3f;
byte = byte | (((yOffsetEven) & 0x0300) >> 2);
saa7104SetReg(avoUnit, 0x94, byte);
}
}
//dumpTheseRegister(avoUnit);
break;
case tmbslVencAna_Scart: /* YPbPr & HV syncs */
saa7104SetReg(avoUnit, 0x3a, 0x20); // no embedded sync
saa7104SetReg(avoUnit, 0x54, 0x01); // PD1 sampled on rising clock edge
saa7104SetReg(avoUnit, 0xDC, 0x05); // HD sync engine disabled
saa7104SetReg(avoUnit, 0xFD, 0xC1); // mode 0, RGB->YUV matrix active
break;
default:
tmRetVal = TMBSL_ERR_VENCANA_BAD_PARAMETER;
goto error;
}
} // end vof24bit444
else
{
tmRetVal = TMBSL_ERR_VENCANA_BAD_PARAMETER;
goto error;
}
}
gSaa7104Inst[avoUnit].powerState = tmPowerOn;
gSaa7104Inst[avoUnit].init = TM_TRUE;
return TM_OK;
error:
saa7104VoDeinit(avoUnit);
return tmRetVal;
}
/******************************************************************************/
/** Deinitialize function, called during the device library Close()
to release all resources allocated for this video output device.
@pre .
@retval TM_OK Operation done.
@retval TMBSL_ERR_VENCANA_BAD_UNIT_NUMBER .
@note None.
*/
static tmErrorCode_t saa7104VoDeinit(
tmUnitSelect_t avoUnit /**< @b IN AVO Unit number. */
)
{
tmErrorCode_t tmRetVal = TM_OK;
if (avoUnit >= SAA7104_MAX_UNITS)
{
tmRetVal = TMBSL_ERR_VENCANA_BAD_UNIT_NUMBER;
}
else
{
// Close IIC devlib instance if open
if (gSaa7104Inst[avoUnit].iicInstance != 0)
{
tmRetVal = tmdlIicClose (gSaa7104Inst[avoUnit].iicInstance);
gSaa7104Inst[avoUnit].iicInstance = 0;
}
}
gSaa7104Inst[avoUnit].init = TM_FALSE;
return tmRetVal;
}
/******************************************************************************/
/** Programs the sync engine.
*/
static tmErrorCode_t saa7104ProgramSyncEngine(
tmUnitSelect_t avoUnit, /**< @b IN AVO Unit number. */
char *videoStandard /**< @b IN requested video standard. */
)
{
psaa7104_HDSync_t pHdSyncs;
tmErrorCode_t err;
pHdSyncs = saa7104GetHdSyncTab( videoStandard );
DBG_ASSERT2( pHdSyncs != NULL, ("Unsupported: %s", videoStandard) );
if ( pHdSyncs == NULL )
{
err = TMBSL_ERR_VENCANA_BAD_PARAMETER;;
goto error;
}
// programm init. values for HD-Sync mode
err = saa7104WriteArray( avoUnit, SAA7104_REG_VIDEO,
(UInt8*)saa7104_hdSync, sizeof(saa7104_hdSync) );
if ( err != TM_OK )
goto error;
#if 0
{
Float pixelClk;
UInt32 clkValue;
tmVideoMode_t vmode;
// program the pixel clock
err = tmVideoMode_GetModeByName( videoStandard, &vmode );
DBG_ASSERT2( err == TM_OK, ("tmVideoMode_GetModeByName failed 0x%X", err) );
err = tmVideoMode_GetPixelClock( vmode, &pixelClk );
DBG_ASSERT2( err == TM_OK, ("tmVideoMode_GetPixelClock 0x%X", err) );
if ( err != TM_OK )
goto error;
clkValue = (pixelClk/27.0) * 0x20000;
err = saa7104SetReg( avoUnit, pcl_1, clkValue & 0xFF );
err = saa7104SetReg( avoUnit, pcl_2, (clkValue >> 8) & 0xFF );
err = saa7104SetReg( avoUnit, pcl_3, (clkValue >> 16) & 0xFF );
}
#endif
if ( pHdSyncs->pD0 != NULL )
{
err = saa7104SetRegM( avoUnit, hdline_0, pHdSyncs->pD0, pHdSyncs->d0Sz );
DBG_ASSERT2( err == TM_OK, ("saa7104SetRegM_D0 0x%X", err) );
}
if ( pHdSyncs->pD2 != NULL )
{
err = saa7104SetRegM( avoUnit, hdline_2, pHdSyncs->pD2, pHdSyncs->d2Sz );
DBG_ASSERT2( err == TM_OK, ("saa7104SetRegM_D2 0x%X", err) );
}
if ( pHdSyncs->pD1 != NULL )
{
err = saa7104SetRegM( avoUnit, hdline_1, pHdSyncs->pD1, pHdSyncs->d1Sz );
DBG_ASSERT2( err == TM_OK, ("saa7104SetRegM_D1 0x%X", err) );
}
if ( pHdSyncs->pD3 != NULL )
{
err = saa7104SetRegM( avoUnit, hdline_3, pHdSyncs->pD3, pHdSyncs->d3Sz );
DBG_ASSERT2( err == TM_OK, ("saa7104SetRegM_D3 0x%X", err) );
}
if ( pHdSyncs->pD4 != NULL )
{
err = saa7104SetRegM( avoUnit, hdline_4, pHdSyncs->pD4, 4 );
DBG_ASSERT2( err == TM_OK, ("saa7104SetRegM_D4 0x%X", err) );
}
if ( pHdSyncs->pD8 != NULL )
{
err = saa7104SetRegM( avoUnit, hdline_8, pHdSyncs->pD8, 4 );
DBG_ASSERT2( err == TM_OK, ("saa7104SetRegM_D8 0x%X", err) );
}
err = saa7104SetReg( avoUnit, hdctrl, 0x0d );
DBG_ASSERT2( err == TM_OK, ("saa7104SetReg 0x%X", err) );
return TM_OK;
error:
return err;
}
/******************************************************************************/
/** Initialize the Cursor bitmap
*/
static void saa7104InitCursorBitmap(
tmUnitSelect_t avoUnit
)
{
UInt32 i;
tmErrorCode_t err;
gSaa7104bData[0] = 0x00; //RAM start address.
for ( i=1; i<= CUR_BITMAP_ARRAY_SIZE; i++ )
{
gSaa7104bData[i] = PIX1_TRANS | PIX2_TRANS | PIX3_TRANS | PIX4_TRANS;
}
// Advance I2C request
gSaa7104IicReq.direction = tmdlIicWrite;
gSaa7104IicReq.address = gSaa7104Inst[avoUnit].slaveAddr;
gSaa7104IicReq.subAddress = cursa;
gSaa7104IicReq.data = &gSaa7104bData[0];
gSaa7104IicReq.byteCount = CUR_BITMAP_ARRAY_SIZE + 1;
// and dispatch the request
err = tmdlIicDispatch( gSaa7104Inst[avoUnit].iicInstance, &gSaa7104IicReq );
DBG_ASSERT2( err == TM_OK, ("saa7104InitCursorBitmap IIC error: 0x%X", err) );
return;
}
/******************************************************************************/
/** Get a register value.
*/
static tmErrorCode_t saa7104GetReg(
tmUnitSelect_t avoUnit, /**< @b IN AVO Unit number. */
UInt8 bReg, /**< @b IN Subaddress of the register. */
UInt8 *pbData /**< @b IN Pointer to variable to recieve value.*/
)
{
tmErrorCode_t tmRetVal;
// Advance I2C request
gSaa7104IicReq.direction = tmdlIicRead;
gSaa7104IicReq.address = gSaa7104Inst[avoUnit].slaveAddr;
gSaa7104IicReq.subAddress = bReg;
gSaa7104IicReq.data = pbData;
gSaa7104IicReq.byteCount = 1;
// and dispatch the request
tmRetVal = tmdlIicDispatch(gSaa7104Inst[avoUnit].iicInstance, &gSaa7104IicReq);
return tmRetVal;
}
/******************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -