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

📄 setdisplaymode.c

📁 ati driver
💻 C
字号:
/*	Copyright (c) 2002, Thomas Kurschel		Part of Radeon accelerant			Sets display modes, colour palette and handles DPMS*/#include "GlobalData.h"#include "generic.h"#include <sys/ioctl.h>#include "../regs/radeon_regs.h"#include "../shared/mmio.h"#include "../regs/crtc_regs.h"#include <GraphicsDefs.h>#include "../regs/crtc_regs.h"#include "../regs/overlay_regs.h"#include "../regs/rbbm_regs.h"#include "../regs/dac_regs.h"#include "set_mode.h"#include <string.h>// round virtual width up to next valid sizeuint32 Radeon_RoundVWidth( 	int virtual_width, int bpp ){	// we have to make both the CRTC and the accelerator happy:	// - the CRTC wants virtual width in pixels to be a multiple of 8	// - the accelerator expects width in bytes to be a multiple of 64	// to put that together, width (in bytes) must be a multiple of the least 	// common nominator of bytes-per-pixel*8 (CRTC) and 64 (accelerator);		// if bytes-per-pixel is a power of two and less than 8, the LCM is 64;	// almost all colour depth satisfy that apart from 24 bit; in this case,	// the LCM is 64*3=192		// after dividing by bytes-per-pixel we get pixels: in first case,	// width must be multiple of 64/bytes-per-pixel; in second case,	// width must be multiple of 64*3/3=64		if( bpp != 3 )		return (virtual_width + 64/bpp - 1) & ~(64/bpp - 1);	else		return (virtual_width + 63) & ~63;}// list of registers that must be reset before display mode switch// to avoid interferencesstatic struct {	uint16 reg;	uint32 val;} common_regs[] = {	{ RADEON_OVR_CLR, 0 },		{ RADEON_OVR_WID_LEFT_RIGHT, 0 },	{ RADEON_OVR_WID_TOP_BOTTOM, 0 },	{ RADEON_OV0_SCALE_CNTL, 0 },		// disable overlay	{ RADEON_SUBPIC_CNTL, 0 },	{ RADEON_I2C_CNTL_1, 0 },};static void Radeon_InitCommonRegs( 	accelerator_info *ai ){	vuint8 *regs = ai->regs;	uint i;		for( i = 0; i < sizeof( common_regs) / sizeof( common_regs[0] ); ++i )		OUTREG( regs, common_regs[i].reg, common_regs[i].val );			// enable extended display modes	OUTREGP( regs, RADEON_CRTC_GEN_CNTL, 		RADEON_CRTC_EXT_DISP_EN, ~RADEON_CRTC_EXT_DISP_EN );			// disable flat panel auto-centering 	// (if we have a CRT on CRTC1, this must be disabled;	//  if we have a flat panel on CRTC1, we setup CRTC manually, not	//  using the auto-centre, automatic-sync-override magic)	OUTREG( regs, RADEON_CRTC_MORE_CNTL, 0 );}// set display mode of one head;// port restrictions, like fixed-sync TFTs connected to it, are taken care ofvoid Radeon_SetMode( 	accelerator_info *ai, crtc_info *crtc, display_mode *mode, impactv_params *tv_params ){	virtual_card *vc = ai->vc;	shared_info *si = ai->si;	vuint8 *regs = ai->regs;	int    format;	int    bpp;	display_device_e disp_devices;	fp_info *fp_info;		crtc_regs		crtc_values;	pll_regs		pll_values;	fp_regs			fp_values;	impactv_regs	impactv_values;	uint32			surface_cntl;		bool internal_tv_encoder;	pll_dividers dividers;		crtc->mode = *mode;		// don't destroy passed values, use our copy instead	mode = &crtc->mode;		disp_devices = crtc->chosen_displays;	fp_info = &si->flatpanels[crtc->flatpanel_port];		// if using an flat panel or LCD, maximum resolution	// is determined by the physical resolution; 	// also, all timing is fixed	if( (disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 ) {		if( mode->timing.h_display > fp_info->panel_xres )			mode->timing.h_display = fp_info->panel_xres;		if(	mode->timing.v_display > fp_info->panel_yres )			mode->timing.v_display = fp_info->panel_yres;				mode->timing.h_total = mode->timing.h_display + fp_info->h_blank;		mode->timing.h_sync_start = mode->timing.h_display + fp_info->h_over_plus;		mode->timing.h_sync_end = mode->timing.h_sync_start + fp_info->h_sync_width;		mode->timing.v_total = mode->timing.v_display + fp_info->v_blank;		mode->timing.v_sync_start = mode->timing.v_display + fp_info->v_over_plus;		mode->timing.v_sync_end = mode->timing.v_sync_start + fp_info->v_sync_width;				mode->timing.pixel_clock = fp_info->dot_clock;	}		// TV-out supports at most 1024x768	if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) {		if( mode->timing.h_display > 1024 )			mode->timing.h_display = 1024;					if( mode->timing.v_display > 768 )			mode->timing.v_display = 768;	}	// if using TV-Out, the timing of the source signal must be tweaked to	// get proper timing	internal_tv_encoder = IS_INTERNAL_TV_OUT( si->tv_chip );		// we need higher accuracy then Be thought of	mode->timing.pixel_clock *= 1000;	// TV stuff must be done first as it tweaks the display mode	if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) {		display_mode tweaked_mode;				Radeon_CalcImpacTVParams( 			&si->pll, tv_params, vc->tv_standard, internal_tv_encoder, 			mode, &tweaked_mode );					*mode = tweaked_mode;	}		Radeon_GetFormat( mode->space, &format, &bpp );		vc->bpp = bpp;	vc->datatype = format;  		// time to read original register content	// lock hardware so noone bothers us	Radeon_WaitForIdle( ai, true );			if( (disp_devices & (dd_dvi | dd_lvds | dd_dvi_ext)) != 0 ) {		if( crtc->crtc_idx == 0 )			Radeon_ReadRMXRegisters( ai, &fp_values );					Radeon_ReadFPRegisters( ai, &fp_values );	}	if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) {		// some register's content isn't created from scratch but		// only modified, so we need the original content first		if( internal_tv_encoder )			Radeon_InternalTVOutReadRegisters( ai, &impactv_values );		else			Radeon_TheatreReadTVRegisters( ai, &impactv_values );	}	// calculate all hardware register values	Radeon_CalcCRTCRegisters( ai, crtc, mode, &crtc_values );	surface_cntl = RADEON_SURF_TRANSLATION_DIS;	if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) {		Radeon_CalcImpacTVRegisters( ai, mode, tv_params, &impactv_values, 			crtc->crtc_idx, internal_tv_encoder, vc->tv_standard, disp_devices );	}	if( (disp_devices & (dd_stv | dd_ctv)) == 0 )		Radeon_CalcCRTPLLDividers( &si->pll, mode, &dividers );	else		dividers = tv_params->crt_dividers;		Radeon_CalcPLLRegisters( mode, &dividers, &pll_values );		// for first CRTC1, we need to setup RMX properly	if( crtc->crtc_idx == 0 )		Radeon_CalcRMXRegisters( fp_info, mode, 			(disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0,			&fp_values );				if( (disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 )		Radeon_CalcFPRegisters( ai, crtc, fp_info, &crtc_values, &fp_values );		// we don't use pixel clock anymore, so it can be reset to Be's kHz	mode->timing.pixel_clock /= 1000;		// write values to registers		Radeon_InitCommonRegs( ai );		Radeon_ProgramCRTCRegisters( ai, crtc->crtc_idx, &crtc_values );		OUTREG( regs, RADEON_SURFACE_CNTL, surface_cntl );	if( crtc->crtc_idx == 0 )		Radeon_ProgramRMXRegisters( ai, &fp_values );	if( (disp_devices & (dd_lvds | dd_dvi | dd_dvi_ext)) != 0 )		Radeon_ProgramFPRegisters( ai, crtc, fp_info, &fp_values );			//if( mode->timing.pixel_clock )	Radeon_ProgramPLL( ai, crtc->crtc_idx, &pll_values );		if( (disp_devices & (dd_ctv | dd_stv)) != 0 ) {		if( internal_tv_encoder )			Radeon_InternalTVOutProgramRegisters( ai, &impactv_values );		else			Radeon_TheatreProgramTVRegisters( ai, &impactv_values );	}	crtc->active_displays = disp_devices;		// programming is over, so hardware can be used again	RELEASE_BEN( si->cp.lock );		// overlay must be setup again after modeswitch (whoever was using it)	// TBD: this won't work if another virtual card was using it,	// but currently, virtual cards don't work anyway...	si->active_overlay.crtc_idx = -1;}// enable or disable VBlank interruptsvoid Radeon_EnableIRQ( 	accelerator_info *ai, bool enable ){	shared_info *si = ai->si;	uint32 int_cntl, int_mask;		int_cntl = INREG( ai->regs, RADEON_GEN_INT_CNTL );	int_mask = 		RADEON_CRTC_VBLANK_MASK		| (si->num_crtc > 1 ? RADEON_CRTC2_VBLANK_MASK : 0);			if( enable )		int_cntl |= int_mask;	else		int_cntl &= ~int_mask;			OUTREG( ai->regs, RADEON_GEN_INT_CNTL, int_cntl );		if( enable ) {		// on enable, we have to acknowledge all IRQs as the graphics card		// waits for that before it issues further IRQs		OUTREG( ai->regs, RADEON_GEN_INT_STATUS, int_cntl );	}	si->enable_virtual_irq = enable;}// public function: set display modestatus_t SET_DISPLAY_MODE( 	display_mode *mode_in ) {	virtual_card *vc = ai->vc;	shared_info *si = ai->si;	display_mode bounds, mode;	mode = bounds = *mode_in;		ACQUIRE_BEN( si->engine.lock );		SHOW_FLOW( 2, "width=%d, height=%d", mode.timing.h_display, mode.timing.v_display );	// check mode and tweak parameters so we can program hardware	// without any further checks				if( PROPOSE_DISPLAY_MODE( &mode, &bounds, &bounds ) == B_ERROR ) {		SHOW_ERROR0( 2, "invalid mode" );				RELEASE_BEN( si->engine.lock );		return B_ERROR;	}	// already done by propose_display_mode, but it was undone on return;	// do this before equality check to recognize changes of multi-monitor mode 	Radeon_DetectMultiMode( vc, &mode );		// mode switches can take quite long and are visible, 	// so avoid them if possible	if( memcmp( &mode, &vc->mode, sizeof( display_mode )) == 0 &&		!vc->enforce_mode_change ) {		RELEASE_BEN( si->engine.lock );		return B_OK;	}		// this flag was set when some internal parameter has changed that	// affects effective display mode	vc->enforce_mode_change = false;		// make sure, we don't get disturbed	//Radeon_Finish( ai );	Radeon_EnableIRQ( ai, false );	// free cursor and framebuffer memory	{		radeon_free_mem fm;				fm.magic = RADEON_PRIVATE_DATA_MAGIC;		fm.memory_type = mt_local;		fm.global = true;			if( vc->cursor.mem_handle ) {			fm.handle = vc->cursor.mem_handle;			ioctl( ai->fd, RADEON_FREE_MEM, &fm );		}				if( vc->fb_mem_handle ) {			fm.handle = vc->fb_mem_handle;			ioctl( ai->fd, RADEON_FREE_MEM, &fm );		}	}		memcpy( &vc->mode, &mode, sizeof( display_mode ));		// verify hardware restrictions *after* saving mode	// e.g. if you want a span mode but have one monitor disconnected,	// configuration shouldn't be touched, so you can continue working	// with two monitors later on just like nothing has happened	Radeon_VerifyMultiMode( vc, si, &mode );	// set main flags		vc->independant_heads = vc->assigned_crtc[0] && si->crtc[0].chosen_displays != dd_none;		if( si->num_crtc > 1 )		vc->independant_heads += vc->assigned_crtc[1] && si->crtc[1].chosen_displays != dd_none;			vc->different_heads = Radeon_DifferentPorts( &mode );	SHOW_FLOW( 2, "independant heads: %d, different heads: %d", 		vc->independant_heads, vc->different_heads );	vc->scroll = mode.flags & B_SCROLL;	SHOW_FLOW( 2, "scrolling %s", vc->scroll ? "enabled" : "disabled" );	// allocate frame buffer and cursor image memory	{		radeon_alloc_mem am;		int format, bpp;				// alloc cursor memory				am.magic = RADEON_PRIVATE_DATA_MAGIC;		am.size = 1024;		am.memory_type = mt_local;		am.global = true;				if( ioctl( ai->fd, RADEON_ALLOC_MEM, &am ) == B_OK ) {			vc->cursor.mem_handle = am.handle;			vc->cursor.fb_offset = am.offset;		} else {			// too bad that we are out of mem -> set reasonable values as			// it's too late to give up (ouch!)			SHOW_ERROR0( 2, "no memory for cursor image!" );			vc->cursor.mem_handle = 0;			vc->cursor.fb_offset = 0;		}				vc->cursor.data = si->local_mem + vc->cursor.fb_offset;			// alloc frame buffer		Radeon_GetFormat( mode.space, &format, &bpp );		vc->pitch = Radeon_RoundVWidth( mode.virtual_width, bpp ) * bpp;		am.size = vc->pitch * mode.virtual_height;				if( ioctl( ai->fd, RADEON_ALLOC_MEM, &am ) == B_OK ) {			vc->fb_mem_handle = am.handle;			vc->fb_offset = am.offset;		} else 	{			// ouch again - set reasonable values			SHOW_ERROR0( 2, "no memory for frame buffer!" );			vc->fb_mem_handle = 0;			vc->fb_offset = 1024;		}				vc->fbc.frame_buffer = si->local_mem + vc->fb_offset;		vc->fbc.frame_buffer_dma = (void *)((uint8 *)si->framebuffer_pci + vc->fb_offset);		vc->fbc.bytes_per_row = vc->pitch;				SHOW_FLOW( 0, "frame buffer CPU-address=%x, phys-address=%x", 			vc->fbc.frame_buffer, vc->fbc.frame_buffer_dma );	}		// multi-screen stuff	Radeon_InitMultiModeVars( ai, &mode );		// GO!		{		routing_regs routing_values;		impactv_params tv_params;			// we first switch off all output, so the monitor(s) won't get invalid signals		if( vc->assigned_crtc[0] ) {			// overwrite list of active displays to switch off displays 			// someone else turned on			si->crtc[0].active_displays = vc->controlled_displays;			Radeon_SetDPMS( ai, 0, B_DPMS_SUSPEND );		}		if( vc->assigned_crtc[1] ) {			si->crtc[1].active_displays = vc->controlled_displays;			Radeon_SetDPMS( ai, 1, B_DPMS_SUSPEND );		}				// mark crtc that will be used from now on		vc->used_crtc[0] = vc->assigned_crtc[0] && si->crtc[0].chosen_displays != dd_none;		vc->used_crtc[1] = vc->assigned_crtc[1] && si->crtc[1].chosen_displays != dd_none;			// then change the mode		if( vc->used_crtc[0] )			Radeon_SetMode( ai, &si->crtc[0], &mode, &tv_params );		if( vc->used_crtc[1] )			Radeon_SetMode( ai, &si->crtc[1], &mode, &tv_params );					// setup signal routing		Radeon_ReadMonitorRoutingRegs( ai, &routing_values );		Radeon_CalcMonitorRouting( ai, &tv_params, &routing_values );		Radeon_ProgramMonitorRouting( ai, &routing_values );	   			// finally, switch display(s) on		if( vc->used_crtc[0] )			Radeon_SetDPMS( ai, 0, B_DPMS_ON );		if( vc->used_crtc[1] )			Radeon_SetDPMS( ai, 1, B_DPMS_ON );					OUTREGP( ai->regs, RADEON_CRTC_EXT_CNTL, 0, ~RADEON_CRTC_DISPLAY_DIS );	}	   	SHOW_FLOW( 3, "pitch=%ld", vc->pitch );   	   	// we'll modify bits of this reg, so save it for async access	si->dac_cntl2 = INREG( ai->regs, RADEON_DAC_CNTL2 );		// setup 2D registers	Radeon_Init2D( ai );	// setup position of framebuffer for 2D commands	Radeon_FillStateBuffer( ai, vc->datatype );		// remember that 2D accelerator is not prepared for any virtual card	si->active_vc = -1;		// first move to well-defined position (to setup CRTC offset)	Radeon_MoveDisplay( ai, 0, 0 );			// then to (probably faulty) user-defined pos	Radeon_MoveDisplay( ai, mode.h_display_start, mode.v_display_start );	// set standard palette in direct-colour modes	if( vc->used_crtc[0] )		Radeon_InitPalette( ai, 0 );	if( vc->used_crtc[1] )		Radeon_InitPalette( ai, 1 );		// initialize cursor data	if( vc->used_crtc[0] )		Radeon_SetCursorColors( ai, 0 );	if( vc->used_crtc[1] )		Radeon_SetCursorColors( ai, 1 );			// sync should be settled now, so we can reenable IRQs	Radeon_EnableIRQ( ai, true );			RELEASE_BEN( si->engine.lock );	// !! all this must be done after lock has been 	//    released to avoid dead-lock !!	// TBD: any invalid intermediate states?	// move_cursor sets all cursor-related variables and registers	vc->cursor.is_visible = false;	MOVE_CURSOR( 0, 0 );	return B_OK;}

⌨️ 快捷键说明

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