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

📄 monitor_detection.c

📁 ati driver
💻 C
📖 第 1 页 / 共 2 页
字号:
	snooze( 4000 );		OUTREG( regs, RADEON_TV_DAC_CNTL, 		RADEON_TV_DAC_CNTL_NBLANK | RADEON_TV_DAC_CNTL_NHOLD |		RADEON_TV_DAC_CNTL_DETECT |		RADEON_TV_DAC_CNTL_STD_NTSC |		(8 << RADEON_TV_DAC_CNTL_BGADJ_SHIFT) |		(6 << RADEON_TV_DAC_CNTL_DACADJ_SHIFT ));			(void)INREG( regs, RADEON_TV_DAC_CNTL );		snooze( 6000 );		// now see which wires are connected	tmp = INREG( regs, RADEON_TV_DAC_CNTL );	if( (tmp & RADEON_TV_DAC_CNTL_GDACDET) != 0 ) {		displays |= dd_stv;		SHOW_INFO0( 2, "S-Video TV-Out is connected" );	}		if( (tmp & RADEON_TV_DAC_CNTL_BDACDET) != 0 ) {		displays |= dd_ctv;		SHOW_INFO0( 2, "Composite TV-Out is connected" );	}	// clean up the mess we did	OUTREG( regs, RADEON_TV_DAC_CNTL, old_tv_dac_cntl );	OUTREG( regs, RADEON_DAC_EXT_CNTL, old_dac_ext_cntl );	OUTREG( regs, RADEON_CRTC2_GEN_CNTL, old_crtc2_gen_cntl );	OUTREG( regs, RADEON_DAC_CNTL2, old_dac_cntl2 );		OUTREGP( regs, RADEON_GPIOPAD_A, old_radeon_gpiopad_a, ~1 );		return displays;}// save readout of TV detection comparatorsstatic bool readTVDetect( accelerator_info *ai ){	uint32 tmp;	int i;	bigtime_t start_time;	bool detect;	// make output constant		Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,		RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK );			// check detection result	Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, &tmp );	detect = (tmp & RADEON_TV_DAC_CNTL_CMPOUT) != 0;		//SHOW_FLOW( 2, "detect=%d", detect );	start_time = system_time();		do {		// wait for stable detect signal		for( i = 0; i < 5; ++i ) {			bool cur_detect;						Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,				RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK |				RADEON_TV_DAC_CNTL_NHOLD );			Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,				RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK );							Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, &tmp );			cur_detect = (tmp & RADEON_TV_DAC_CNTL_CMPOUT) != 0;						//SHOW_FLOW( 2, "cur_detect=%d", cur_detect );						if( cur_detect != detect )				break;							detect = cur_detect;		}				if( i == 5 ) {			//SHOW_FLOW( 2, "return %d", detect );			return detect;		}			// don't wait forever - give up after 1 second			} while( system_time() - start_time < 1000000 );		SHOW_FLOW0( 2, "timeout" );		return false;}// detect TV connected to external Theatre-Outstatic display_device_e Radeon_DetectTV_Theatre( accelerator_info *ai ){	uint32 		old_tv_dac_cntl, old_pre_dac_mux_cntl, old_modulator_cntl1, old_master_cntl;	uint32 		uv_adr, old_last_fifo_entry, old_mid_fifo_entry, last_fifo_addr;	display_device_e displays = dd_none;		if( ai->si->tv_chip != tc_external_rt1 )		return dd_none;			// save previous values (TV-Out may be running)		Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, &old_tv_dac_cntl );		// enable DAC and comparators	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, 		RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | 		RADEON_TV_DAC_CNTL_NHOLD | RADEON_TV_DAC_CNTL_NBLANK );		Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL, &old_pre_dac_mux_cntl );				Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_MODULATOR_CNTL1, &old_modulator_cntl1 );			Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL, &old_master_cntl );		// save output timing	Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_UV_ADR, &uv_adr );		last_fifo_addr = (uv_adr & RADEON_TV_UV_ADR_MAX_UV_ADR_MASK) * 2 + 1;		old_last_fifo_entry = Radeon_TheatreReadFIFO( ai, last_fifo_addr );	old_mid_fifo_entry = Radeon_TheatreReadFIFO( ai, 0x18f );		Radeon_TheatreWriteFIFO( ai, last_fifo_addr, 0x20208 );	Radeon_TheatreWriteFIFO( ai, 0x18f, 0x3ff2608 );		// stop TV-Out to savely program it	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL, 		RADEON_TV_MASTER_CNTL_TV_FIFO_ASYNC_RST | RADEON_TV_MASTER_CNTL_TV_ASYNC_RST );			// set constant base level	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MODULATOR_CNTL1,		(0x2c << RADEON_TV_MODULATOR_CNTL1_SET_UP_LEVEL_SHIFT) |		(0x2c << RADEON_TV_MODULATOR_CNTL1_BLANK_LEVEL_SHIFT) );			// enable output	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL,		RADEON_TV_MASTER_CNTL_TV_ASYNC_RST );	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL,		0 );	// set constant Composite output	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL,		RADEON_TV_PRE_DAC_MUX_CNTL_CMP_BLU_EN | 		RADEON_TV_PRE_DAC_MUX_CNTL_DAC_DITHER_EN | 		(9 << RADEON_TV_PRE_DAC_MUX_CNTL_BLU_MX_SHIFT) |		(0xa8 << RADEON_TV_PRE_DAC_MUX_CNTL_FORCE_DAC_DATA_SHIFT) );	// check for S-Video connection	if( readTVDetect( ai )) {		SHOW_FLOW0( 2, "Composite-Out of Rage Theatre is connected" );		displays |= dd_ctv;	}	// enable output changes		Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,		RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK |		RADEON_TV_DAC_CNTL_NHOLD );	// set constant Y-output of S-Video adapter	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL,		RADEON_TV_PRE_DAC_MUX_CNTL_Y_RED_EN | 		RADEON_TV_PRE_DAC_MUX_CNTL_DAC_DITHER_EN | 		(9 << RADEON_TV_PRE_DAC_MUX_CNTL_RED_MX_SHIFT) |		(0xa8 << RADEON_TV_PRE_DAC_MUX_CNTL_FORCE_DAC_DATA_SHIFT) );	// check for composite connection	if( readTVDetect( ai )) {		SHOW_FLOW0( 2, "S-Video-Out of Rage Theatre is connected" );		displays |= dd_stv;	}	// restore everything	Radeon_TheatreWriteFIFO( ai, last_fifo_addr, old_last_fifo_entry );	Radeon_TheatreWriteFIFO( ai, 0x18f, old_mid_fifo_entry );	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL, old_master_cntl );	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MODULATOR_CNTL1, old_modulator_cntl1 );	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL, old_pre_dac_mux_cntl );	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, old_tv_dac_cntl );		return displays;}// check whether there is a TV connected to TV-DAC// returns bit set, i.e. there can be S-Video or composite or bothstatic display_device_e Radeon_DetectTV( accelerator_info *ai, bool tv_crt_found ){	switch( ai->si->asic ) {	case rt_r100:	case rt_r200:		return Radeon_DetectTV_Theatre( ai );			case rt_ve:	case rt_m6:	case rt_rv200:	case rt_m7:	case rt_rv250:	case rt_m9:	case rt_rv280:	case rt_m9plus:	// IGP method is guessed	case rt_rs100:	case rt_rs200:		return Radeon_DetectTV_RV200( ai, tv_crt_found );			case rt_r300:	case rt_r300_4p:	case rt_rv350:	case rt_rv360:	case rt_m10:	case rt_r350:	case rt_r360:		return Radeon_DetectTV_R300( ai );	}				return dd_none;}// get native monitor timing, using Detailed Monitor Descriptionstatic void Radeon_FindFPTiming_DetailedMonitorDesc( 	const edid1_info *edid, fp_info *fp, uint32 *max_hsize, uint32 *max_vsize ){	int i;		for( i = 0; i < EDID1_NUM_DETAILED_MONITOR_DESC; ++i ) {		if( edid->detailed_monitor[i].monitor_desc_type == edid1_is_detailed_timing ) {			const edid1_detailed_timing *timing = &edid->detailed_monitor[i].data.detailed_timing;						SHOW_FLOW( 2, "Found detailed timing for mode %dx%d in DDC data", 				(int)timing->h_active, (int)timing->v_active );						if( timing->h_active > *max_hsize && timing->v_active > *max_vsize ) {				*max_hsize = timing->h_active;				*max_vsize = timing->v_active;				// copy it to timing specification							fp->panel_xres = timing->h_active;				fp->h_blank = timing->h_blank;				fp->h_over_plus = timing->h_sync_off;				fp->h_sync_width = timing->h_sync_width;								fp->panel_yres = timing->v_active;				fp->v_blank = timing->v_blank;				fp->v_over_plus = timing->v_sync_off;				fp->v_sync_width = timing->v_sync_width;				// BeOS uses kHz, but the timing is in 10 kHz				fp->dot_clock = timing->pixel_clock * 10;			}		}	}}// get native monitor timing, using Standard Timing table;// this table doesn't contain the actual timing, so we try to find a// appropriate VESA modes for the resolutions given in the tablestatic void Radeon_FindFPTiming_StandardTiming( 	const edid1_info *edid, fp_info *fp, uint32 *max_hsize, uint32 *max_vsize ){	int i;		for( i = 0; i < EDID1_NUM_STD_TIMING; ++i ) {		const edid1_std_timing *std_timing = &edid->std_timing[i];				int best_fit = -1;		int best_refresh_deviation = 10000;		int j;				if( std_timing->h_size <= 256 )			continue;				for( j = 0; j < (int)vesa_mode_list_count; ++j ) {			int refresh_rate, cur_refresh_deviation;						if( vesa_mode_list[j].h_display != std_timing->h_size ||				vesa_mode_list[j].v_display != std_timing->v_size )				continue;							// take pixel_clock times 1000 because is is in kHz			// further, take it times 1000 again, to get 1/1000 frames 			// as refresh rate			refresh_rate = (int64)vesa_mode_list[j].pixel_clock * 1000*1000 / 				(vesa_mode_list[j].h_total * vesa_mode_list[j].v_total);							// standard timing is in frames, so multiple by it to get 1/1000 frames			// result is scaled by 100 to get difference in percentage;			cur_refresh_deviation = 				(100 * (refresh_rate - std_timing->refresh * 1000)) / refresh_rate;							if( cur_refresh_deviation < 0 )				cur_refresh_deviation = -cur_refresh_deviation;							// less then 1 percent difference is (hopefully) OK, 			// if there are multiple, we take best one			// (if the screen is that picky, it should have defined an enhanced timing)			if( cur_refresh_deviation < 1 && 				cur_refresh_deviation < best_refresh_deviation ) 			{				best_fit = j;				best_refresh_deviation = cur_refresh_deviation;			}		}				if( best_fit < 0 ) {			SHOW_FLOW( 2, "Unsupported standard mode %dx%d@%dHz (not VESA)", 				std_timing->h_size, std_timing->v_size, std_timing->refresh );			continue;		}				if( std_timing->h_size > *max_hsize && std_timing->h_size > *max_vsize ) {			const display_timing *timing = &vesa_mode_list[best_fit];						SHOW_FLOW( 2, "Found DDC data for standard mode %dx%d", 				(int)timing->h_display, (int)timing->v_display );							*max_hsize = timing->h_display;			*max_vsize = timing->h_display;						// copy it to timing specification			fp->panel_xres = timing->h_display;			fp->h_blank = timing->h_total - timing->h_display;			fp->h_over_plus = timing->h_sync_start - timing->h_display;			fp->h_sync_width = timing->h_sync_end - timing->h_sync_start;						fp->panel_yres = timing->v_display;			fp->v_blank = timing->v_total - timing->v_display;			fp->v_over_plus = timing->v_sync_start - timing->v_display;			fp->v_sync_width = timing->v_sync_end - timing->v_sync_start;			fp->dot_clock = timing->pixel_clock;		}	}}	// read edid data of flat panel and setup its timing accordinglystatic status_t Radeon_StoreFPEDID( accelerator_info *ai, const edid1_info *edid ){	fp_info *fp = &ai->si->flatpanels[0];	uint32 max_hsize, max_vsize;	SHOW_FLOW0( 2, "EDID data read from DVI port via DDC2:" );	edid_dump( edid );	// find detailed timing with maximum resolution	max_hsize = max_vsize = 0;			Radeon_FindFPTiming_DetailedMonitorDesc( edid, fp, &max_hsize, &max_vsize );	if( max_hsize == 0 ) {		SHOW_FLOW0( 2, "Timing is not explicitely defined in DDC - checking standard modes" );				Radeon_FindFPTiming_StandardTiming( 			edid, fp, &max_hsize, &max_vsize );			if( max_hsize == 0 ) {			SHOW_FLOW0( 2, "Still found no valid native mode, disabling DVI" );			return B_ERROR;		}	}				SHOW_INFO( 2, "h_disp=%d, h_blank=%d, h_over_plus=%d, h_sync_width=%d", 		fp->panel_xres, fp->h_blank, fp->h_over_plus, fp->h_sync_width );	SHOW_INFO( 2, "v_disp=%d, v_blank=%d, v_over_plus=%d, v_sync_width=%d", 		fp->panel_yres, fp->v_blank, fp->v_over_plus, fp->v_sync_width );				SHOW_INFO( 2, "pixel_clock=%d kHz", fp->dot_clock );	return B_OK;}// detect connected displays devices// whished_num_heads - how many heads the requested display mode needsvoid Radeon_DetectDisplays( accelerator_info *ai ){	shared_info *si = ai->si;	display_device_e displays = 0;	display_device_e controlled_displays = ai->vc->controlled_displays;	edid1_info edid;		// lock hardware so noone bothers us	Radeon_WaitForIdle( ai, true );	// mobile chips are for use in laptops - there must be a laptop panel		if( si->is_mobility )		displays |= dd_lvds;	// use DDC to detect monitors - if we can read DDC, there must be a monitor		// all non-mobility versions have a DVI port	if( (displays & dd_lvds) == 0 && 		Radeon_ReadEDID( ai, RADEON_GPIO_DVI_DDC, &edid ))	{		SHOW_FLOW0( 2, "Found monitor on DVI DDC port" );		// there may be an analog monitor connected to DVI-I;		// we must check EDID to see whether it's really a digital monitor		if( edid.display.input_type == 1 ) {			SHOW_FLOW0( 2, "Must be a DVI monitor" );						// store info about DVI-connected flat-panel			if( Radeon_StoreFPEDID( ai, &edid ) == B_OK ) {				displays |= dd_dvi;			} else {				SHOW_ERROR0( 2, "Disabled DVI - invalid EDID" );			}		} else {			// must be the analog portion of DVI			// I'm not sure about Radeons with one CRTC - do they have DVI-I or DVI-D?			// anyway - if there are two CRTC, analog portion must be connected 			// to TV-DAC; if there is one CRTC, it must be the normal VGA-DAC			if( si->num_crtc > 1 ) {				SHOW_FLOW0( 2, "Must be an analog monitor on DVI port" );				displays |= dd_tv_crt;			} else {				SHOW_FLOW0( 2, "Seems to be a CRT on VGA port!?" );				displays |= dd_crt;			}		}	}		// all chips have a standard VGA port	if( Radeon_ReadEDID( ai, RADEON_GPIO_VGA_DDC, &edid ))		displays |= dd_crt;			// we may have overseen monitors if they don't support DDC or 	// have broken DDC data (like mine);	// time to do a physical wire test; this test is more reliable, but it	// leads to distortions on screen, which is not very nice to look at		// for DVI, there is no mercy if no DDC data is there - we wouldn't	// even know the native resolution of the panel!	// all versions have a standard VGA port		if( (displays & dd_crt) == 0 &&		(controlled_displays && dd_crt) != 0 &&		Radeon_DetectCRT( ai ))		displays |= dd_crt;			// check VGA signal routed to DVI port	// (the detection code checks whether there is hardware for that)	if( (displays & dd_tv_crt) == 0 &&		(controlled_displays && dd_tv_crt) != 0 &&		Radeon_DetectTVCRT( ai ))		displays |= dd_tv_crt;	// check TV-out connector	if( (controlled_displays && (dd_ctv | dd_stv)) != 0 )		displays |= Radeon_DetectTV( ai, (displays & dd_tv_crt) != 0 );	SHOW_INFO( 0, "Detected monitors: 0x%x", displays );		displays &= controlled_displays;			// if no monitor found, we define to have a CRT connected to CRT-DAC	if( displays == 0 )		displays = dd_crt;			ai->vc->connected_displays = displays;		RELEASE_BEN( si->cp.lock );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -