📄 dvi_hdmi.c.070605.int
字号:
if (*ppDH) {
RMDBGLOG((ENABLE, "Warning: Call to DHInitWithAutoDetect() with initialized struct DH_control!\n"));
}
err = DHCreate(pRUA, ppDH);
if (RMFAILED(err)) return err;
RMDBGLOG((LOCALDBG, "Using I2C module %lu to access TX on GPIO %d/%d\n", i2c_module, pio_clock_transmitter, pio_data_transmitter));
(*ppDH)->i2c_module = i2c_module;
(*ppDH)->i2c_tx.I2C = EMHWLIB_MODULE(I2C, i2c_module);
(*ppDH)->i2c_tx.dev.PioClock = pio_clock_transmitter;
(*ppDH)->i2c_tx.dev.PioData = pio_data_transmitter;
#ifdef GPIO_RESET
gpio_reset = GPIO_RESET; // For Odyssey Based Designs and siI170, Force to unreset the Transmitter
#endif
if (i2c_module == 2) { // tango2 internal SiI9030
#ifdef RMFEATURE_HAS_HDMI
err = DHUnresetHDMICore(pRUA, Reset);
if (RMFAILED(err)) return err;
(*ppDH)->gpio_reset = 255;
#else
if (! manutest) fprintf(stderr, "[HDMI] ERROR: No internal SiI9030 core on this Sigma chip!\n");
return RM_ERROR;
#endif
} else if (gpio_reset != 0) { // 0 is reserved for "No GPIO for RESET"
(*ppDH)->gpio_reset = gpio_reset;
DHReset_siI164(*ppDH);
}
// We try all known parts
part_num = 0;
found_part = 0;
while (part_num < (sizeof(part_info)/sizeof(part_info[0]))) {
(*ppDH)->i2c_tx.dev.WrAddr = (part_info[part_num].i2c_transmitter_write_address) & 0xFF ;
(*ppDH)->i2c_tx.dev.RdAddr = (part_info[part_num].i2c_transmitter_write_address + 0x01) & 0xFF;
(*ppDH)->i2c_tx.dev.DelayUs = part_info[part_num].i2c_transmitter_delay_us;
// Check for device vendor ID
found_part = 1; // Assume OK and validate each byte
for (index = 0; index < sizeof(vendor_id); index++) {
if (RMFAILED(err = DH_i2c_read((*ppDH)->pRUA, &((*ppDH)->i2c_tx),
part_info[part_num].vendor_id_sud_address + index, &(vendor_id[index])))) {
RMDBGLOG((LOCALDBG, "Failed reading DVI or HDMI vendor ID\n"));
pi2c_prev_dev = NULL; // Will need to set new i2c address next read
found_part = 0; // Did not find in this loop
break; // Break from for loop
}
if( index == 3 && vendor_id[3] == 0x16 )
{
vendor_id[3] = 0x06 ;
}
found_part &= (part_info[part_num].vendor_id[index] == vendor_id[index]);
}
if (found_part) {
break;
}
part_num += 1;
}
if (found_part) {
if (! manutest) fprintf(stderr, "[HDMI] Found the part: %s (%d) , ID = 0x%02X%02X%02X%02X\n",
part_info[part_num].part_string, part_num,
vendor_id[0], vendor_id[1], vendor_id[2], vendor_id[3]);
(*ppDH)->part = (enum DH_vendor_parts) part_num;
// Note: siI9030 does not use rx (DDC is implemented using a FIFO in the siI9030
if ((TRANSMITTER_GPIO_CLOCK == 0) && (TRANSMITTER_GPIO_DATA == 1)) {
if (! manutest) fprintf(stderr, "[HDMI] Using I2C module %lu to access DDC on GPIO %d/%d\n", i2c_module, TRANSMITTER_GPIO_CLOCK, TRANSMITTER_GPIO_DATA);
(*ppDH)->i2c_rx.I2C = EMHWLIB_MODULE(I2C, i2c_module);
} else {
// Pins not supported by hw i2c, fall back to sw i2c
if (! manutest) fprintf(stderr, "[HDMI] Using software I2C to access DDC on GPIO %d/%d\n", TRANSMITTER_GPIO_CLOCK, TRANSMITTER_GPIO_DATA);
(*ppDH)->i2c_rx.I2C = EMHWLIB_MODULE(I2C, 0);
}
(*ppDH)->i2c_rx.dev.PioClock = TRANSMITTER_GPIO_CLOCK;
(*ppDH)->i2c_rx.dev.PioData = TRANSMITTER_GPIO_DATA;
(*ppDH)->i2c_rx.dev.WrAddr = part_info[part_num].i2c_receiver_write_address;
(*ppDH)->i2c_rx.dev.RdAddr = part_info[part_num].i2c_receiver_write_address + 0x01;
(*ppDH)->i2c_rx.dev.DelayUs = part_info[part_num].i2c_receiver_delay_us;
// 2007/06/04 added by jj_tseng@chipadvanced.com
fprintf(stderr,"part_num = %d\n",part_num) ;
fprintf(stderr,"(*ppDH)->i2c_tx.dev.WrAddr = 0x%02x\n",(*ppDH)->i2c_tx.dev.WrAddr) ;
fprintf(stderr,"(*ppDH)->i2c_tx.dev.RdAddr = 0x%02x\n",(*ppDH)->i2c_tx.dev.RdAddr) ;
fprintf(stderr,"(*ppDH)->i2c_rx.dev.WrAddr = 0x%02x\n",(*ppDH)->i2c_rx.dev.WrAddr) ;
fprintf(stderr,"(*ppDH)->i2c_rx.dev.RdAddr = 0x%02x\n",(*ppDH)->i2c_rx.dev.RdAddr) ;
//~jj_tseng@chipadvanced.com 2007/06/04
// siI9030 uses a second address
if ((enum DH_vendor_parts) part_num == DH_siI9030) {
(*ppDH)->i2c_tx2 = (*ppDH)->i2c_tx; // Same i2c line
(*ppDH)->i2c_tx2.dev.WrAddr += 8;
(*ppDH)->i2c_tx2.dev.RdAddr += 8;
} else {
(*ppDH)->i2c_tx2.I2C = 0;
}
if ((enum DH_vendor_parts) part_num == DH_siI170) {
if (! (*ppDH)->gpio_reset) {
if (! manutest) fprintf(stderr, "[HDMI] WARNING: no Reset GPIO set for SiI170, set GPIO_RESET in samples/dvi_hdmi.c!\n");
}
}
DHInitChip(*ppDH);
DHGetConnection(*ppDH, &(*ppDH)->cable, NULL, NULL);
DHCheckHDMI(*ppDH, NULL);
err = RM_OK;
} else {
if (! manutest) fprintf(stderr, "[HDMI] Did not find any known DVI/HDMI parts!\n");
RMFree(*ppDH);
*ppDH = NULL;
err = RM_ERROR;
}
return err;
}
RMstatus DHInitWithAutoDetect(struct RUA *pRUA,
RMuint8 pio_clock_transmitter, RMuint8 pio_data_transmitter, RMuint32 i2c_module,
RMuint8 gpio_reset, struct DH_control **ppDH)
{
return DHInitWithAutoDetectReset(pRUA, pio_clock_transmitter, pio_data_transmitter, i2c_module, gpio_reset, ppDH, FALSE);
}
// The following function is kept for backward compatibility. We remove the "auto-detect" that
// is now done by DHInitWithAutoDetect (Better for test applications).
// pio_clock_receiver and pio_data_receiver are now ignored.
RMstatus DHInitReset(struct RUA *pRUA, RMuint8 pio_clock_transmitter, RMuint8 pio_data_transmitter,
RMuint8 pio_clock_receiver, RMuint8 pio_data_receiver, RMuint32 i2c_module,
enum DH_vendor_parts part, struct DH_control **ppDH, RMbool Reset)
{
RMstatus err = RM_OK;
RMuint8 vendor_id[4];
RMuint8 index;
RMbool found_part;
if (pRUA == NULL) {
if (! manutest) fprintf(stderr, "[HDMI] Call to DHInit with invalid RUA structure!\n");
return RM_FATALINVALIDPOINTER;
}
CHECK_PTR("DHInit", ppDH);
if (*ppDH) {
RMDBGLOG((ENABLE, "Warning: Call to DHInit() with initialized struct DH_control!\n"));
}
err = DHCreate(pRUA, ppDH);
if (RMFAILED(err)) return err;
RMDBGLOG((LOCALDBG, "Using I2C module %lu to access TX on GPIO %d/%d\n", i2c_module, pio_clock_transmitter, pio_data_transmitter));
(*ppDH)->part = part;
(*ppDH)->i2c_module = i2c_module;
(*ppDH)->i2c_tx.I2C = EMHWLIB_MODULE(I2C, i2c_module);
(*ppDH)->i2c_tx.dev.PioClock = pio_clock_transmitter;
(*ppDH)->i2c_tx.dev.PioData = pio_data_transmitter;
if (part == DH_siI9030) {
(*ppDH)->i2c_rx = (*ppDH)->i2c_tx;
} else {
if ((TRANSMITTER_GPIO_CLOCK == 0) && (TRANSMITTER_GPIO_DATA == 1)) {
(*ppDH)->i2c_rx.I2C = EMHWLIB_MODULE(I2C, i2c_module);
} else {
// Pins not supported by hw i2c, fall back to sw i2c
(*ppDH)->i2c_rx.I2C = EMHWLIB_MODULE(I2C, 0);
}
(*ppDH)->i2c_rx.dev.PioClock = TRANSMITTER_GPIO_CLOCK;
(*ppDH)->i2c_rx.dev.PioData = TRANSMITTER_GPIO_DATA;
}
switch(part) {
case DH_siI164:
RMDBGLOG((LOCALDBG, "Looking for part SiI164\n"));
if (0)
case DH_siI170:
RMDBGLOG((LOCALDBG, "Looking for part SiI170\n"));
if (0)
case DH_siI9030:
RMDBGLOG((LOCALDBG, "Looking for part SiI9030\n"));
(*ppDH)->i2c_tx.dev.WrAddr = part_info[(int) part].i2c_transmitter_write_address;
(*ppDH)->i2c_tx.dev.RdAddr = part_info[(int) part].i2c_transmitter_write_address + 0x01;
(*ppDH)->i2c_tx.dev.DelayUs = part_info[(int) part].i2c_transmitter_delay_us;
// siI9030 uses a second address tx2
if (part == DH_siI9030) {
(*ppDH)->i2c_tx2 = (*ppDH)->i2c_tx; // Same i2c line
(*ppDH)->i2c_tx2.dev.WrAddr += 8;
(*ppDH)->i2c_tx2.dev.RdAddr += 8;
}
// Note: siI9030 does not use rx (DDC is implemented using a FIFO in the siI9030
else {
(*ppDH)->i2c_tx2.I2C = 0;
(*ppDH)->i2c_rx.dev.WrAddr = part_info[(int) part].i2c_receiver_write_address;
(*ppDH)->i2c_rx.dev.RdAddr = part_info[(int) part].i2c_receiver_write_address + 0x01;
(*ppDH)->i2c_rx.dev.DelayUs = part_info[(int) part].i2c_receiver_delay_us;
}
break;
case DH_cat6611:
RMDBGLOG((LOCALDBG, "Looking for part cat6611\n"));
(*ppDH)->i2c_tx.dev.WrAddr = (part_info[(int) part].i2c_transmitter_write_address)&0xFF;
(*ppDH)->i2c_tx.dev.RdAddr = (part_info[(int) part].i2c_transmitter_write_address + 0x01)&0xFF;
(*ppDH)->i2c_tx.dev.DelayUs = part_info[(int) part].i2c_transmitter_delay_us;
// siI9030 uses a second address tx2
if (part == DH_siI9030) {
(*ppDH)->i2c_tx2 = (*ppDH)->i2c_tx; // Same i2c line
(*ppDH)->i2c_tx2.dev.WrAddr += 8;
(*ppDH)->i2c_tx2.dev.RdAddr += 8;
}
// Note: siI9030 does not use rx (DDC is implemented using a FIFO in the siI9030
else {
(*ppDH)->i2c_tx2.I2C = 0;
(*ppDH)->i2c_rx.dev.WrAddr = part_info[(int) part].i2c_receiver_write_address;
(*ppDH)->i2c_rx.dev.RdAddr = part_info[(int) part].i2c_receiver_write_address + 0x01;
(*ppDH)->i2c_rx.dev.DelayUs = part_info[(int) part].i2c_receiver_delay_us;
}
break;
default:
if (! manutest) fprintf(stderr, "[HDMI] Unknown DVI or HDMI part (%d)!!!\n", part);
err = RM_ERROR;
goto cleanup;
}
if (i2c_module == 2) { // tango2 internal SiI9030
#ifdef RMFEATURE_HAS_HDMI
err = DHUnresetHDMICore(pRUA, Reset);
if (RMFAILED(err)) return err;
(*ppDH)->gpio_reset = 255;
#else
if (! manutest) fprintf(stderr, "[HDMI] ERROR: No internal SiI9030 core on this Sigma chip!\n");
return RM_ERROR;
#endif
}
else if(part != DH_siI9030 && part != DH_cat6611) {
#ifdef GPIO_RESET
(*ppDH)->gpio_reset = GPIO_RESET; // Keep GPIO reset info
DHReset_siI164(*ppDH);
#else
if (part == DH_siI170) {
if (! manutest) fprintf(stderr, "[HDMI] WARNING: no Reset GPIO set for SiI170, set GPIO_RESET in samples/dvi_hdmi.c!\n");
}
#endif
}
// Check for device vendor ID
found_part = 1; // Assume OK and validate each byte
for (index = 0; index < sizeof(vendor_id); index++) {
if (RMFAILED(err = DH_i2c_read((*ppDH)->pRUA, &((*ppDH)->i2c_tx),
part_info[(int) part].vendor_id_sud_address + index, &(vendor_id[index])))) {
RMDBGLOG((LOCALDBG, "Failed reading DVI or HDMI vendor ID\n"));
goto cleanup;
}
if( index == 3 && vendor_id[3] == 0x16 )
{
vendor_id[3] = 0x06 ;
}
found_part &= (part_info[(int) part].vendor_id[index] == vendor_id[index]);
}
// Do some "auto identification to be more "user friendly"
if (found_part) {
if (! manutest) fprintf(stderr, "[HDMI] Found part, Vendor ID is 0x%02X%02X%02X%02X\n",
vendor_id[0], vendor_id[1], vendor_id[2], vendor_id[3]);
} else {
if (! manutest) fprintf(stderr, "[HDMI] Did not find the DVI part! Read Vendor ID part is 0x%02X%02X%02X%02X\n",
vendor_id[0], vendor_id[1], vendor_id[2], vendor_id[3]);
err = RM_ERROR;
goto cleanup;
}
DHInitChip(*ppDH);
DHGetConnection(*ppDH, &(*ppDH)->cable, NULL, NULL);
DHCheckHDMI(*ppDH, NULL);
return err;
cleanup:
RMFree(*ppDH);
*ppDH = NULL;
return err;
}
RMstatus DHInit(struct RUA *pRUA, RMuint8 pio_clock_transmitter, RMuint8 pio_data_transmitter,
RMuint8 pio_clock_receiver, RMuint8 pio_data_receiver, RMuint32 i2c_module,
enum DH_vendor_parts part, struct DH_control **ppDH)
{
return DHInitReset(pRUA, pio_clock_transmitter, pio_data_transmitter, pio_clock_receiver, pio_data_receiver, i2c_module, part, ppDH, FALSE);
}
RMstatus DHSetHDMIMode(struct DH_control *pDH, RMbool HDMI)
{
RMstatus err;
RMuint8 reg;
CHECK_pDH("DHSetHDMIMode");
if (! manutest) fprintf(stderr, "[HDMI] DHSetHDMIMode(%s)\n", HDMI ? "TRUE" : "FALSE");
pDH->HDMI_mode = HDMI ; // && (pDH->part == DH_siI9030||pDH->part == DH_cat6611);
#if 1 // def FORCE_HDMI
pDH->HDMI_mode = 1;
#endif
if (! pDH->HDMI_mode) {
pDH->info_frame_enable = 0;
RMDBGLOG((LOCALDBG, "info_frame_enable now 0x%04X\n", pDH->info_frame_enable));
}
switch (pDH->part) {
case DH_siI9030:
// set HDMI mode (DVI or HDMI)
err = DH_i2c_read(pDH->pRUA, &(pDH->i2c_tx2), 0x2F, ®); // HDMI mode
if (RMFAILED(err)) reg = 0x00;
RMinsShiftBool(®, pDH->HDMI_mode, 0);
err = DH_i2c_write(pDH->pRUA, &(pDH->i2c_tx2), 0x2F, reg); // HDMI mode
// enable / disable audio
err = DH_i2c_read(pDH->pRUA, &(pDH->i2c_tx2), 0x14, ®);
reg = (reg & 0xFE) | ((pDH->HDMI_mode && pDH->HDMI_audio) ? 0x01 : 0x00);
err = DH_i2c_write(pDH->pRUA, &(pDH->i2c_tx2), 0x14, reg);
// disable info frames, if DVI
if (! pDH->HDMI_mode) {
err = DH_i2c_write(pDH->pRUA, &(pDH->i2c_tx2), 0x3E, 0x00);
if (RMFAILED(err)) RMDBGLOG((ENABLE, "Failed to write info_frame_enable!\n"));
err = DH_i2c_write(pDH->pRUA, &(pDH->i2c_tx2), 0x3F, 0x00);
if (RMFAILED(err)) RMDBGLOG((ENABLE, "Failed to write info_frame_enable!\n"));
}
break;
// 07/01/02 added by jjtseng
case DH_cat6611:
err = DHEnableHDMIOutput_cat6611(pDH,pDH->HDMI_mode); // HDMI mode
// disable info frames, if DVI
if (! pDH->HDMI_mode) {
DH_i2c_write(pDH->pRUA, &(pDH->i2c_tx), 0xC6, 0);
DH_i2c_write(pDH->pRUA, &(pDH->i2c_tx), 0xC9, 0);
DH_i2c_write(pDH->pRUA, &(pDH->i2c_tx), 0xCA, 0);
DH_i2c_write(pDH->pRUA, &(pDH->i2c_tx), 0xCB, 0);
DH_i2c_write(pDH->pRUA, &(pDH->i2c_tx), 0xCC, 0);
DH_i2c_write(pDH->pRUA, &(pDH->i2c_tx), 0xCD, 0);
DH_i2c_write(pDH->pRUA, &(pDH->i2c_tx), 0xCE, 0);
DH_i2c_write(pDH->pRUA, &(pDH->i2c_tx), 0xCF, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -