xref: /haiku/src/add-ons/accelerants/skeleton/engine/general.c (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
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 
11 static status_t test_ram(void);
12 static status_t engxx_general_powerup (void);
13 static status_t eng_general_bios_to_powergraphics(void);
14 
15 static 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 
89 status_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 
116 static 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) */
150 status_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 
187 void 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 
267 void 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 
296 static 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. */
343 status_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. */
387 status_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. */
416 static 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. */
578 status_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