1/* Authors:
2   Mark Watson 12/1999,
3   Apsed,
4   Rudolf Cornelissen 10/2002-11/2004
5*/
6
7#define MODULE_BIT 0x00008000
8
9#include "std.h"
10
11static status_t test_ram(void);
12static status_t engxx_general_powerup (void);
13static status_t eng_general_bios_to_powergraphics(void);
14
15static void eng_dump_configuration_space (void)
16{
17#define DUMP_CFG(reg, type) if (si->ps.card_type >= type) do { \
18	uint32 value = CFGR(reg); \
19	MSG(("configuration_space 0x%02x %20s 0x%08x\n", \
20		ENCFG_##reg, #reg, value)); \
21} while (0)
22	DUMP_CFG (DEVID,	0);
23	DUMP_CFG (DEVCTRL,	0);
24	DUMP_CFG (CLASS,	0);
25	DUMP_CFG (HEADER,	0);
26	DUMP_CFG (BASE1REGS,0);
27	DUMP_CFG (BASE2FB,	0);
28	DUMP_CFG (BASE3,	0);
29	DUMP_CFG (BASE4,	0);
30	DUMP_CFG (BASE5,	0);
31	DUMP_CFG (BASE6,	0);
32	DUMP_CFG (BASE7,	0);
33	DUMP_CFG (SUBSYSID1,0);
34	DUMP_CFG (ROMBASE,	0);
35	DUMP_CFG (CAPPTR,	0);
36	DUMP_CFG (CFG_1,	0);
37	DUMP_CFG (INTERRUPT,0);
38	DUMP_CFG (SUBSYSID2,0);
39	DUMP_CFG (AGPREF,	0);
40	DUMP_CFG (AGPSTAT,	0);
41	DUMP_CFG (AGPCMD,	0);
42	DUMP_CFG (ROMSHADOW,0);
43	DUMP_CFG (VGA,		0);
44	DUMP_CFG (SCHRATCH,	0);
45	DUMP_CFG (CFG_10,	0);
46	DUMP_CFG (CFG_11,	0);
47	DUMP_CFG (CFG_12,	0);
48	DUMP_CFG (CFG_13,	0);
49	DUMP_CFG (CFG_14,	0);
50	DUMP_CFG (CFG_15,	0);
51	DUMP_CFG (CFG_16,	0);
52	DUMP_CFG (CFG_17,	0);
53	DUMP_CFG (CFG_18,	0);
54	DUMP_CFG (CFG_19,	0);
55	DUMP_CFG (CFG_20,	0);
56	DUMP_CFG (CFG_21,	0);
57	DUMP_CFG (CFG_22,	0);
58	DUMP_CFG (CFG_23,	0);
59	DUMP_CFG (CFG_24,	0);
60	DUMP_CFG (CFG_25,	0);
61	DUMP_CFG (CFG_26,	0);
62	DUMP_CFG (CFG_27,	0);
63	DUMP_CFG (CFG_28,	0);
64	DUMP_CFG (CFG_29,	0);
65	DUMP_CFG (CFG_30,	0);
66	DUMP_CFG (CFG_31,	0);
67	DUMP_CFG (CFG_32,	0);
68	DUMP_CFG (CFG_33,	0);
69	DUMP_CFG (CFG_34,	0);
70	DUMP_CFG (CFG_35,	0);
71	DUMP_CFG (CFG_36,	0);
72	DUMP_CFG (CFG_37,	0);
73	DUMP_CFG (CFG_38,	0);
74	DUMP_CFG (CFG_39,	0);
75	DUMP_CFG (CFG_40,	0);
76	DUMP_CFG (CFG_41,	0);
77	DUMP_CFG (CFG_42,	0);
78	DUMP_CFG (CFG_43,	0);
79	DUMP_CFG (CFG_44,	0);
80	DUMP_CFG (CFG_45,	0);
81	DUMP_CFG (CFG_46,	0);
82	DUMP_CFG (CFG_47,	0);
83	DUMP_CFG (CFG_48,	0);
84	DUMP_CFG (CFG_49,	0);
85	DUMP_CFG (CFG_50,	0);
86#undef DUMP_CFG
87}
88
89status_t eng_general_powerup()
90{
91	status_t status;
92
93	LOG(1,("POWERUP: Haiku skeleton Accelerant 0.01 running.\n"));
94
95	/* preset no laptop */
96	si->ps.laptop = false;
97
98	/* detect card type and power it up */
99	switch(CFGR(DEVID))
100	{
101	/* Vendor Via */
102/*	case 0x31221106:
103		si->ps.card_type = NV04;
104		si->ps.card_arch = NV04A;
105		LOG(4,("POWERUP: Detected Nvidia TNT1 (NV04)\n"));
106		status = engxx_general_powerup();
107		break;
108*/	default:
109		LOG(8,("POWERUP: Failed to detect valid card 0x%08x\n",CFGR(DEVID)));
110		return B_ERROR;
111	}
112
113	return status;
114}
115
116static status_t test_ram()
117{
118	uint32 value, offset;
119	status_t result = B_OK;
120
121	/* make sure we don't corrupt the hardware cursor by using fbc.frame_buffer. */
122	if (si->fbc.frame_buffer == NULL)
123	{
124		LOG(8,("INIT: test_ram detected NULL pointer.\n"));
125		return B_ERROR;
126	}
127
128	for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
129	{
130		/* write testpattern to cardRAM */
131		((uint32 *)si->fbc.frame_buffer)[offset] = value;
132		/* toggle testpattern */
133		value = 0xffffffff - value;
134	}
135
136	for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
137	{
138		/* readback and verify testpattern from cardRAM */
139		if (((uint32 *)si->fbc.frame_buffer)[offset] != value) result = B_ERROR;
140		/* toggle testpattern */
141		value = 0xffffffff - value;
142	}
143	return result;
144}
145
146/* NOTE:
147 * This routine *has* to be done *after* SetDispplayMode has been executed,
148 * or test results will not be representative!
149 * (CAS latency is dependant on NV setup on some (DRAM) boards) */
150status_t eng_set_cas_latency()
151{
152	status_t result = B_ERROR;
153	uint8 latency = 0;
154
155	/* check current RAM access to see if we need to change anything */
156	if (test_ram() == B_OK)
157	{
158		LOG(4,("INIT: RAM access OK.\n"));
159		return B_OK;
160	}
161
162	/* check if we read PINS at starttime so we have valid registersettings at our disposal */
163	if (si->ps.pins_status != B_OK)
164	{
165		LOG(4,("INIT: RAM access errors; not fixable: PINS was not read from cardBIOS.\n"));
166		return B_ERROR;
167	}
168
169	/* OK. We might have a problem, try to fix it now.. */
170	LOG(4,("INIT: RAM access errors; tuning CAS latency if prudent...\n"));
171
172	switch(si->ps.card_type)
173	{
174	default:
175			LOG(4,("INIT: RAM CAS tuning not implemented for this card, aborting.\n"));
176			return B_OK;
177			break;
178	}
179	if (result == B_OK)
180		LOG(4,("INIT: RAM access OK. CAS latency set to %d cycles.\n", latency));
181	else
182		LOG(4,("INIT: RAM access not fixable. CAS latency set to %d cycles.\n", latency));
183
184	return result;
185}
186
187void setup_virtualized_heads(bool cross)
188{
189	if (cross)
190	{
191		head1_validate_timing	= (crtc_validate_timing)	eng_crtc2_validate_timing;
192		head1_set_timing		= (crtc_set_timing)			eng_crtc2_set_timing;
193		head1_depth				= (crtc_depth)				eng_crtc2_depth;
194		head1_dpms				= (crtc_dpms)				eng_crtc2_dpms;
195		head1_dpms_fetch		= (crtc_dpms_fetch)			eng_crtc2_dpms_fetch;
196		head1_set_display_pitch	= (crtc_set_display_pitch)	eng_crtc2_set_display_pitch;
197		head1_set_display_start	= (crtc_set_display_start)	eng_crtc2_set_display_start;
198		head1_cursor_init		= (crtc_cursor_init)		eng_crtc2_cursor_init;
199		head1_cursor_show		= (crtc_cursor_show)		eng_crtc2_cursor_show;
200		head1_cursor_hide		= (crtc_cursor_hide)		eng_crtc2_cursor_hide;
201		head1_cursor_define		= (crtc_cursor_define)		eng_crtc2_cursor_define;
202		head1_cursor_position	= (crtc_cursor_position)	eng_crtc2_cursor_position;
203
204		head1_mode				= (dac_mode)				eng_dac2_mode;
205		head1_palette			= (dac_palette)				eng_dac2_palette;
206		head1_set_pix_pll		= (dac_set_pix_pll)			eng_dac2_set_pix_pll;
207		head1_pix_pll_find		= (dac_pix_pll_find)		eng_dac2_pix_pll_find;
208
209		head2_validate_timing	= (crtc_validate_timing)	eng_crtc_validate_timing;
210		head2_set_timing		= (crtc_set_timing)			eng_crtc_set_timing;
211		head2_depth				= (crtc_depth)				eng_crtc_depth;
212		head2_dpms				= (crtc_dpms)				eng_crtc_dpms;
213		head2_dpms_fetch		= (crtc_dpms_fetch)			eng_crtc_dpms_fetch;
214		head2_set_display_pitch	= (crtc_set_display_pitch)	eng_crtc_set_display_pitch;
215		head2_set_display_start	= (crtc_set_display_start)	eng_crtc_set_display_start;
216		head2_cursor_init		= (crtc_cursor_init)		eng_crtc_cursor_init;
217		head2_cursor_show		= (crtc_cursor_show)		eng_crtc_cursor_show;
218		head2_cursor_hide		= (crtc_cursor_hide)		eng_crtc_cursor_hide;
219		head2_cursor_define		= (crtc_cursor_define)		eng_crtc_cursor_define;
220		head2_cursor_position	= (crtc_cursor_position)	eng_crtc_cursor_position;
221
222		head2_mode				= (dac_mode)				eng_dac_mode;
223		head2_palette			= (dac_palette)				eng_dac_palette;
224		head2_set_pix_pll		= (dac_set_pix_pll)			eng_dac_set_pix_pll;
225		head2_pix_pll_find		= (dac_pix_pll_find)		eng_dac_pix_pll_find;
226	}
227	else
228	{
229		head1_validate_timing	= (crtc_validate_timing)	eng_crtc_validate_timing;
230		head1_set_timing		= (crtc_set_timing)			eng_crtc_set_timing;
231		head1_depth				= (crtc_depth)				eng_crtc_depth;
232		head1_dpms				= (crtc_dpms)				eng_crtc_dpms;
233		head1_dpms_fetch		= (crtc_dpms_fetch)			eng_crtc_dpms_fetch;
234		head1_set_display_pitch	= (crtc_set_display_pitch)	eng_crtc_set_display_pitch;
235		head1_set_display_start	= (crtc_set_display_start)	eng_crtc_set_display_start;
236		head1_cursor_init		= (crtc_cursor_init)		eng_crtc_cursor_init;
237		head1_cursor_show		= (crtc_cursor_show)		eng_crtc_cursor_show;
238		head1_cursor_hide		= (crtc_cursor_hide)		eng_crtc_cursor_hide;
239		head1_cursor_define		= (crtc_cursor_define)		eng_crtc_cursor_define;
240		head1_cursor_position	= (crtc_cursor_position)	eng_crtc_cursor_position;
241
242		head1_mode				= (dac_mode)				eng_dac_mode;
243		head1_palette			= (dac_palette)				eng_dac_palette;
244		head1_set_pix_pll		= (dac_set_pix_pll)			eng_dac_set_pix_pll;
245		head1_pix_pll_find		= (dac_pix_pll_find)		eng_dac_pix_pll_find;
246
247		head2_validate_timing	= (crtc_validate_timing)	eng_crtc2_validate_timing;
248		head2_set_timing		= (crtc_set_timing)			eng_crtc2_set_timing;
249		head2_depth				= (crtc_depth)				eng_crtc2_depth;
250		head2_dpms				= (crtc_dpms)				eng_crtc2_dpms;
251		head2_dpms_fetch		= (crtc_dpms_fetch)			eng_crtc2_dpms_fetch;
252		head2_set_display_pitch	= (crtc_set_display_pitch)	eng_crtc2_set_display_pitch;
253		head2_set_display_start	= (crtc_set_display_start)	eng_crtc2_set_display_start;
254		head2_cursor_init		= (crtc_cursor_init)		eng_crtc2_cursor_init;
255		head2_cursor_show		= (crtc_cursor_show)		eng_crtc2_cursor_show;
256		head2_cursor_hide		= (crtc_cursor_hide)		eng_crtc2_cursor_hide;
257		head2_cursor_define		= (crtc_cursor_define)		eng_crtc2_cursor_define;
258		head2_cursor_position	= (crtc_cursor_position)	eng_crtc2_cursor_position;
259
260		head2_mode				= (dac_mode)				eng_dac2_mode;
261		head2_palette			= (dac_palette)				eng_dac2_palette;
262		head2_set_pix_pll		= (dac_set_pix_pll)			eng_dac2_set_pix_pll;
263		head2_pix_pll_find		= (dac_pix_pll_find)		eng_dac2_pix_pll_find;
264	}
265}
266
267void set_crtc_owner(bool head)
268{
269	if (si->ps.secondary_head)
270	{
271		if (!head)
272		{
273			/* note: 'OWNER' is a non-standard register in behaviour(!) on NV11's,
274			 * while non-NV11 cards behave normally.
275			 *
276			 * Double-write action needed on those strange NV11 cards: */
277			/* RESET: needed on NV11 */
278			CRTCW(OWNER, 0xff);
279			/* enable access to CRTC1, SEQ1, GRPH1, ATB1, ??? */
280			CRTCW(OWNER, 0x00);
281		}
282		else
283		{
284			/* note: 'OWNER' is a non-standard register in behaviour(!) on NV11's,
285			 * while non-NV11 cards behave normally.
286			 *
287			 * Double-write action needed on those strange NV11 cards: */
288			/* RESET: needed on NV11 */
289			CRTC2W(OWNER, 0xff);
290			/* enable access to CRTC2, SEQ2, GRPH2, ATB2, ??? */
291			CRTC2W(OWNER, 0x03);
292		}
293	}
294}
295
296static status_t engxx_general_powerup()
297{
298	LOG(4, ("INIT: card powerup\n"));
299
300	/* setup cardspecs */
301	/* note:
302	 * this MUST be done before the driver attempts a card coldstart */
303	set_specs();
304
305	/* only process BIOS for finetuning specs and coldstarting card if requested
306	 * by the user;
307	 * note:
308	 * this in fact frees the driver from relying on the BIOS to be executed
309	 * at system power-up POST time. */
310	if (!si->settings.usebios)
311	{
312		LOG(2, ("INIT: Attempting card coldstart!\n"));
313		/* update the cardspecs in the shared_info PINS struct according to reported
314		 * specs as much as is possible;
315		 * this also coldstarts the card if possible (executes BIOS CMD script(s)) */
316//		parse_pins();
317	}
318	else
319	{
320		LOG(2, ("INIT: Skipping card coldstart!\n"));
321	}
322
323	/* get RAM size and fake panel startup (panel init code is still missing) */
324	fake_panel_start();
325
326	/* log the final card specifications */
327	dump_pins();
328
329	/* dump config space as it is after a possible coldstart attempt */
330	if (si->settings.logmask & 0x80000000) eng_dump_configuration_space();
331
332	/* setup CRTC and DAC functions access: determined in fake_panel_start */
333	setup_virtualized_heads(si->ps.crtc2_prim);
334
335	/* do powerup needed from pre-inited card state as done by system POST cardBIOS
336	 * execution or driver coldstart above */
337	return eng_general_bios_to_powergraphics();
338}
339
340/* this routine switches the CRTC/DAC sets to 'connectors', but only for analog
341 * outputs. We need this to make sure the analog 'switch' is set in the same way the
342 * digital 'switch' is set by the BIOS or we might not be able to use dualhead. */
343status_t eng_general_output_select(bool cross)
344{
345	/* make sure this call is warranted */
346	if (si->ps.secondary_head)
347	{
348		/* NV11 cards can't switch heads (confirmed) */
349		if (si->ps.card_type != NV11)
350		{
351			if (cross)
352			{
353				LOG(4,("INIT: switching analog outputs to be cross-connected\n"));
354
355				/* enable head 2 on connector 1 */
356				/* (b8 = select CRTC (head) for output,
357				 *  b4 = ??? (confirmed not to be a FP switch),
358				 *  b0 = enable CRT) */
359				DACW(OUTPUT, 0x00000101);
360				/* enable head 1 on connector 2 */
361				DAC2W(OUTPUT, 0x00000001);
362			}
363			else
364			{
365				LOG(4,("INIT: switching analog outputs to be straight-through\n"));
366
367				/* enable head 1 on connector 1 */
368				DACW(OUTPUT, 0x00000001);
369				/* enable head 2 on connector 2 */
370				DAC2W(OUTPUT, 0x00000101);
371			}
372		}
373		else
374		{
375			LOG(4,("INIT: NV11 analog outputs are hardwired to be straight-through\n"));
376		}
377		return B_OK;
378	}
379	else
380	{
381		return B_ERROR;
382	}
383}
384
385/* this routine switches CRTC/DAC set use. We need this because it's unknown howto
386 * switch digital panels to/from a specific CRTC/DAC set. */
387status_t eng_general_head_select(bool cross)
388{
389	/* make sure this call is warranted */
390	if (si->ps.secondary_head)
391	{
392		/* invert CRTC/DAC use to do switching */
393		if (cross)
394		{
395			LOG(4,("INIT: switching CRTC/DAC use to be cross-connected\n"));
396			si->crtc_switch_mode = !si->ps.crtc2_prim;
397		}
398		else
399		{
400			LOG(4,("INIT: switching CRTC/DAC use to be straight-through\n"));
401			si->crtc_switch_mode = si->ps.crtc2_prim;
402		}
403		/* update CRTC and DAC functions access */
404		setup_virtualized_heads(si->crtc_switch_mode);
405
406		return B_OK;
407	}
408	else
409	{
410		return B_ERROR;
411	}
412}
413
414/* basic change of card state from VGA to enhanced mode:
415 * Should work from VGA BIOS POST init state. */
416static status_t eng_general_bios_to_powergraphics()
417{
418	/* let acc engine make power off/power on cycle to start 'fresh' */
419//	ENG_RG32(RG32_PWRUPCTRL) = 0x13110011;
420	snooze(1000);
421
422	/* power-up all hardware function blocks */
423	/* bit 28: OVERLAY ENGINE (BES),
424	 * bit 25: CRTC2, (> NV04A)
425	 * bit 24: CRTC1,
426	 * bit 20: framebuffer,
427	 * bit 16: PPMI,
428	 * bit 12: PGRAPH,
429	 * bit  8: PFIFO,
430	 * bit  4: PMEDIA,
431	 * bit  0: TVOUT. (> NV04A) */
432//	ENG_RG32(RG32_PWRUPCTRL) = 0x13111111;
433
434	/* select colormode CRTC registers base adresses */
435//	ENG_REG8(RG8_MISCW) = 0xcb;
436
437	/* enable access to primary head */
438//	set_crtc_owner(0);
439	/* unlock head's registers for R/W access */
440//	CRTCW(LOCK, 0x57);
441//	CRTCW(VSYNCE ,(CRTCR(VSYNCE) & 0x7f));
442//	if (si->ps.secondary_head)
443	if (0)
444	{
445		/* enable access to secondary head */
446		set_crtc_owner(1);
447		/* unlock head's registers for R/W access */
448		CRTC2W(LOCK, 0x57);
449		CRTC2W(VSYNCE ,(CRTCR(VSYNCE) & 0x7f));
450	}
451
452	/* turn off both displays and the hardcursors (also disables transfers) */
453//	head1_dpms(false, false, false);
454//	head1_cursor_hide();
455//	if (si->ps.secondary_head)
456	if (0)
457	{
458//		head2_dpms(false, false, false);
459//		head2_cursor_hide();
460	}
461
462//	if (si->ps.secondary_head)
463	if (0)
464	{
465		/* switch overlay engine to CRTC1 */
466		/* bit 17: GPU FP port #1	(confirmed NV25, NV28, confirmed not on NV34),
467		 * bit 16: GPU FP port #2	(confirmed NV25, NV28, NV34),
468		 * bit 12: overlay engine	(all cards),
469		 * bit  9: TVout chip #2	(confirmed on NV18, NV25, NV28),
470		 * bit  8: TVout chip #1	(all cards),
471		 * bit  4: both I2C busses	(all cards) */
472		ENG_RG32(RG32_2FUNCSEL) &= ~0x00001000;
473		ENG_RG32(RG32_FUNCSEL) |= 0x00001000;
474	}
475	si->overlay.crtc = false;
476
477	/* enable 'enhanced' mode on primary head: */
478	/* enable access to primary head */
479//	set_crtc_owner(0);
480	/* note: 'BUFFER' is a non-standard register in behaviour(!) on most
481	 * NV11's like the GeForce2 MX200, while the MX400 and non-NV11 cards
482	 * behave normally.
483	 * Also readback is not nessesarily what was written before!
484	 *
485	 * Double-write action needed on those strange NV11 cards: */
486	/* RESET: don't doublebuffer CRTC access: set programmed values immediately... */
487//	CRTCW(BUFFER, 0xff);
488	/* ... and use fine pitched CRTC granularity on > NV4 cards (b2 = 0) */
489	/* note: this has no effect on possible bandwidth issues. */
490//	CRTCW(BUFFER, 0xfb);
491	/* select VGA mode (old VGA register) */
492//	CRTCW(MODECTL, 0xc3);
493	/* select graphics mode (old VGA register) */
494//	SEQW(MEMMODE, 0x0e);
495	/* select 8 dots character clocks (old VGA register) */
496//	SEQW(CLKMODE, 0x21);
497	/* select VGA mode (old VGA register) */
498//	GRPHW(MODE, 0x00);
499	/* select graphics mode (old VGA register) */
500//	GRPHW(MISC, 0x01);
501	/* select graphics mode (old VGA register) */
502//	ATBW(MODECTL, 0x01);
503	/* enable 'enhanced mode', enable Vsync & Hsync,
504	 * set DAC palette to 8-bit width, disable large screen */
505//	CRTCW(REPAINT1, 0x04);
506
507	/* enable 'enhanced' mode on secondary head: */
508//	if (si->ps.secondary_head)
509	if (0)
510	{
511		/* enable access to secondary head */
512		set_crtc_owner(1);
513		/* select colormode CRTC2 registers base adresses */
514		ENG_REG8(RG8_MISCW) = 0xcb;
515		/* note: 'BUFFER' is a non-standard register in behaviour(!) on most
516		 * NV11's like the GeForce2 MX200, while the MX400 and non-NV11 cards
517		 * behave normally.
518		 * Also readback is not nessesarily what was written before!
519		 *
520		 * Double-write action needed on those strange NV11 cards: */
521		/* RESET: don't doublebuffer CRTC2 access: set programmed values immediately... */
522		CRTC2W(BUFFER, 0xff);
523		/* ... and use fine pitched CRTC granularity on > NV4 cards (b2 = 0) */
524		/* note: this has no effect on possible bandwidth issues. */
525		CRTC2W(BUFFER, 0xfb);
526		/* select VGA mode (old VGA register) */
527		CRTC2W(MODECTL, 0xc3);
528		/* select graphics mode (old VGA register) */
529		SEQW(MEMMODE, 0x0e);
530		/* select 8 dots character clocks (old VGA register) */
531		SEQW(CLKMODE, 0x21);
532		/* select VGA mode (old VGA register) */
533		GRPHW(MODE, 0x00);
534		/* select graphics mode (old VGA register) */
535		GRPHW(MISC, 0x01);
536		/* select graphics mode (old VGA register) */
537		ATB2W(MODECTL, 0x01);
538		/* enable 'enhanced mode', enable Vsync & Hsync,
539		 * set DAC palette to 8-bit width, disable large screen */
540		CRTC2W(REPAINT1, 0x04);
541	}
542
543	/* enable palettes */
544//	DACW(GENCTRL, 0x00100100);
545//	if (si->ps.secondary_head) DAC2W(GENCTRL, 0x00100100);
546
547	/* enable programmable PLLs */
548//	DACW(PLLSEL, 0x10000700);
549//	if (si->ps.secondary_head) DACW(PLLSEL, (DACR(PLLSEL) | 0x20000800));
550
551	/* turn on DAC and make sure detection testsignal routing is disabled
552	 * (b16 = disable DAC,
553	 *  b12 = enable testsignal output */
554//	DACW(TSTCTRL, (DACR(TSTCTRL) & 0xfffeefff));
555	/* turn on DAC2 if it exists
556	 * (NOTE: testsignal function block resides in DAC1 only (!)) */
557//	if (si->ps.secondary_head) DAC2W(TSTCTRL, (DAC2R(TSTCTRL) & 0xfffeefff));
558
559	/* setup AGP:
560	 * Note:
561	 * This may only be done when no transfers are in progress on the bus, so now
562	 * is probably a good time.. */
563	eng_agp_setup();
564
565	/* turn screen one on */
566//	head1_dpms(true, true, true);
567
568	return B_OK;
569}
570
571/* Check if mode virtual_size adheres to the cards _maximum_ contraints, and modify
572 * virtual_size to the nearest valid maximum for the mode on the card if not so.
573 * Also: check if virtual_width adheres to the cards granularity constraints, and
574 * create mode slopspace if not so.
575 * We use acc or crtc granularity constraints based on the 'worst case' scenario.
576 *
577 * Mode slopspace is reflected in fbc->bytes_per_row BTW. */
578status_t eng_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode)
579{
580	uint32 video_pitch;
581	uint32 acc_mask, crtc_mask;
582	uint32 max_crtc_width, max_acc_width;
583	uint8 depth = 8;
584
585	/* determine pixel multiple based on 2D/3D engine constraints */
586	switch (si->ps.card_arch)
587	{
588	default:
589		/* confirmed for:
590		 * TNT1, TNT2, TNT2-M64, GeForce2 MX400, GeForce4 MX440, GeForceFX 5200 */
591		switch (target->space)
592		{
593			case B_CMAP8: acc_mask = 0x0f; depth =  8; break;
594			case B_RGB15: acc_mask = 0x07; depth = 16; break;
595			case B_RGB16: acc_mask = 0x07; depth = 16; break;
596			case B_RGB24: acc_mask = 0x0f; depth = 24; break;
597			case B_RGB32: acc_mask = 0x03; depth = 32; break;
598			default:
599				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
600				return B_ERROR;
601		}
602		/* NV31 (confirmed GeForceFX 5600) has NV20A granularity!
603		 * So let it fall through... */
604		if (si->ps.card_type != NV31) break;
605	case NV20A:
606		/* confirmed for:
607		 * GeForce4 Ti4200 */
608		switch (target->space)
609		{
610			case B_CMAP8: acc_mask = 0x3f; depth =  8; break;
611			case B_RGB15: acc_mask = 0x1f; depth = 16; break;
612			case B_RGB16: acc_mask = 0x1f; depth = 16; break;
613			case B_RGB24: acc_mask = 0x3f; depth = 24; break;
614			case B_RGB32: acc_mask = 0x0f; depth = 32; break;
615			default:
616				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
617				return B_ERROR;
618		}
619		break;
620	}
621
622	/* determine pixel multiple based on CRTC memory pitch constraints:
623	 * -> all NV cards have same granularity constraints on CRTC1 and CRTC2,
624	 *    provided that the CRTC1 and CRTC2 BUFFER register b2 = 0;
625	 *
626	 * (Note: Don't mix this up with CRTC timing contraints! Those are
627	 *        multiples of 8 for horizontal, 1 for vertical timing.) */
628	switch (si->ps.card_type)
629	{
630	default:
631//	case NV04:
632		/* confirmed for:
633		 * TNT1 always;
634		 * TNT2, TNT2-M64, GeForce2 MX400, GeForce4 MX440, GeForce4 Ti4200,
635		 * GeForceFX 5200: if the CRTC1 (and CRTC2) BUFFER register b2 = 0 */
636		/* NOTE:
637		 * Unfortunately older cards have a hardware fault that prevents use.
638		 * We need doubled granularity on those to prevent the single top line
639		 * from shifting to the left!
640		 * This is confirmed for TNT2, GeForce2 MX200, GeForce2 MX400.
641		 * Confirmed OK are:
642		 * GeForce4 MX440, GeForce4 Ti4200, GeForceFX 5200. */
643		switch (target->space)
644		{
645			case B_CMAP8: crtc_mask = 0x0f; break; /* 0x07 */
646			case B_RGB15: crtc_mask = 0x07; break; /* 0x03 */
647			case B_RGB16: crtc_mask = 0x07; break; /* 0x03 */
648			case B_RGB24: crtc_mask = 0x0f; break; /* 0x07 */
649			case B_RGB32: crtc_mask = 0x03; break; /* 0x01 */
650			default:
651				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
652				return B_ERROR;
653		}
654		break;
655//	default:
656		/* confirmed for:
657		 * TNT2, TNT2-M64, GeForce2 MX400, GeForce4 MX440, GeForce4 Ti4200,
658		 * GeForceFX 5200: if the CRTC1 (and CRTC2) BUFFER register b2 = 1 */
659/*		switch (target->space)
660		{
661			case B_CMAP8: crtc_mask = 0x1f; break;
662			case B_RGB15: crtc_mask = 0x0f; break;
663			case B_RGB16: crtc_mask = 0x0f; break;
664			case B_RGB24: crtc_mask = 0x1f; break;
665			case B_RGB32: crtc_mask = 0x07; break;
666			default:
667				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
668				return B_ERROR;
669		}
670		break;
671*/	}
672
673	/* set virtual_width limit for accelerated modes */
674	switch (si->ps.card_arch)
675	{
676	case NV04A:
677		/* confirmed for:
678		 * TNT1, TNT2, TNT2-M64 */
679		switch(target->space)
680		{
681			case B_CMAP8: max_acc_width = 8176; break;
682			case B_RGB15: max_acc_width = 4088; break;
683			case B_RGB16: max_acc_width = 4088; break;
684			case B_RGB24: max_acc_width = 2720; break;
685			case B_RGB32: max_acc_width = 2044; break;
686			default:
687				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
688				return B_ERROR;
689		}
690		break;
691	default:
692		/* confirmed for:
693		 * GeForce2 MX400, GeForce4 MX440, GeForceFX 5200 */
694		switch(target->space)
695		{
696			case B_CMAP8: max_acc_width = 16368; break;
697			case B_RGB15: max_acc_width =  8184; break;
698			case B_RGB16: max_acc_width =  8184; break;
699			case B_RGB24: max_acc_width =  5456; break;
700			case B_RGB32: max_acc_width =  4092; break;
701			default:
702				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
703				return B_ERROR;
704		}
705		/* NV31 (confirmed GeForceFX 5600) has NV20A granularity!
706		 * So let it fall through... */
707		if (si->ps.card_type != NV31) break;
708	case NV20A:
709		/* confirmed for:
710		 * GeForce4 Ti4200 */
711		switch(target->space)
712		{
713			case B_CMAP8: max_acc_width = 16320; break;
714			case B_RGB15: max_acc_width =  8160; break;
715			case B_RGB16: max_acc_width =  8160; break;
716			case B_RGB24: max_acc_width =  5440; break;
717			case B_RGB32: max_acc_width =  4080; break;
718			default:
719				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
720				return B_ERROR;
721		}
722		break;
723	}
724
725	/* set virtual_width limit for unaccelerated modes */
726	switch (si->ps.card_type)
727	{
728	default:
729//	case NV04:
730		/* confirmed for:
731		 * TNT1 always;
732		 * TNT2, TNT2-M64, GeForce2 MX400, GeForce4 MX440, GeForce4 Ti4200,
733		 * GeForceFX 5200: if the CRTC1 (and CRTC2) BUFFER register b2 = 0 */
734		/* NOTE:
735		 * Unfortunately older cards have a hardware fault that prevents use.
736		 * We need doubled granularity on those to prevent the single top line
737		 * from shifting to the left!
738		 * This is confirmed for TNT2, GeForce2 MX200, GeForce2 MX400.
739		 * Confirmed OK are:
740		 * GeForce4 MX440, GeForce4 Ti4200, GeForceFX 5200. */
741		switch(target->space)
742		{
743			case B_CMAP8: max_crtc_width = 16368; break; /* 16376 */
744			case B_RGB15: max_crtc_width =  8184; break; /*  8188 */
745			case B_RGB16: max_crtc_width =  8184; break; /*  8188 */
746			case B_RGB24: max_crtc_width =  5456; break; /*  5456 */
747			case B_RGB32: max_crtc_width =  4092; break; /*  4094 */
748			default:
749				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
750				return B_ERROR;
751		}
752		break;
753//	default:
754		/* confirmed for:
755		 * TNT2, TNT2-M64, GeForce2 MX400, GeForce4 MX440, GeForce4 Ti4200,
756		 * GeForceFX 5200: if the CRTC1 (and CRTC2) BUFFER register b2 = 1 */
757/*		switch(target->space)
758		{
759			case B_CMAP8: max_crtc_width = 16352; break;
760			case B_RGB15: max_crtc_width =  8176; break;
761			case B_RGB16: max_crtc_width =  8176; break;
762			case B_RGB24: max_crtc_width =  5440; break;
763			case B_RGB32: max_crtc_width =  4088; break;
764			default:
765				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
766				return B_ERROR;
767		}
768		break;
769*/	}
770
771	/* check for acc capability, and adjust mode to adhere to hardware constraints */
772	if (max_acc_width <= max_crtc_width)
773	{
774		/* check if we can setup this mode with acceleration */
775//		*acc_mode = true;
776//blocking acc totally:
777*acc_mode = false;
778		/* virtual_width */
779		if (target->virtual_width > max_acc_width) *acc_mode = false;
780		/* virtual_height */
781		/* (NV cards can even do more than this(?)...
782		 *  but 4096 is confirmed on all cards at max. accelerated width.) */
783		if (target->virtual_height > 4096) *acc_mode = false;
784
785		/* now check virtual_size based on CRTC constraints */
786		if (target->virtual_width > max_crtc_width) target->virtual_width = max_crtc_width;
787		/* virtual_height: The only constraint here is the cards memory size which is
788		 * checked later on in ProposeMode: virtual_height is adjusted then if needed.
789		 * 'Limiting here' to the variable size that's at least available (uint16). */
790		if (target->virtual_height > 65535) target->virtual_height = 65535;
791
792		/* OK, now we know that virtual_width is valid, and it's needing no slopspace if
793		 * it was confined above, so we can finally calculate safely if we need slopspace
794		 * for this mode... */
795		if (*acc_mode)
796		{
797			/* the mode needs to adhere to the largest granularity imposed... */
798			if (acc_mask < crtc_mask)
799				video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
800			else
801				video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask);
802		}
803		else /* unaccelerated mode */
804			video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
805	}
806	else /* max_acc_width > max_crtc_width */
807	{
808		/* check if we can setup this mode with acceleration */
809		*acc_mode = true;
810		/* (we already know virtual_width will be no problem) */
811		/* virtual_height */
812		/* (NV cards can even do more than this(?)...
813		 *  but 4096 is confirmed on all cards at max. accelerated width.) */
814		if (target->virtual_height > 4096) *acc_mode = false;
815
816		/* now check virtual_size based on CRTC constraints */
817		if (*acc_mode)
818		{
819			/* note that max_crtc_width already adheres to crtc_mask */
820			if (target->virtual_width > (max_crtc_width & ~acc_mask))
821					target->virtual_width = (max_crtc_width & ~acc_mask);
822		}
823		else /* unaccelerated mode */
824		{
825			if (target->virtual_width > max_crtc_width)
826					target->virtual_width = max_crtc_width;
827		}
828		/* virtual_height: The only constraint here is the cards memory size which is
829		 * checked later on in ProposeMode: virtual_height is adjusted then if needed.
830		 * 'Limiting here' to the variable size that's at least available (uint16). */
831		if (target->virtual_height > 65535) target->virtual_height = 65535;
832
833		/* OK, now we know that virtual_width is valid, and it's needing no slopspace if
834		 * it was confined above, so we can finally calculate safely if we need slopspace
835		 * for this mode... */
836		if (*acc_mode)
837		{
838			/* the mode needs to adhere to the largest granularity imposed... */
839			if (acc_mask < crtc_mask)
840				video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
841			else
842				video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask);
843		}
844		else /* unaccelerated mode */
845			video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
846	}
847
848	LOG(2,("INIT: memory pitch will be set to %d pixels for colorspace 0x%08x\n",
849														video_pitch, target->space));
850	if (target->virtual_width != video_pitch)
851		LOG(2,("INIT: effective mode slopspace is %d pixels\n",
852											(video_pitch - target->virtual_width)));
853
854	/* now calculate bytes_per_row for this mode */
855	*bytes_per_row = video_pitch * (depth >> 3);
856
857	return B_OK;
858}
859