/* CTRC functionality */
/* Author:
   Rudolf Cornelissen 4/2003-1/2004
*/

#define MODULE_BIT 0x00040000

#include "nm_std.h"

/* Adjust passed parameters to a valid mode line */
//fixme: the order of the sync edges should also be checked,
//just like the sync signal's min. pulse length...
status_t nm_crtc_validate_timing(
	uint16 *hd_e,uint16 *hs_s,uint16 *hs_e,uint16 *ht,
	uint16 *vd_e,uint16 *vs_s,uint16 *vs_e,uint16 *vt
)
{
/* horizontal */
	/* make all parameters multiples of 8 */
	*hd_e &= 0xfff8;
	*hs_s &= 0xfff8;
	*hs_e &= 0xfff8;
	*ht   &= 0xfff8;

	/* confine to required number of bits, taking logic into account */
	if (*hd_e > ((0xff - 2) << 3)) *hd_e = ((0xff - 2) << 3);
	if (*hs_s > ((0xff - 1) << 3)) *hs_s = ((0xff - 1) << 3);
	if (*hs_e > ( 0xff      << 3)) *hs_e = ( 0xff      << 3);
	if (*ht   > ((0xff + 5) << 3)) *ht   = ((0xff + 5) << 3);

	/* NOTE: keep horizontal timing at multiples of 8! */
	/* confine to a reasonable width */
	if (*hd_e < 640) *hd_e = 640;
	if (*hd_e > si->ps.max_crtc_width) *hd_e = si->ps.max_crtc_width;

	/* if hor. total does not leave room for a sensible sync pulse, increase it! */
	if (*ht < (*hd_e + 80)) *ht = (*hd_e + 80);

	/* make sure sync pulse is not during display */
	if (*hs_e > (*ht - 8)) *hs_e = (*ht - 8);
	if (*hs_s < (*hd_e + 8)) *hs_s = (*hd_e + 8);

	/* correct sync pulse if it is too long:
	 * there are only 5 bits available to save this in the card registers! */
	if (*hs_e > (*hs_s + 0xf8)) *hs_e = (*hs_s + 0xf8);

/*vertical*/
	/* confine to required number of bits, taking logic into account */
	if (si->ps.card_type < NM2200)
	{
		if (*vd_e > (0x3ff - 2)) *vd_e = (0x3ff - 2);
		if (*vs_s > (0x3ff - 1)) *vs_s = (0x3ff - 1);
		if (*vs_e >  0x3ff     ) *vs_e =  0x3ff     ;
		if (*vt   > (0x3ff + 2)) *vt   = (0x3ff + 2);
	}
	else
	{
		if (*vd_e > (0x7ff - 2)) *vd_e = (0x7ff - 2);
		if (*vs_s > (0x7ff - 1)) *vs_s = (0x7ff - 1);
		if (*vs_e >  0x7ff     ) *vs_e =  0x7ff     ;
		if (*vt   > (0x7ff + 2)) *vt   = (0x7ff + 2);
	}

	/* confine to a reasonable height */
	if (*vd_e < 480) *vd_e = 480;
	if (*vd_e > si->ps.max_crtc_height) *vd_e = si->ps.max_crtc_height;

	/*if vertical total does not leave room for a sync pulse, increase it!*/
	if (*vt < (*vd_e + 3)) *vt = (*vd_e + 3);

	/* make sure sync pulse is not during display */
	if (*vs_e > (*vt - 1)) *vs_e = (*vt - 1);
	if (*vs_s < (*vd_e + 1)) *vs_s = (*vd_e + 1);

	/* correct sync pulse if it is too long:
	 * there are only 4 bits available to save this in the card registers! */
	if (*vs_e > (*vs_s + 0x0f)) *vs_e = (*vs_s + 0x0f);

	return B_OK;
}

/* set a mode line */
status_t nm_crtc_set_timing(display_mode target, bool crt_only)
{
	uint8 temp;

	uint32 htotal;		/*total horizontal total VCLKs*/
	uint32 hdisp_e;            /*end of horizontal display (begins at 0)*/
	uint32 hsync_s;            /*begin of horizontal sync pulse*/
	uint32 hsync_e;            /*end of horizontal sync pulse*/
	uint32 hblnk_s;            /*begin horizontal blanking*/
	uint32 hblnk_e;            /*end horizontal blanking*/

	uint32 vtotal;		/*total vertical total scanlines*/
	uint32 vdisp_e;            /*end of vertical display*/
	uint32 vsync_s;            /*begin of vertical sync pulse*/
	uint32 vsync_e;            /*end of vertical sync pulse*/
	uint32 vblnk_s;            /*begin vertical blanking*/
	uint32 vblnk_e;            /*end vertical blanking*/

	uint32 linecomp;	/*split screen and vdisp_e interrupt*/

	LOG(4,("CRTC: setting timing\n"));

	/* modify visible sceensize if needed */
	/* (note that MOVE_CURSOR checks for a panning/scrolling mode itself,
	 *  the display_mode as placed in si->dm may _not_ be modified!) */
	if (!(crt_only))
	{
		if (target.timing.h_display > si->ps.panel_width)
		{
			target.timing.h_display = si->ps.panel_width;
			LOG(4, ("CRTC: req. width > panel width: setting panning mode\n"));
		}
		if (target.timing.v_display > si->ps.panel_height)
		{
			target.timing.v_display = si->ps.panel_height;
			LOG(4, ("CRTC: req. height > panel height: setting scrolling mode\n"));
		}
	}

	/* Modify parameters as required by standard VGA */
	htotal = ((target.timing.h_total >> 3) - 5);
	hdisp_e = ((target.timing.h_display >> 3) - 1);
	hblnk_s = hdisp_e;
	hblnk_e = (htotal + 0); /* this register differs from standard VGA! (says + 4) */		
	hsync_s = (target.timing.h_sync_start >> 3);
	hsync_e = (target.timing.h_sync_end >> 3);

	vtotal = target.timing.v_total - 2;
	vdisp_e = target.timing.v_display - 1;
	vblnk_s = vdisp_e;
	vblnk_e = (vtotal + 1);
	vsync_s = target.timing.v_sync_start;//-1;
	vsync_e = target.timing.v_sync_end;//-1;

	/* prevent memory adress counter from being reset (linecomp may not occur) */
	linecomp = target.timing.v_display;

	if (crt_only)
	{
		LOG(4,("CRTC: CRT only mode, setting full timing...\n"));

		/* log the mode that will be set */
		LOG(2,("CRTC:\n\tHTOT:%x\n\tHDISPEND:%x\n\tHBLNKS:%x\n\tHBLNKE:%x\n\tHSYNCS:%x\n\tHSYNCE:%x\n\t",htotal,hdisp_e,hblnk_s,hblnk_e,hsync_s,hsync_e));
		LOG(2,("VTOT:%x\n\tVDISPEND:%x\n\tVBLNKS:%x\n\tVBLNKE:%x\n\tVSYNCS:%x\n\tVSYNCE:%x\n",vtotal,vdisp_e,vblnk_s,vblnk_e,vsync_s,vsync_e));

		/* actually program the card! */
		/* unlock CRTC registers at index 0-7 */
		temp = (ISACRTCR(VSYNCE) & 0x7f);
		/* we need to wait a bit or the card will mess-up it's register values.. */
		snooze(10);
		ISACRTCW(VSYNCE, temp);
		/* horizontal standard VGA regs */
		ISACRTCW(HTOTAL, (htotal & 0xff));
		ISACRTCW(HDISPE, (hdisp_e & 0xff));
		ISACRTCW(HBLANKS, (hblnk_s & 0xff));
		/* also unlock vertical retrace registers in advance */
		ISACRTCW(HBLANKE, ((hblnk_e & 0x1f) | 0x80));
		ISACRTCW(HSYNCS, (hsync_s & 0xff));
		ISACRTCW(HSYNCE, ((hsync_e & 0x1f) | ((hblnk_e & 0x20) << 2)));

		/* vertical standard VGA regs */
		ISACRTCW(VTOTAL, (vtotal & 0xff));
		ISACRTCW(OVERFLOW,
		(
			((vtotal & 0x100) >> (8 - 0)) | ((vtotal & 0x200) >> (9 - 5)) |
			((vdisp_e & 0x100) >> (8 - 1)) | ((vdisp_e & 0x200) >> (9 - 6)) |
			((vsync_s & 0x100) >> (8 - 2)) | ((vsync_s & 0x200) >> (9 - 7)) |
			((vblnk_s & 0x100) >> (8 - 3)) | ((linecomp & 0x100) >> (8 - 4))
		));
		ISACRTCW(PRROWSCN, 0x00); /* not used */
		ISACRTCW(MAXSCLIN, (((vblnk_s & 0x200) >> (9 - 5)) | ((linecomp & 0x200) >> (9 - 6))));
		ISACRTCW(VSYNCS, (vsync_s & 0xff));
		temp = (ISACRTCR(VSYNCE) & 0xf0);
		/* we need to wait a bit or the card will mess-up it's register values.. */
		snooze(10);
		ISACRTCW(VSYNCE, (temp | (vsync_e & 0x0f)));
		ISACRTCW(VDISPE, (vdisp_e & 0xff));
		ISACRTCW(VBLANKS, (vblnk_s & 0xff));
		ISACRTCW(VBLANKE, (vblnk_e & 0xff));
//linux:
//	regp->CRTC[23] = 0xC3;
		ISACRTCW(LINECOMP, (linecomp & 0xff));

		/* horizontal - no extended regs available or needed on NeoMagic chips */

		/* vertical - extended regs */
//fixme: checkout if b2 or 3 should be switched! (linux contains error here)
//fixme: linecomp should also have an extra bit... testable by setting linecomp
//to 100 for example and then try out writing an '1' to b2, b3(!) and the rest
//for screenorig reset visible on upper half of the screen or not at all..
		if (si->ps.card_type >= NM2200)
			ISACRTCW(VEXT,
			(
			 	((vtotal & 0x400) >> (10 - 0)) |
				((vdisp_e & 0x400) >> (10 - 1)) |
				((vblnk_s & 0x400) >> (10 - 2)) |
				((vsync_s & 0x400) >> (10 - 3))/*|
				((linecomp&0x400)>>3)*/
			));

		/* setup HSYNC & VSYNC polarity */
		LOG(2,("CRTC: sync polarity: "));
		temp = ISARB(MISCR);
		if (target.timing.flags & B_POSITIVE_HSYNC)
		{
			LOG(2,("H:pos "));
			temp &= ~0x40;
		}
		else
		{
			LOG(2,("H:neg "));
			temp |= 0x40;
		}
		if (target.timing.flags & B_POSITIVE_VSYNC)
		{
			LOG(2,("V:pos "));
			temp &= ~0x80;
		}
		else
		{
			LOG(2,("V:neg "));
			temp |= 0x80;
		}
		/* we need to wait a bit or the card will mess-up it's register values.. */
		snooze(10);
		ISAWB(MISCW, temp);

		LOG(2,(", MISC reg readback: $%02x\n", ISARB(MISCR)));
	}
	else
	{
		LOG(4,("CRTC: internal flatpanel active, setting display region only\n"));

		/* actually program the card! */
		/* unlock CRTC registers at index 0-7 */
		temp = (ISACRTCR(VSYNCE) & 0x7f);
		/* we need to wait a bit or the card will mess-up it's register values.. */
		snooze(10);
		ISACRTCW(VSYNCE, temp);
		/* horizontal standard VGA regs */
		ISACRTCW(HDISPE, (hdisp_e & 0xff));

		/* vertical standard VGA regs */
		temp = (ISACRTCR(OVERFLOW) & ~0x52);
		/* we need to wait a bit or the card will mess-up it's register values.. */
		snooze(10);
		ISACRTCW(OVERFLOW,
		(	
			temp |
			((vdisp_e & 0x100) >> (8 - 1)) |
			((vdisp_e & 0x200) >> (9 - 6)) |
			((linecomp & 0x100) >> (8 - 4))
		));

		ISACRTCW(PRROWSCN, 0x00); /* not used */

		temp = (ISACRTCR(MAXSCLIN) & ~0x40);
		/* we need to wait a bit or the card will mess-up it's register values.. */
		snooze(10);
		ISACRTCW(MAXSCLIN, (temp | ((linecomp & 0x200) >> (9 - 6))));

		ISACRTCW(VDISPE, (vdisp_e & 0xff));
//linux:
//	regp->CRTC[23] = 0xC3;
		ISACRTCW(LINECOMP, (linecomp & 0xff));

		/* horizontal - no extended regs available or needed on NeoMagic chips */

		/* vertical - extended regs */
//fixme: linecomp should have an extra bit... testable by setting linecomp
//to 100 for example and then try out writing an '1' to b2, b3(!) and the rest
//for screenorig reset visible on upper half of the screen or not at all..
		if (si->ps.card_type >= NM2200)
		{
			temp = (ISACRTCR(VEXT) & ~0x02);
			/* we need to wait a bit or the card will mess-up it's register values.. */
			snooze(10);
			ISACRTCW(VEXT,
			(
				temp |
				((vdisp_e & 0x400) >> (10 - 1))/*|
				((linecomp&0x400)>>3)*/
			));
		}
	}

	return B_OK;
}

status_t nm_crtc_depth(int mode)
{
	uint8 vid_delay = 0;

	LOG(4,("CRTC: setting colordepth to be displayed\n"));

	/* set VCLK scaling */
	switch(mode)
	{
	case BPP8:
		vid_delay = 0x01;
		break;
	case BPP15:
		vid_delay = 0x02;
		break;
	case BPP16:
		vid_delay = 0x03;
		break;
	case BPP24:
		vid_delay = 0x04;
		break;
	default:
		LOG(4,("CRTC: colordepth not supported, aborting!\n"));
		return B_ERROR;
		break;
	}

	switch (si->ps.card_type)
	{
	case NM2070:
		vid_delay |= (ISAGRPHR(COLDEPTH) & 0xf0);
		break;
	default:
		vid_delay |= (ISAGRPHR(COLDEPTH) & 0x70);
		break;
	}
	/* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */
	snooze(10);
	ISAGRPHW(COLDEPTH, vid_delay);

	snooze(10);
	LOG(4,("CRTC: colordepth register readback $%02x\n", (ISAGRPHR(COLDEPTH))));

	return B_OK;
}

status_t nm_crtc_dpms(bool display, bool h, bool v)
{
	uint8 temp;

	LOG(4,("CRTC: setting DPMS: "));

	/* start synchronous reset: required before turning screen off! */
	ISASEQW(RESET, 0x01);

	/* turn screen off */
	temp = ISASEQR(CLKMODE);
	/* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */
	snooze(10);

	if (display)
	{
		ISASEQW(CLKMODE, (temp & ~0x20));

		/* end synchronous reset if display should be enabled */
		ISASEQW(RESET, 0x03);

		LOG(4,("display on\n"));
	}
	else
	{
		ISASEQW(CLKMODE, (temp | 0x20));

		LOG(4,("display off\n"));
	}

//	LOG(4,("CRTC: setting DPMS (%d,%d,%d)\n", display,h,v));

//	VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0xCF)|((!v)<<5))|((!h)<<4);
	
	/* set some required fixed values for proper nm mode initialisation */
//	VGAW_I(CRTC,0x17,0xC3);
//	VGAW_I(CRTC,0x14,0x00);

	return B_OK;
}

status_t nm_crtc_dpms_fetch(bool * display, bool * h, bool * v)
{
	*display = !(ISASEQR(CLKMODE) & 0x20);

//	*display=!((VGAR_I(SEQ,1)&0x20)>>5);
//	*h=!((VGAR_I(CRTCEXT,1)&0x10)>>4);
//	*v=!((VGAR_I(CRTCEXT,1)&0x20)>>5);

	*h = *v = true;

	LOG(4,("CTRC: fetched DPMS state:"));
	if (display) LOG(4,("display on\n"));
	else LOG(4,("display off\n"));

	return B_OK;
}

status_t nm_crtc_set_display_pitch() 
{
	uint32 offset;

	LOG(4,("CRTC: setting card pitch (offset between lines)\n"));

	/* figure out offset value hardware needs: same for all Neomagic cards */
	offset = si->fbc.bytes_per_row / 8;

	LOG(2,("CRTC: offset register set to: $%04x\n", offset));
		
	/* program the card */
	ISACRTCW(PITCHL, (offset & 0xff));
	//fixme: test for max supported pitch if possible,
	//not all bits below will be implemented.
	//NM2160: confirmed b0 and b1 in register below to exist and work.
	ISAGRPHW(CRTC_PITCHE, ((offset & 0xff00) >> 8));

	return B_OK;
}

status_t nm_crtc_set_display_start(uint32 startadd,uint8 bpp) 
{
	uint8 val;
	uint32 timeout = 0;

	LOG(2,("CRTC: relative startadd: $%06x\n",startadd));
	LOG(2,("CRTC: frameRAM: $%08x\n",si->framebuffer));
	LOG(2,("CRTC: framebuffer: $%08x\n",si->fbc.frame_buffer));

	/* make sure we are in retrace, because otherwise distortions might occur
	 * during our reprogramming them (no double buffering) (verified on NM2160) */

	/* we might have no retraces during setmode! So:
	 * wait 25mS max. for retrace to occur (refresh > 40Hz) */
	//fixme? move this function to the kernel driver... is much 'faster'.
	while ((!(ISARB(INSTAT1) & 0x08)) && (timeout < (25000/4)))
	{
		snooze(4);
		timeout++;
	}

	/* the neomagic framebuffer startadress is given in 32bit words */
	startadd >>= 2;

	/* set standard VGA registers */
    ISACRTCW(FBSTADDH, ((startadd & 0x00FF00) >> 8));
    ISACRTCW(FBSTADDL, (startadd & 0x0000FF));

	/* set NM extended register */
	//fixme: NM2380 _must_ have one more bit (has >4Mb RAM)!!
	//this is testable via virtualscreen in 640x480x8 mode...
	//(b4 is >256Kb adresswrap bit, so that's already occupied)
	val = ISAGRPHR(FBSTADDE);
	/* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */
	snooze(10);
	if (si->ps.card_type < NM2200)
		ISAGRPHW(FBSTADDE,(((startadd >> 16) & 0x07) | (val & 0xf8)));
	else
		ISAGRPHW(FBSTADDE,(((startadd >> 16) & 0x0f) | (val & 0xf0)));

	return B_OK;
}

/* setup centering mode for current internal or simultaneous flatpanel mode */
status_t nm_crtc_center(display_mode target)
{
	uint8 vcent1, vcent2, vcent3, vcent4, vcent5;
	uint8 hcent1, hcent2, hcent3, hcent4, hcent5;
	uint8 ctrl2, ctrl3;

	/* preset no centering */
	uint16 hoffset = 0;
	uint16 voffset = 0;
	vcent1 = vcent2 = vcent3 = vcent4 = vcent5 = 0x00;
	hcent1 = hcent2 = hcent3 = hcent4 = hcent5 = 0x00;
	ctrl2 = ctrl3 = 0x00;

	/* calculate offsets for centering if prudent */
	if (target.timing.h_display < si->ps.panel_width)
	{
		hoffset = (si->ps.panel_width - target.timing.h_display);
		/* adjust for register contraints:
		 * horizontal center granularity is 16 pixels */
		hoffset = ((hoffset >> 4) - 1);
//fixme: what does this do?
		/* turn on horizontal centering? */
		ctrl3 = 0x10;
	}

	if (target.timing.v_display < si->ps.panel_height)
	{
		voffset = (si->ps.panel_height - target.timing.v_display);
		/* adjust for register contraints:
		 * vertical center granularity is 2 pixels */
		voffset = ((voffset >> 1) - 2);
//fixme: what does this do?
		/* turn on vertical centering? */
		ctrl2 = 0x01;
	}

	switch(target.timing.h_display)
	{
	case 640:
		hcent1 = hoffset;
		vcent3 = voffset;
		break;
	case 800:
		hcent2 = hoffset;
		switch(target.timing.v_display)
		{
		case 480:
			//Linux fixme: check this out...
			vcent3 = voffset;
			break;
		case 600:
			vcent4 = voffset;
			break;
		}
		break;
	case 1024:
		hcent5 = hoffset;
		vcent5 = voffset;
		break;
	case 1280:
		/* this mode equals the largest possible panel on the newest chip:
		 * so no centering needed here. */
		break;
	default:
		//fixme?: block non-standard modes? for now: not centered.
		break;
	}

	/* now program the card's registers */
	ISAGRPHW(PANELVCENT1, vcent1);
	ISAGRPHW(PANELVCENT2, vcent2);
	ISAGRPHW(PANELVCENT3, vcent3);
	if (si->ps.card_type > NM2070)
	{
		ISAGRPHW(PANELVCENT4, vcent4);
		ISAGRPHW(PANELHCENT1, hcent1);
		ISAGRPHW(PANELHCENT2, hcent2);
		ISAGRPHW(PANELHCENT3, hcent3);
	}
	if (si->ps.card_type >= NM2160)
	{
		ISAGRPHW(PANELHCENT4, hcent4);
	}
	if (si->ps.card_type >= NM2200)
	{
		ISAGRPHW(PANELVCENT5, vcent5);
		ISAGRPHW(PANELHCENT5, hcent5);
	}

	/* program panel control register 2: don't touch bit 3-5 */
	ctrl2 |= (ISAGRPHR(PANELCTRL2) & 0x38);
	/* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */
	snooze(10);
	ISAGRPHW(PANELCTRL2, ctrl2);

	if (si->ps.card_type > NM2070)
	{
		/* program panel control register 3: don't touch bit 7-5 and bit 3-0 */
		ctrl3 |= (ISAGRPHR(PANELCTRL3) & 0xef);
		/* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */
		snooze(10);
		ISAGRPHW(PANELCTRL3, ctrl3);
	}

	return B_OK;
}

status_t nm_crtc_cursor_init()
{
	int i;
	uint32 * fb;
	/* cursor bitmap will be stored at the start of the framebuffer */
	uint32 curadd = 0, curreg;

	/* set cursor bitmap adress on a 1kb boundary, and move the bits around
	 * so they get placed at the correct registerbits */
	//fixme: NM2380 must have an extra bit for > 4Mb???
	curreg = (((curadd >> 10) & 0x000f) << 8);
	curreg |= (((curadd >> 10) & 0x0ff0) >> 4);

	if (si->ps.card_type < NM2200)
		CR1W(CURADDRESS, curreg);
	else
		CR1W(22CURADDRESS, curreg);

	/*set cursor colour*/
	if (si->ps.card_type < NM2200)
	{
		/* background is black */
		CR1W(CURBGCOLOR, 0x00000000);
		/* foreground is white */
		CR1W(CURFGCOLOR, 0x00ffffff);
	}
	else
	{
		/* background is black */
		CR1W(22CURBGCOLOR, 0x00000000);
		/* foreground is white */
		CR1W(22CURFGCOLOR, 0x00ffffff);
	}

	/*clear cursor*/
	fb = (uint32 *) si->framebuffer + curadd;
	for (i=0;i<(1024/4);i++)
	{
		fb[i]=0;
	}

	/* activate hardware cursor */
	nm_crtc_cursor_show();

	return B_OK;
}

status_t nm_crtc_cursor_show()
{
	if (si->ps.card_type < NM2200)
	{
		CR1W(CURCTRL, 0x00000001);
	}
	else
	{
		CR1W(22CURCTRL, 0x00000001);
	}
	return B_OK;
}

status_t nm_crtc_cursor_hide()
{
//linux fixme: using this kills PCI(?) access sometimes, so use ISA access as below...
/*
	if (si->ps.card_type < NM2200)
	{
		CR1W(CURCTRL, 0x00000000);
	}
	else
	{
		CR1W(22CURCTRL, 0x00000000);
	}
*/
	/* disable cursor */
	ISAGRPHW(CURCTRL,0x00);

	return B_OK;
}

/*set up cursor shape*/
status_t nm_crtc_cursor_define(uint8* andMask,uint8* xorMask)
{
	uint8 y;
	uint8 * cursor;

	/*get a pointer to the cursor*/
	cursor = (uint8*) si->framebuffer;

	/*draw the cursor*/
	for(y=0;y<16;y++)
	{
		cursor[y*16+8]=~*andMask++;
		cursor[y*16+0]=*xorMask++;
		cursor[y*16+9]=~*andMask++;
		cursor[y*16+1]=*xorMask++;
	}

	//test.. only valid for <NM2200!!
/*	{
		float pclk;
		uint8 n,m,x = 1;
		n = ISAGRPHR(PLLC_NL);
		m = ISAGRPHR(PLLC_M);
		LOG(4,("CRTC: PLLSEL $%02x\n", ISARB(MISCR)));
		LOG(4,("CRTC: PLLN $%02x\n", n));
		LOG(4,("CRTC: PLLM $%02x\n", m));

		if (n & 0x80) x = 2;
		n &= 0x7f;
		pclk = ((si->ps.f_ref * (n + 1)) / ((m + 1) * x));
		LOG(2,("CRTC: Pixelclock is %fMHz\n", pclk));
		nm_general_output_select();
	}
*/
	return B_OK;
}

/*position the cursor*/
status_t nm_crtc_cursor_position(uint16 x ,uint16 y)
{
//NM2160 is ok without this, still verify the rest..:
	/* make sure we are not in retrace, because the register(s) might get copied
	 * during our reprogramming them (double buffering feature) */
/*	fixme!?
	while (ACCR(STATUS) & 0x08)
	{
		snooze(4);
	}
*/
	if (si->ps.card_type < NM2200)
	{
		CR1W(CURX, (uint32)x);
		CR1W(CURY, (uint32)y);
	}
	else
	{
		CR1W(22CURX, (uint32)x);
		CR1W(22CURY, (uint32)y);
	}

	return B_OK;
}
