rem: uint8 maventv_regs[64];   gx50_maven_timing m_timing;
context: int maventv_init(display_mode target) {	uint8 val;	uint8 m_result, n_result, p_result;	unsigned int ht_new, ht_last_line;	float calc_pclk = 0;	/* use a display_mode copy because we might tune it for TVout compatibility */	display_mode tv_target = target;	/* used as buffer for TVout signal to generate */	uint8 maventv_regs[64];	/* used in G450/G550 to calculate TVout signal timing dependant on pixelclock;	 * <= G400MAX use fixed settings because base-clock here is the fixed crystal	 * frequency. */	//fixme: if <=G400 cards with MAVEN and crystal of 14.31818Mhz exist, modify!?!	gx50_maven_timing m_timing;	/* preset new TVout mode */	if ((tv_target.flags & TV_BITS) == TV_PAL)	{		LOG(4, ("MAVENTV: PAL TVout\n"));		gxx0_maventv_PAL_init(maventv_regs);		gx50_maventv_PAL_timing(&m_timing);	}	else	{		LOG(4, ("MAVENTV: NTSC TVout\n"));		gxx0_maventv_NTSC_init(maventv_regs);		gx50_maventv_NTSC_timing(&m_timing);	}	/* enter mode-program mode *///	if (si->ps.card_type <= G400MAX) MAVW(PGM, 0x01);//	else//	{//		DXIW(TVO_IDX, NVMAV_PGM);//		DXIW(TVO_DATA, 0x01);//	}	/* tune new TVout mode *///	if (si->ps.card_type <= G400MAX)	{		/* setup TV-mode 'copy' of CRTC2, setup PLL, inputs, outputs and sync-locks *///		MAVW(MONSET, 0x00);//		MAVW(MONEN, 0xA2);		/* xmiscctrl */		//unknown regs://		MAVWW(WREG_0X8E_L, 0x1EFF); //		MAVW(BREG_0XC6, 0x01);//		MAVW(LOCK, 0x01);//		MAVW(OUTMODE, 0x08);//		MAVW(LUMA, 0x78);//		MAVW(STABLE, 0x02);//		MAVW(MONEN, 0xB3);		/* setup video PLL */		g100_g400max_maventv_vid_pll_find(			tv_target, &ht_new, &ht_last_line, &m_result, &n_result, &p_result);//		MAVW(PIXPLLM, m_result);//		MAVW(PIXPLLN, n_result);//		MAVW(PIXPLLP, (p_result | 0x80));//		MAVW(MONSET, 0x20);//		MAVW(TEST, 0x10);		/* htotal - 2 *///		MAVWW(HTOTALL, ht_new);		/* last line in field can have different length */		/* hlen - 2 *///		MAVWW(LASTLINEL, ht_last_line);		/* horizontal vidrst pos: 0 <= vidrst pos <= htotal - 2 *///		MAVWW(HVIDRSTL, (ht_last_line - si->crtc_delay - //						(tv_target.timing.h_sync_end - tv_target.timing.h_sync_start)));		//ORG (does the same but with limit checks but these limits should never occur!)://		slen = tv_target.timing.h_sync_end - tv_target.timing.h_sync_start;//		hcrt = tv_target.timing.h_total - slen - si->crtc_delay;//		if (ht_last_line < tv_target.timing.h_total) hcrt += ht_last_line;//		if (hcrt > tv_target.timing.h_total) hcrt -= tv_target.timing.h_total;//		if (hcrt + 2 > tv_target.timing.h_total) hcrt = 0;	/* or issue warning? *///		MAVWW(HVIDRSTL, hcrt);		/* who knows *///		MAVWW(HSYNCSTRL, 0x0004);//must be 4!!		/* hblanking end: 100% *///		MAVWW(HSYNCLENL, (tv_target.timing.h_total - tv_target.timing.h_sync_end));		/* vertical line count - 1 *///		MAVWW(VTOTALL, (tv_target.timing.v_total - 1));		/* vertical vidrst pos *///		MAVWW(VVIDRSTL, (tv_target.timing.v_total - 2));		/* something end... [A6]+1..[A8] *///		MAVWW(VSYNCSTRL, 0x0001);		/* vblanking end: stop vblanking *///		MAVWW(VSYNCLENL, (tv_target.timing.v_sync_end - tv_target.timing.v_sync_start - 1));		//org: no visible diff:		//MAVWW(VSYNCLENL, (tv_target.timing.v_total - tv_target.timing.v_sync_start - 1));		/* something start... 0..[A4]-1 *///		MAVWW(VDISPLAYL, 0x0000);		//std setmode (no visible difference)		//MAVWW(VDISPLAYL, (tv_target.timing.v_total - 1));		/* ... *///		MAVWW(WREG_0X98_L, 0x0000);		/* moves picture up/down and so on... *///		MAVWW(VSOMETHINGL, 0x0001); /* Fix this... 0..VTotal */		{			uint32 h_display_tv;			uint8 h_scale_tv;			unsigned int ib_min_length;			unsigned int ib_length;			int index;			/* calc hor scale-back factor from input to output picture (in 1.7 format)			 * the MAVEN has 736 pixels fixed visible? outputline length for TVout */ 			//fixme: shouldn't this be 768 (= PAL 1:1 output 4:3 ratio format)?!?			h_scale_tv = (736 << 7) / tv_target.timing.h_total;//should be PLL corrected			LOG(4,("MAVENTV: horizontal scale-back factor is: %f\n", (h_scale_tv / 128.0)));			/* limit values to MAVEN capabilities (scale-back factor is 0.5-1.0) */			//fixme: how about lowres upscaling?			if (h_scale_tv > 0x80)			{				h_scale_tv = 0x80;				LOG(4,("MAVENTV: limiting horizontal scale-back factor to: %f\n", (h_scale_tv / 128.0)));			}			if (h_scale_tv < 0x40)			{				h_scale_tv = 0x40;				LOG(4,("MAVENTV: limiting horizontal scale-back factor to: %f\n", (h_scale_tv / 128.0)));			}			/* make sure we get no round-off error artifacts on screen */			h_scale_tv--;			/* calc difference in (wanted output picture width (excl. hsync_length)) and			 * (fixed total output line length (=768)),			 * based on input picture and scaling factor */			/* (MAVEN trick (part 1) to get output picture width to fit into just 8 bits) */			h_display_tv = ((768 - 1) << 7) -				(((tv_target.timing.h_total - tv_target.timing.h_sync_end)	/* is left margin */				 + tv_target.timing.h_display - 8)				 * h_scale_tv);			/* convert result from 25.7 to 32.0 format */			h_display_tv = h_display_tv >> 7;			LOG(4,("MAVENTV: displaying output on %d picture pixels\n",				((768 - 1) - h_display_tv)));			/* half result: MAVEN trick (part 2)			 * (258 - 768 pixels, only even number per line is possible) */			h_display_tv = h_display_tv >> 1;			/* limit value to register contraints */			if (h_display_tv > 0xFF) h_display_tv = 0xFF;//			MAVW(HSCALETV, h_scale_tv);//			MAVW(HDISPLAYTV, h_display_tv);			/* calculate line inputbuffer length */			/* It must be between (including):			 * ((input picture left margin) + (input picture hor. resolution) + 4)			 * AND			 * (input picture total line length) (PLL corrected) */			/* calculate minimal line input buffer length */			ib_min_length = ((tv_target.timing.h_total - tv_target.timing.h_sync_end) +				 			  tv_target.timing.h_display + 4);			/* calculate optimal line input buffer length (so top of picture is OK too) */			/* The following formula applies:			 * optimal buffer length = ((((0x78 * i) - R) / hor. scaling factor) + Q)			 *			 * where (in 4.8 format!)		     * R      Qmin  Qmax			 * 0x0E0  0x5AE 0x5BF			 * 0x100  0x5CF 0x5FF				 * 0x180  0x653 0x67F			 * 0x200  0x6F8 0x6FF			 */			index = 1;			do			{				ib_length = ((((((0x7800 << 7) * index) - (0x100 << 7)) / h_scale_tv) + 0x05E7) >> 8);				index++;			} while (ib_length < ib_min_length);			LOG(4,("MAVENTV: optimal line inputbuffer length: %d\n", ib_length));			if (ib_length >= ht_new + 2)			{				ib_length = ib_min_length;				LOG(4,("MAVENTV: limiting line inputbuffer length, setting minimal usable: %d\n", ib_length));			}//			MAVWW(HDISPLAYL, ib_length);		}		{			uint16 t_scale_tv;			uint32 v_display_tv;			/* calc total scale-back factor from input to output picture */			{				uint32 out_clocks;				uint32 in_clocks;				//takes care of green stripes:				/* calc output clocks per frame */				out_clocks = m_timing.v_total * (ht_new + 2);				/* calc input clocks per frame */				in_clocks = (tv_target.timing.v_total - 1) * (ht_new + 2) +	ht_last_line + 2;				/* calc total scale-back factor from input to output picture in 1.15 format */				t_scale_tv = ((((uint64)out_clocks) << 15) / in_clocks); 				LOG(4,("MAVENTV: total scale-back factor is: %f\n", (t_scale_tv / 32768.0)));				/* min. scale-back factor is 1.0 for 1:1 output */				if (t_scale_tv > 0x8000)				{					t_scale_tv = 0x8000;					LOG(4,("MAVENTV: limiting total scale-back factor to: %f\n", (t_scale_tv / 32768.0)));				}			}			/*calc output picture height based on input picture and scaling factor */			//warning: v_display was 'one' lower originally!			v_display_tv = 				((tv_target.timing.v_sync_end - tv_target.timing.v_sync_start) 	/* is sync length */				 + (tv_target.timing.v_total - tv_target.timing.v_sync_end) 	/* is upper margin */				 + tv_target.timing.v_display)				 * t_scale_tv;			/* convert result from 17.15 to 32.0 format */			v_display_tv = (v_display_tv >> 15);			LOG(4,("MAVENTV: displaying output on %d picture frame-lines\n", v_display_tv));			/* half result, and compensate for internal register offset			 * (MAVEN trick to get it to fit into just 8 bits).			 * (allowed output frame height is 292 - 802 lines, only even numbers) */			v_display_tv = (v_display_tv >> 1) - 146;			/* limit value to register contraints */			if (v_display_tv > 0xFF) v_display_tv = 0xFF;			/* make sure we get no round-off error artifacts on screen */			t_scale_tv--;//			MAVWW(TSCALETVL, t_scale_tv);//			MAVW(VDISPLAYTV, v_display_tv);		}//		MAVW(TEST, 0x00);		/* gamma correction registers *///		MAVW(GAMMA1, 0x00);//		MAVW(GAMMA2, 0x00);//		MAVW(GAMMA3, 0x00);//		MAVW(GAMMA4, 0x1F);//		MAVW(GAMMA5, 0x10);//		MAVW(GAMMA6, 0x10);//		MAVW(GAMMA7, 0x10);//		MAVW(GAMMA8, 0x64);	/* 100 *///		MAVW(GAMMA9, 0xC8);	/* 200 */		/* set flickerfilter */		/* OFF: is dependant on MAVEN chip version(?): NV_TVO_B = $40, else $00.		 * ON : always set $a2. *///		MAVW(FFILTER, 0xa2);		/* 0x10 or anything ored with it */		//fixme? linux uses 0x14...//		MAVW(TEST, (MAVR(TEST) & 0x10));		/* output: SVideo/Composite *///		MAVW(OUTMODE, 0x08);	}//	else /* card_type is >= G450 */	{		//fixme: setup an intermediate buffer if vertical res is different than settings below!		//fixme: setup 2D or 3D engine to do screen_to_screen_scaled_filtered_blit between the buffers		//       during vertical retrace!		if ((tv_target.flags & TV_BITS) == TV_PAL)		{			int diff;			/* defined by the PAL standard */			tv_target.timing.v_total = m_timing.v_total;			/* we need to center the image on TV vertically.			 * note that 576 is the maximum supported resolution for the PAL standard,			 * this is already overscanning by approx 8-10% */			diff = 576 - tv_target.timing.v_display;			/* if we cannot display the current vertical resolution fully, clip it */			if (diff < 0)			{				tv_target.timing.v_display = 576;				diff = 0;			}			/* now center the image on TV by centering the vertical sync pulse */			tv_target.timing.v_sync_start = tv_target.timing.v_display + 1 + (diff / 2);			tv_target.timing.v_sync_end = tv_target.timing.v_sync_start + 1;		}		else		{			int diff;			/* defined by the NTSC standard */			tv_target.timing.v_total = m_timing.v_total;			/* we need to center the image on TV vertically.			 * note that 480 is the maximum supported resolution for the NTSC standard,			 * this is already overscanning by approx 8-10% */			diff = 480 - tv_target.timing.v_display;			/* if we cannot display the current vertical resolution fully, clip it */			if (diff < 0)			{				tv_target.timing.v_display = 480;				diff = 0;			}			/* now center the image on TV by centering the vertical sync pulse */			tv_target.timing.v_sync_start = tv_target.timing.v_display + 1 + (diff / 2);			tv_target.timing.v_sync_end = tv_target.timing.v_sync_start + 1;		}		/* setup video PLL for G450/G550:		 * this can be done in the normal way because the MAVEN works in slave mode!		 * NOTE: must be done before programming CRTC2, or interlaced startup may fail. */		//fixme: make sure videoPLL is powered up: XPWRCTRL b1=1		{			uint16 front_porch, back_porch, h_sync_length, burst_length, h_total, h_display;			uint32 chromasc;			uint64 pix_period;			uint16 h_total_wanted, leftover;			/* calculate tv_h_display in 'half pixelclocks' and adhere to MAVEN restrictions.			 * ('half pixelclocks' exist because the MAVEN uses them...) */			h_display = (((tv_target.timing.h_display << 1) + 3) & ~0x03);			if (h_display > 2044) h_display = 2044;			/* copy result to MAVEN TV mode */			maventv_regs[0x31] = (h_display >> 3);			maventv_regs[0x32] = (h_display & 0x07);			/* calculate needed video pixelclock in kHz.			 * NOTE:			 * The clock calculated is based on MAVEN output, so each pixelclock period			 * is in fact a 'half pixelclock' period compared to monitor mode use. */			tv_target.timing.pixel_clock =				((((uint64)h_display) * 1000000000) / m_timing.h_display);			/* tune display_mode adhering to CRTC2 restrictions */			/* (truncate h_display to 'whole pixelclocks') */			tv_target.timing.h_display = ((h_display >> 1) & ~0x07);			tv_target.timing.h_sync_start = tv_target.timing.h_display + 8;//			g450_g550_maven_vid_pll_find(tv_target, &calc_pclk, &m_result, &n_result, &p_result, 1);			/* adjust mode to actually used pixelclock */			tv_target.timing.pixel_clock = (calc_pclk * 1000);			/* program videoPLL *///			DXIW(VIDPLLM, m_result);//			DXIW(VIDPLLN, n_result);//			DXIW(VIDPLLP, p_result);			/* calculate videoclock 'half' period duration in picoseconds */			pix_period = (1000000000 / ((float)tv_target.timing.pixel_clock)) + 0.5;			LOG(4,("MAVENTV: TV videoclock period is %d picoseconds\n", pix_period));			/* calculate number of 'half' clocks per line according to pixelclock set */			/* fixme: try to setup the modes in such a way that			 * (h_total_clk % 16) == 0 because of the CRTC2 restrictions:			 * we want to loose the truncating h_total trick below if possible! */			/* Note:			 * This is here so we can see the wanted and calc'd timing difference. */			h_total_wanted = ((m_timing.h_total / ((float)pix_period)) + 0.5);			LOG(4,("MAVENTV: TV h_total should be %d units\n", h_total_wanted));			/* calculate chroma subcarrier value to setup:			 * do this as exact as possible because this signal is very sensitive.. */			chromasc =				((((uint64)0x100000000) * (m_timing.chroma_subcarrier / calc_pclk)) + 0.5);			/* copy result to MAVEN TV mode */			maventv_regs[0] = ((chromasc >> 24) & 0xff);			maventv_regs[1] = ((chromasc >> 16) & 0xff);			maventv_regs[2] = ((chromasc >>  8) & 0xff);			maventv_regs[3] = ((chromasc >>  0) & 0xff);			LOG(4,("MAVENTV: TV chroma subcarrier divider set is $%08x\n", chromasc));			/* calculate front porch in 'half pixelclocks' */			/* we always round up because of the h_total truncating 'trick' below,			 * which works in combination with the existing difference between			 * h_total_clk and h_total */			//fixme: prevent this if possible!			front_porch = ((m_timing.front_porch / ((float)pix_period)) + 1);			/* value must be even */			front_porch &= ~0x01;			/* calculate back porch in 'half pixelclocks' */			/* we always round up because of the h_total truncating 'trick' below,			 * which works in combination with the existing difference between			 * h_total_clk and h_total */			//fixme: prevent this if possible!			back_porch = ((m_timing.back_porch / ((float)pix_period)) + 1);			/* value must be even */			back_porch &= ~0x01;			/* calculate h_sync length in 'half pixelclocks' */			/* we always round up because of the h_total truncating 'trick' below,			 * which works in combination with the existing difference between			 * h_total_clk and h_total */			//fixme: prevent this if possible!			h_sync_length = ((m_timing.h_sync_length / ((float)pix_period)) + 1);			/* value must be even */			h_sync_length &= ~0x01;			/* calculate h_total in 'half pixelclocks' */			h_total = h_display + front_porch + back_porch + h_sync_length;			LOG(4,("MAVENTV: TV front_porch is %d clocks\n", front_porch));			LOG(4,("MAVENTV: TV back_porch is %d clocks\n", back_porch));			LOG(4,("MAVENTV: TV h_sync_length is %d clocks\n", h_sync_length));			LOG(4,("MAVENTV: TV h_display is %d clocks \n", h_display));			LOG(4,("MAVENTV: TV h_total is %d clocks\n", h_total));			/* calculate color_burst length in 'half pixelclocks' */			burst_length = (((m_timing.color_burst /*- 1*/) / ((float)pix_period)) + 0.5);			LOG(4,("MAVENTV: TV color_burst is %d clocks.\n", burst_length));			/* copy result to MAVEN TV mode */			maventv_regs[0x09] = burst_length;			/* Calculate line length 'rest' that remains after truncating			 * h_total to adhere to the CRTC2 timing restrictions. */			leftover = h_total & 0x0F;			/* if some 'rest' exists, we need to compensate for it... */ 			/* Note:			 * It's much better to prevent this from happening because this			 * 'trick' will decay TVout timing! (timing is nolonger official) */			if (leftover)			{				/* truncate line length to adhere to CRTC2 restrictions */				front_porch -= leftover;				h_total -= leftover;				/* now set line length to closest CRTC2 valid match */				if (leftover < 3)				{					/* 1 <= old rest <= 2:					 * Truncated line length is closest match. */					LOG(4,("MAVENTV: CRTC2 h_total leftover discarded (< 3)\n"));				}				else				{					if (leftover < 10)					{						/* 3 <= old rest <= 9:						 * We use the NTSC killer circuitry to get closest match.						 * (The 'g400_crtc2_set_timing' routine will enable it						 *  because of the illegal h_total timing we create here.) */						front_porch += 4;						h_total += 4;						LOG(4,("MAVENTV: CRTC2 h_total leftover corrected via killer (> 2, < 10)\n"));					}					else					{						/* 10 <= old rest <= 15:						 * Set closest valid CRTC2 match. */						front_porch += 16;						h_total += 16;						LOG(4,("MAVENTV: CRTC2 h_total leftover corrected via increase (> 9, < 16)\n"));					}				}			}			/* (linux) fixme: maybe MAVEN has requirement 800 < h_total < 1184 */			maventv_regs[0x2C] = front_porch;			maventv_regs[0x0A] = back_porch;			maventv_regs[0x08] = h_sync_length;			/* change h_total to represent 'whole pixelclocks' */			h_total = h_total >> 1;			/* tune display_mode adhering to CRTC2 restrictions */			tv_target.timing.h_sync_end = (h_total & ~0x07) - 8;			/* h_total is checked before being programmed! (NTSC killer circuitry) */			tv_target.timing.h_total = h_total;		}		/* output Y/C and CVBS signals (| $40 needed for SCART) *///		DXIW(TVO_IDX, 0x80);//		DXIW(TVO_DATA, 0x03);		/* select input colorspace */		//fixme?: has no effect on output picture on monitor or TV...		//DXIW(TVO_IDX, 0x81);		//DXIW(TVO_DATA, 0x00);		/* calculate vertical sync point */		{			int upper;					/* set 625 lines for PAL or 525 lines for NTSC */			maventv_regs[0x17] = m_timing.v_total / 4;			maventv_regs[0x18] = m_timing.v_total & 3;			/* calculate upper blanking range in field lines */			upper = (m_timing.v_total - tv_target.timing.v_sync_end) >> 1;			/* blank TVout above the line number calculated */			maventv_regs[0x33] = upper - 1;			/* set calculated vertical sync point *///			DXIW(TVO_IDX, 0x82);//			DXIW(TVO_DATA, (upper & 0xff));//			DXIW(TVO_IDX, 0x83);//			DXIW(TVO_DATA, ((upper >> 8) & 0xff));			LOG(4,("MAVENTV: TV upper blanking range set is %d\n", upper));		}		/* set fized horizontal sync point *///		DXIW(TVO_IDX, 0x84);//		DXIW(TVO_DATA, 0x01);//		DXIW(TVO_IDX, 0x85);//		DXIW(TVO_DATA, 0x00);		/* connect DAC1 to CON1, CRTC2/'DAC2' to CON2 (TVout mode) *///		DXIW(OUTPUTCONN,0x0d); 	}	/* program new TVout mode */	for (val = 0x00; val <= 0x3D; val++)	{/*		if (si->ps.card_type <= G400MAX)		{			i2c_maven_write(val, maventv_regs[val]);		}		else*/		{//			DXIW(TVO_IDX, val);//			DXIW(TVO_DATA, maventv_regs[val]);		}	}	/* leave mode-program mode *///	if (si->ps.card_type <= G400MAX) MAVW(PGM, 0x00);//	else//	{//		DXIW(TVO_IDX, NVMAV_PGM);//		DXIW(TVO_DATA, 0x00);		/* Select 2.0 Volt MAVEN DAC ref. so we have enough contrast/brightness range *///		DXIW(GENIOCTRL, DXIR(GENIOCTRL) | 0x40);//		DXIW(GENIODATA, 0x00);//	}	/* setup CRTC2 timing */	head2_set_timing(tv_target);	/* start whole thing if needed *///	if (si->ps.card_type <= G400MAX) MAVW(RESYNC, 0x20);	return 0;}