📄 ddc.cpp
字号:
/*
* $Workfile: ddc.cpp $
* $Revision: 3 $
* $Date: 4/07/00 8:48a $
* $Modtime: 4/07/00 8:38a $
* $Author: Sarma $
*
* Contains routines for GXVideo initialization and also to set modes.
*
* Copyright (c) 1998 National Semiconductor Corporation.
* All Rights Reserved.
*
* This software is the confidential and proprietary information of National
* Semiconductor Corporation. ("Confidential Information").
* You shall not disclose such Confidential Information and shall use it only
* in accordance with the terms of the license agreement you entered into
* with National Semiconductor Corporation.
* This code is supplied as is.
*
*/
/*
*$Log: /CE/Platform/Nsc/Drivers/Video/gxvideo/base/ddc.cpp $
*
* 3 4/07/00 8:48a Sarma
* Removed Cyrix Corporation from the legal/confidentail information.
*
* 2 7/20/99 2:09p Sarma
* Added Vss history tags.
*/
#include "precomp.h"
#include "ddc.h"
//Data locations in VESA ver1.0 format containg 128 Bytes
#define VESA1_VERSION 12
#define VESA1_REVSION 13
#define VESA1_EST_TIM1 35
#define VESA1_EST_TIM2 36
#define VESA1_EST_MANU_TIM 37
#define VESA1_EST_STAND_TIM 38
typedef struct _DispAspectRatio{
int xRatio;
int yRatio;
}DispAspectRatio;
static DispAspectRatio asp[4] = {
{1, 1},
{4, 3},
{5, 4},
{16, 9}
};
static void standardTiming(unsigned char *data)
{
int width, height;
int freq, ratio, pos;
for (int i = 0; i < 8; i++) {
//value = (HorizTiming /8) - 31
pos = VESA1_EST_STAND_TIM + (i <<1); //Each timing uses 2 Bytes as info.
if((data[pos] == 0x1 ) && (data[pos + 1] == 0x1))
continue;
width = (data[pos] + 31) << 3;
freq = 60+(data[pos + 1] & 0x3F);
ratio = (data[pos + 1] & 0xC0) >> 6;
height = (width / asp[ratio].xRatio) * asp[ratio].yRatio;
DEBUGMSG( 1,(TEXT("%d = %3dX%3d %dHz\n"),i, width, height, freq));
//RETAILMSG( 1,(_T("%d = %3dX%3d %dHz\n"),i, width, height, freq));
}
}
static void dumpData(unsigned char *data, int length)
{
for (int i = 0; i < length; i++) {
DEBUGMSG( 1,(TEXT("%d = %2X %3d\n"),i, data[i],data[i]));
//RETAILMSG( 1,(_T("%d = %2X %3d\n"),i, data[i],data[i]));
}
}
DDC1_2B::DDC1_2B(unsigned char *regBase) {
cxReg = regBase;
displayDataLength = 128;
displaySupports = 0;
displayData = new byte[displayDataLength];
memset(displayData, 0x0, displayDataLength);
startXfer();
init();
getBlock(displayData, displayDataLength);
endXfer();
dumpData(displayData, displayDataLength);
standardTiming(displayData);
}
DDC1_2B::~DDC1_2B()
{
DEBUGMSG( 0,(TEXT("DDC1_2B::~DDC1_2B\n")));
if(displayData)
delete [] displayData;
displayData = 0x0;
}
// Data accessors for extracting information from the data block
bool DDC1_2B::doesDisplaySupport(unsigned long mode)
{
//Check if we were really able to read display
if((displayData[VESA1_VERSION] == 0xFF) ||
(displayData[VESA1_REVSION] == 0xFF))
return false;
displaySupports = (displayData[VESA1_EST_TIM1] << 16) |
(displayData[VESA1_EST_TIM2] << 8) |
displayData[VESA1_EST_MANU_TIM];
DEBUGMSG( 1,(TEXT("doesDisplaySupport %X\n"),displaySupports));
return ((displaySupports & mode) == mode);
}
//Wait for microSeconds
void DDC1_2B::wait(int uSec)
{
DEBUGMSG( 0,(TEXT("delay %d\n"),uSec));
unsigned long target = GetTickCount() + uSec;
while (GetTickCount() <= target);
}
unsigned char DDC1_2B::ReadByte(bool ack)
{
unsigned char val = 0;
DEBUGMSG( 0,(TEXT("getByte\n")));
for (int i = 0; i < 8; i++) {
val <<= 1;
val |= ReadBit();
}
Ack(ack);
return val;
}
int DDC1_2B::ReadBit()
{
DEBUGMSG( 0,(TEXT("getBit\n")));
wait();
ClearSCL();
wait();
WaitSCLHigh();
wait();
return GetSDA();
}
void DDC1_2B::WaitSCLHigh()
{
DEBUGMSG( 0,(TEXT("WaitSCLHigh\n")));
SetSCL();
// slow down trasfer
unsigned long target = GetTickCount() + 2;
for (;;) {
if (GetSCL() == 1) {
break;
} else if (GetTickCount() > target) {
DEBUGMSG( 1,(TEXT("timeout")));
}
DEBUGMSG( 1,(TEXT("WaitSCLHigh - Delay 2 u Sec\n")));
}
}
void DDC1_2B::SendByte(unsigned char data)
{
DEBUGMSG( 0,(TEXT("sendByte Enter\n")));
for (int i = 7; i >= 0; i--) {
SendBit((data >> i) & 1);
}
if (! waitForAck()) {
DEBUGMSG( 1,(TEXT("NACK received\n")));
}
ClearSCL();
DEBUGMSG( 0,(TEXT("sendByte Exit\n")));
}
void DDC1_2B::SendBit(bool flag)
{
DEBUGMSG( 0,(TEXT("sendBit\n")));
wait();
ClearSCL();
wait();
if (flag) {
SetSDA();
} else {
ClearSDA();
}
wait();
WaitSCLHigh();
}
void DDC1_2B::StartBit()
{
DEBUGMSG( 0,(TEXT("startBit\n")));
wait();
SetSDA();
wait();
WaitSCLHigh();
wait();
ClearSDA();
wait();
}
void DDC1_2B::StopBit()
{
DEBUGMSG( 0,(TEXT("stopBit\n")));
wait();
WaitSCLHigh();
wait();
SetSDA();
wait(2);
}
void DDC1_2B::Ack(bool flag)
{
DEBUGMSG( 0,(TEXT("ACK\n")));
wait();
ClearSCL();
wait();
if (flag) {
ClearSDA();
} else {
SetSDA();
}
WaitSCLHigh();
ClearSCL();
wait();
SetSDA();
DEBUGMSG( 0,(TEXT("ACK Exit\n")));
}
bool DDC1_2B::waitForAck()
{
DEBUGMSG( 0,(TEXT("waitForACK\n")));
wait();
ClearSCL();
wait();
SetSDA();
unsigned long target = GetTickCount() + 2;
for (;;) {
wait();
if (GetSDA() == 0) {
wait();
WaitSCLHigh();
return true;
//} else if(endtime > target) {
} else if(GetTickCount() > target) {
wait();
WaitSCLHigh();
return false;
}
}
}
void DDC1_2B::requestData()
{
DEBUGMSG( 0,(TEXT("requestData\n")));
StartBit();
SendByte(0xa0);
SendByte(0);
StopBit();
StartBit();
SendByte(0xa1);
}
void DDC1_2B::init()
{
DEBUGMSG( 0,(TEXT("setup\n")));
SetSDA();
WaitSCLHigh();
ClearSCL();
WaitSCLHigh();
ClearSCL();
WaitSCLHigh();
requestData();
ReadByte(false);
StopBit();
}
void DDC1_2B::getBlock(unsigned char *block, int length)
{
DEBUGMSG( 0,(TEXT("getBlock\n")));
requestData();
int cksum = 0;
int end = length - 1;
for (int i = 0; i < length; i++) {
block[i] = ReadByte((i != end));
cksum += (int)block[i];
}
StopBit();
DEBUGMSG( 0,(TEXT("getBlock %d\n"),cksum));
if ((cksum & 0xff) != 0) {
DEBUGMSG( 1,(TEXT("Checksum Error\n")));
}
}
////////////////////////////////////////////////////////////////
// H/W DEPENDENT LOW LAYER ROUTINES
////////////////////////////////////////////////////////////////
// Toggle SDA from low to high while SCL is high.
void DDC1_2B::startXfer()
{
unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
DEBUGMSG( 0,(TEXT("startXfer\n")));
data &= ~CX5530_DCFG_DDC_SCL;
WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
data &= ~CX5530_DCFG_DDC_SDA;
WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
data |= CX5530_DCFG_DDC_SCL;
WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
data |= CX5530_DCFG_DDC_SDA;
WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
}
// Toggle SDA from high to low while SCL is high.
void DDC1_2B::endXfer()
{
unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
DEBUGMSG( 0,(TEXT("endXfer\n")));
data &= ~CX5530_DCFG_DDC_SCL;
WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
data |= CX5530_DCFG_DDC_SDA;
WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
data |= CX5530_DCFG_DDC_SCL;
WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
data &= ~CX5530_DCFG_DDC_SDA;
WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
}
//Set clock high
void DDC1_2B::SetSCL()
{
unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
DEBUGMSG( 0,(TEXT("SetSCL\n")));
data |= CX5530_DCFG_DDC_SCL;
WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
}
//Set clock low
void DDC1_2B::ClearSCL()
{
unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
data &= ~CX5530_DCFG_DDC_SCL;
DEBUGMSG( 0,(TEXT("DDCclockLo %X\n"),data));
WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
}
int DDC1_2B::GetSCL()
{
unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
DEBUGMSG( 0,(TEXT("GetSCL %X\n"), data));
return ((data & CX5530_DCFG_DDC_SCL) >> 22);
}
//Set data high
void DDC1_2B::SetSDA()
{
unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
data |= CX5530_DCFG_DDC_SDA | CX5530_DCFG_DDC_OE;
DEBUGMSG( 0,(TEXT("SetSDA %X\n"), data));
WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
}
//Set data low
void DDC1_2B::ClearSDA()
{
unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
data &= ~CX5530_DCFG_DDC_SDA;
data |= CX5530_DCFG_DDC_OE;
DEBUGMSG( 0,(TEXT("ClearSDA %X\n"), data));
WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
}
int DDC1_2B::GetSDA()
{
unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
data &= ~CX5530_DCFG_DDC_OE;
WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
wait(2); //10
data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
DEBUGMSG( 0,(TEXT("GetSDA %X\n"), data));
return (data >> 31);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -