⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvi_hdmi.c.070605.int

📁 linux下面的hdmi驱动
💻 INT
📖 第 1 页 / 共 5 页
字号:
	
	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, &reg);  // HDMI mode
			if (RMFAILED(err)) reg = 0x00;
			RMinsShiftBool(&reg, 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 = (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 + -