xref: /haiku/src/add-ons/accelerants/via/engine/general.c (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
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 VIA Accelerant 0.16 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 0x30221106:
103 		si->ps.card_type = CLE3022;
104 		si->ps.card_arch = CLE266;
105 		LOG(4,("POWERUP: Detected VIA CLE266 Unichrome Pro (CLE3022)\n"));
106 		status = engxx_general_powerup();
107 		break;
108 	case 0x31081106:
109 		//fixme: card_type unknown..
110 		si->ps.card_type = VT3204;
111 		si->ps.card_arch = K8M800;
112 		LOG(4,("POWERUP: Detected VIA K8M800 Unichrome Pro (unknown chiptype)\n"));
113 		status = engxx_general_powerup();
114 		break;
115 	case 0x31221106:
116 		si->ps.card_type = CLE3122;
117 		si->ps.card_arch = CLE266;
118 		LOG(4,("POWERUP: Detected VIA CLE266 Unichrome Pro (CLE3122)\n"));
119 		status = engxx_general_powerup();
120 		break;
121 	case 0x32041106:
122 		si->ps.card_type = VT3204;
123 		si->ps.card_arch = K8M800;
124 		LOG(4,("POWERUP: Detected VIA K8M800 Unichrome Pro (VT3204)\n"));
125 		status = engxx_general_powerup();
126 		break;
127 	case 0x32051106:
128 		si->ps.card_type = VT3205;
129 		si->ps.card_arch = KM400;
130 		LOG(4,("POWERUP: Detected VIA KM400 Unichrome (VT3205)\n"));
131 		status = engxx_general_powerup();
132 		break;
133 	case 0x72041106:
134 		si->ps.card_type = VT7204;
135 		si->ps.card_arch = K8M800;
136 		LOG(4,("POWERUP: Detected VIA K8M800 Unichrome Pro (VT7204)\n"));
137 		status = engxx_general_powerup();
138 		break;
139 	case 0x72051106:
140 		si->ps.card_type = VT7205;
141 		si->ps.card_arch = KM400;
142 		LOG(4,("POWERUP: Detected VIA KM400 Unichrome (VT7205)\n"));
143 		status = engxx_general_powerup();
144 		break;
145 	default:
146 		LOG(8,("POWERUP: Failed to detect valid card 0x%08x\n",CFGR(DEVID)));
147 		return B_ERROR;
148 	}
149 
150 	return status;
151 }
152 
153 static status_t test_ram()
154 {
155 	uint32 value, offset;
156 	status_t result = B_OK;
157 
158 	/* make sure we don't corrupt the hardware cursor by using fbc.frame_buffer. */
159 	if (si->fbc.frame_buffer == NULL)
160 	{
161 		LOG(8,("INIT: test_ram detected NULL pointer.\n"));
162 		return B_ERROR;
163 	}
164 
165 	for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
166 	{
167 		/* write testpattern to cardRAM */
168 		((uint32 *)si->fbc.frame_buffer)[offset] = value;
169 		/* toggle testpattern */
170 		value = 0xffffffff - value;
171 	}
172 
173 	for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
174 	{
175 		/* readback and verify testpattern from cardRAM */
176 		if (((uint32 *)si->fbc.frame_buffer)[offset] != value) result = B_ERROR;
177 		/* toggle testpattern */
178 		value = 0xffffffff - value;
179 	}
180 	return result;
181 }
182 
183 /* NOTE:
184  * This routine *has* to be done *after* SetDispplayMode has been executed,
185  * or test results will not be representative!
186  * (CAS latency is dependant on NV setup on some (DRAM) boards) */
187 status_t eng_set_cas_latency()
188 {
189 	status_t result = B_ERROR;
190 	uint8 latency = 0;
191 
192 	/* check current RAM access to see if we need to change anything */
193 	if (test_ram() == B_OK)
194 	{
195 		LOG(4,("INIT: RAM access OK.\n"));
196 		return B_OK;
197 	}
198 
199 	/* check if we read PINS at starttime so we have valid registersettings at our disposal */
200 	if (si->ps.pins_status != B_OK)
201 	{
202 		LOG(4,("INIT: RAM access errors; not fixable: PINS was not read from cardBIOS.\n"));
203 		return B_ERROR;
204 	}
205 
206 	/* OK. We might have a problem, try to fix it now.. */
207 	LOG(4,("INIT: RAM access errors; tuning CAS latency if prudent...\n"));
208 
209 	switch(si->ps.card_type)
210 	{
211 	default:
212 			LOG(4,("INIT: RAM CAS tuning not implemented for this card, aborting.\n"));
213 			return B_OK;
214 			break;
215 	}
216 	if (result == B_OK)
217 		LOG(4,("INIT: RAM access OK. CAS latency set to %d cycles.\n", latency));
218 	else
219 		LOG(4,("INIT: RAM access not fixable. CAS latency set to %d cycles.\n", latency));
220 
221 	return result;
222 }
223 
224 void setup_virtualized_heads(bool cross)
225 {
226 	if (cross)
227 	{
228 		head1_validate_timing	= (crtc_validate_timing)	eng_crtc2_validate_timing;
229 		head1_set_timing		= (crtc_set_timing)			eng_crtc2_set_timing;
230 		head1_depth				= (crtc_depth)				eng_crtc2_depth;
231 		head1_dpms				= (crtc_dpms)				eng_crtc2_dpms;
232 		head1_dpms_fetch		= (crtc_dpms_fetch)			eng_crtc2_dpms_fetch;
233 		head1_set_display_pitch	= (crtc_set_display_pitch)	eng_crtc2_set_display_pitch;
234 		head1_set_display_start	= (crtc_set_display_start)	eng_crtc2_set_display_start;
235 		head1_cursor_init		= (crtc_cursor_init)		eng_crtc2_cursor_init;
236 		head1_cursor_show		= (crtc_cursor_show)		eng_crtc2_cursor_show;
237 		head1_cursor_hide		= (crtc_cursor_hide)		eng_crtc2_cursor_hide;
238 		head1_cursor_define		= (crtc_cursor_define)		eng_crtc2_cursor_define;
239 		head1_cursor_position	= (crtc_cursor_position)	eng_crtc2_cursor_position;
240 
241 		head1_mode				= (dac_mode)				eng_dac2_mode;
242 		head1_palette			= (dac_palette)				eng_dac2_palette;
243 		head1_set_pix_pll		= (dac_set_pix_pll)			eng_dac2_set_pix_pll;
244 		head1_pix_pll_find		= (dac_pix_pll_find)		eng_dac2_pix_pll_find;
245 
246 		head2_validate_timing	= (crtc_validate_timing)	eng_crtc_validate_timing;
247 		head2_set_timing		= (crtc_set_timing)			eng_crtc_set_timing;
248 		head2_depth				= (crtc_depth)				eng_crtc_depth;
249 		head2_dpms				= (crtc_dpms)				eng_crtc_dpms;
250 		head2_dpms_fetch		= (crtc_dpms_fetch)			eng_crtc_dpms_fetch;
251 		head2_set_display_pitch	= (crtc_set_display_pitch)	eng_crtc_set_display_pitch;
252 		head2_set_display_start	= (crtc_set_display_start)	eng_crtc_set_display_start;
253 		head2_cursor_init		= (crtc_cursor_init)		eng_crtc_cursor_init;
254 		head2_cursor_show		= (crtc_cursor_show)		eng_crtc_cursor_show;
255 		head2_cursor_hide		= (crtc_cursor_hide)		eng_crtc_cursor_hide;
256 		head2_cursor_define		= (crtc_cursor_define)		eng_crtc_cursor_define;
257 		head2_cursor_position	= (crtc_cursor_position)	eng_crtc_cursor_position;
258 
259 		head2_mode				= (dac_mode)				eng_dac_mode;
260 		head2_palette			= (dac_palette)				eng_dac_palette;
261 		head2_set_pix_pll		= (dac_set_pix_pll)			eng_dac_set_pix_pll;
262 		head2_pix_pll_find		= (dac_pix_pll_find)		eng_dac_pix_pll_find;
263 	}
264 	else
265 	{
266 		head1_validate_timing	= (crtc_validate_timing)	eng_crtc_validate_timing;
267 		head1_set_timing		= (crtc_set_timing)			eng_crtc_set_timing;
268 		head1_depth				= (crtc_depth)				eng_crtc_depth;
269 		head1_dpms				= (crtc_dpms)				eng_crtc_dpms;
270 		head1_dpms_fetch		= (crtc_dpms_fetch)			eng_crtc_dpms_fetch;
271 		head1_set_display_pitch	= (crtc_set_display_pitch)	eng_crtc_set_display_pitch;
272 		head1_set_display_start	= (crtc_set_display_start)	eng_crtc_set_display_start;
273 		head1_cursor_init		= (crtc_cursor_init)		eng_crtc_cursor_init;
274 		head1_cursor_show		= (crtc_cursor_show)		eng_crtc_cursor_show;
275 		head1_cursor_hide		= (crtc_cursor_hide)		eng_crtc_cursor_hide;
276 		head1_cursor_define		= (crtc_cursor_define)		eng_crtc_cursor_define;
277 		head1_cursor_position	= (crtc_cursor_position)	eng_crtc_cursor_position;
278 
279 		head1_mode				= (dac_mode)				eng_dac_mode;
280 		head1_palette			= (dac_palette)				eng_dac_palette;
281 		head1_set_pix_pll		= (dac_set_pix_pll)			eng_dac_set_pix_pll;
282 		head1_pix_pll_find		= (dac_pix_pll_find)		eng_dac_pix_pll_find;
283 
284 		head2_validate_timing	= (crtc_validate_timing)	eng_crtc2_validate_timing;
285 		head2_set_timing		= (crtc_set_timing)			eng_crtc2_set_timing;
286 		head2_depth				= (crtc_depth)				eng_crtc2_depth;
287 		head2_dpms				= (crtc_dpms)				eng_crtc2_dpms;
288 		head2_dpms_fetch		= (crtc_dpms_fetch)			eng_crtc2_dpms_fetch;
289 		head2_set_display_pitch	= (crtc_set_display_pitch)	eng_crtc2_set_display_pitch;
290 		head2_set_display_start	= (crtc_set_display_start)	eng_crtc2_set_display_start;
291 		head2_cursor_init		= (crtc_cursor_init)		eng_crtc2_cursor_init;
292 		head2_cursor_show		= (crtc_cursor_show)		eng_crtc2_cursor_show;
293 		head2_cursor_hide		= (crtc_cursor_hide)		eng_crtc2_cursor_hide;
294 		head2_cursor_define		= (crtc_cursor_define)		eng_crtc2_cursor_define;
295 		head2_cursor_position	= (crtc_cursor_position)	eng_crtc2_cursor_position;
296 
297 		head2_mode				= (dac_mode)				eng_dac2_mode;
298 		head2_palette			= (dac_palette)				eng_dac2_palette;
299 		head2_set_pix_pll		= (dac_set_pix_pll)			eng_dac2_set_pix_pll;
300 		head2_pix_pll_find		= (dac_pix_pll_find)		eng_dac2_pix_pll_find;
301 	}
302 }
303 
304 void set_crtc_owner(bool head)
305 {
306 	if (si->ps.secondary_head)
307 	{
308 		if (!head)
309 		{
310 			/* note: 'OWNER' is a non-standard register in behaviour(!) on NV11's,
311 			 * while non-NV11 cards behave normally.
312 			 *
313 			 * Double-write action needed on those strange NV11 cards: */
314 			/* RESET: needed on NV11 */
315 			CRTCW(OWNER, 0xff);
316 			/* enable access to CRTC1, SEQ1, GRPH1, ATB1, ??? */
317 			CRTCW(OWNER, 0x00);
318 		}
319 		else
320 		{
321 			/* note: 'OWNER' is a non-standard register in behaviour(!) on NV11's,
322 			 * while non-NV11 cards behave normally.
323 			 *
324 			 * Double-write action needed on those strange NV11 cards: */
325 			/* RESET: needed on NV11 */
326 			CRTC2W(OWNER, 0xff);
327 			/* enable access to CRTC2, SEQ2, GRPH2, ATB2, ??? */
328 			CRTC2W(OWNER, 0x03);
329 		}
330 	}
331 }
332 
333 static status_t engxx_general_powerup()
334 {
335 	LOG(4,("POWERUP: Chip revision is $%02x\n", si->ps.chip_rev));
336 	LOG(4, ("INIT: card powerup\n"));
337 
338 	/* setup cardspecs */
339 	/* note:
340 	 * this MUST be done before the driver attempts a card coldstart */
341 	set_specs();
342 
343 	/* only process BIOS for finetuning specs and coldstarting card if requested
344 	 * by the user;
345 	 * note:
346 	 * this in fact frees the driver from relying on the BIOS to be executed
347 	 * at system power-up POST time. */
348 	if (!si->settings.usebios)
349 	{
350 		LOG(2, ("INIT: Attempting card coldstart!\n"));
351 		/* update the cardspecs in the shared_info PINS struct according to reported
352 		 * specs as much as is possible;
353 		 * this also coldstarts the card if possible (executes BIOS CMD script(s)) */
354 //		parse_pins();
355 	}
356 	else
357 	{
358 		LOG(2, ("INIT: Skipping card coldstart!\n"));
359 	}
360 
361 	/* get RAM size and fake panel startup (panel init code is still missing) */
362 	fake_panel_start();
363 
364 	/* log the final card specifications */
365 	dump_pins();
366 
367 	/* dump config space as it is after a possible coldstart attempt */
368 	if (si->settings.logmask & 0x80000000) eng_dump_configuration_space();
369 
370 	/* setup CRTC and DAC functions access: determined in fake_panel_start */
371 	setup_virtualized_heads(si->ps.crtc2_prim);
372 
373 	/* do powerup needed from pre-inited card state as done by system POST cardBIOS
374 	 * execution or driver coldstart above */
375 	return eng_general_bios_to_powergraphics();
376 }
377 
378 /* this routine switches the CRTC/DAC sets to 'connectors', but only for analog
379  * outputs. We need this to make sure the analog 'switch' is set in the same way the
380  * digital 'switch' is set by the BIOS or we might not be able to use dualhead. */
381 status_t eng_general_output_select(bool cross)
382 {
383 	/* make sure this call is warranted */
384 	if (si->ps.secondary_head)
385 	{
386 		/* NV11 cards can't switch heads (confirmed) */
387 		if (si->ps.card_type != NV11)
388 		{
389 			if (cross)
390 			{
391 				LOG(4,("INIT: switching analog outputs to be cross-connected\n"));
392 
393 				/* enable head 2 on connector 1 */
394 				/* (b8 = select CRTC (head) for output,
395 				 *  b4 = ??? (confirmed not to be a FP switch),
396 				 *  b0 = enable CRT) */
397 				DACW(OUTPUT, 0x00000101);
398 				/* enable head 1 on connector 2 */
399 				DAC2W(OUTPUT, 0x00000001);
400 			}
401 			else
402 			{
403 				LOG(4,("INIT: switching analog outputs to be straight-through\n"));
404 
405 				/* enable head 1 on connector 1 */
406 				DACW(OUTPUT, 0x00000001);
407 				/* enable head 2 on connector 2 */
408 				DAC2W(OUTPUT, 0x00000101);
409 			}
410 		}
411 		else
412 		{
413 			LOG(4,("INIT: NV11 analog outputs are hardwired to be straight-through\n"));
414 		}
415 		return B_OK;
416 	}
417 	else
418 	{
419 		return B_ERROR;
420 	}
421 }
422 
423 /* this routine switches CRTC/DAC set use. We need this because it's unknown howto
424  * switch digital panels to/from a specific CRTC/DAC set. */
425 status_t eng_general_head_select(bool cross)
426 {
427 	/* make sure this call is warranted */
428 	if (si->ps.secondary_head)
429 	{
430 		/* invert CRTC/DAC use to do switching */
431 		if (cross)
432 		{
433 			LOG(4,("INIT: switching CRTC/DAC use to be cross-connected\n"));
434 			si->crtc_switch_mode = !si->ps.crtc2_prim;
435 		}
436 		else
437 		{
438 			LOG(4,("INIT: switching CRTC/DAC use to be straight-through\n"));
439 			si->crtc_switch_mode = si->ps.crtc2_prim;
440 		}
441 		/* update CRTC and DAC functions access */
442 		setup_virtualized_heads(si->crtc_switch_mode);
443 
444 		return B_OK;
445 	}
446 	else
447 	{
448 		return B_ERROR;
449 	}
450 }
451 
452 /* basic change of card state from VGA to enhanced mode:
453  * Should work from VGA BIOS POST init state. */
454 static status_t eng_general_bios_to_powergraphics()
455 {
456 	/* let acc engine make power off/power on cycle to start 'fresh' */
457 //	ENG_REG32(RG32_PWRUPCTRL) = 0x13110011;
458 	snooze(1000);
459 
460 	/* power-up all hardware function blocks */
461 //	ENG_REG32(RG32_PWRUPCTRL) = 0x13111111;
462 
463 	/* select colormode CRTC registers base adresses,
464 	 * but don't touch the current selected pixelclock source yet */
465 	ENG_REG8(RG8_MISCW) = (((ENG_REG8(RG8_MISCR)) & 0x0c) | 0xc3);
466 
467 	/* unlock (extended) registers for R/W access */
468 	SEQW(LOCK, 0x01);
469 	CRTCW(VSYNCE ,(CRTCR(VSYNCE) & 0x7f));
470 
471 	/* turn off both displays and the hardcursors (also disables transfers) */
472 	head1_dpms(false, false, false);
473 	head1_cursor_hide();
474 	if (si->ps.secondary_head)
475 	{
476 //		head2_dpms(false, false, false);
477 //		head2_cursor_hide();
478 	}
479 
480 //	if (si->ps.secondary_head)
481 	if (0)
482 	{
483 		/* switch overlay engine to CRTC1 */
484 		/* bit 17: GPU FP port #1	(confirmed NV25, NV28, confirmed not on NV34),
485 		 * bit 16: GPU FP port #2	(confirmed NV25, NV28, NV34),
486 		 * bit 12: overlay engine	(all cards),
487 		 * bit  9: TVout chip #2	(confirmed on NV18, NV25, NV28),
488 		 * bit  8: TVout chip #1	(all cards),
489 		 * bit  4: both I2C busses	(all cards) */
490 		ENG_REG32(RG32_2FUNCSEL) &= ~0x00001000;
491 		ENG_REG32(RG32_FUNCSEL) |= 0x00001000;
492 	}
493 	si->overlay.crtc = false;
494 
495 	/* set card to 'enhanced' mode: (only VGA standard registers used here) */
496 	/* (keep) card enabled, set plain normal memory usage, no old VGA 'tricks' ... */
497 	CRTCW(MODECTL, 0xc3);
498 	/* ... plain sequential memory use, more than 64Kb RAM installed,
499 	 * switch to graphics mode ... */
500 	SEQW(MEMMODE, 0x0e);
501 	/* ... disable bitplane tweaking ... */
502 	GRPHW(ENSETRESET, 0x00);
503 	/* ... no logical function tweaking with display data, no data rotation ... */
504 	GRPHW(DATAROTATE, 0x00);
505 	/* ... reset read map select to plane 0 ... */
506 	GRPHW(READMAPSEL, 0x00);
507 	/* ... set standard mode ... */
508 	GRPHW(MODE, 0x00);
509 	/* ... ISA framebuffer mapping is 64Kb window, switch to graphics mode (again),
510 	 * select standard adressing ... */
511 	GRPHW(MISC, 0x05);
512 	/* ... disable bit masking ... */
513 	GRPHW(BITMASK, 0xff);
514 	/* ... attributes are in color, switch to graphics mode (again) ... */
515 	ATBW(MODECTL, 0x01);
516 	/* ... set overscan color to black ... */
517 	ATBW(OSCANCOLOR, 0x00);
518 	/* ... enable all color planes ... */
519 	ATBW(COLPLANE_EN, 0x0f);
520 	/* ... reset horizontal pixelpanning ... */
521 	ATBW(HORPIXPAN, 0x00);
522 	/* ...  reset colorpalette groupselect bits ... */
523 	ATBW(COLSEL, 0x00);
524 	/* ... do unknown standard VGA register ... */
525 	ATBW(0x16, 0x01);
526 	/* ... and enable all four byteplanes. */
527 	SEQW(MAPMASK, 0x0f);
528 	/* setup sequencer clocking mode */
529 	SEQW(CLKMODE, 0x21);
530 
531 	/* setup AGP:
532 	 * Note:
533 	 * This may only be done when no transfers are in progress on the bus, so now
534 	 * is probably a good time.. */
535 	eng_agp_setup();
536 
537 	/* turn screen one on */
538 	head1_dpms(true, true, true);
539 
540 	return B_OK;
541 }
542 
543 /* Check if mode virtual_size adheres to the cards _maximum_ contraints, and modify
544  * virtual_size to the nearest valid maximum for the mode on the card if not so.
545  * Also: check if virtual_width adheres to the cards granularity constraints, and
546  * create mode slopspace if not so.
547  * We use acc or crtc granularity constraints based on the 'worst case' scenario.
548  *
549  * Mode slopspace is reflected in fbc->bytes_per_row BTW. */
550 status_t eng_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode)
551 {
552 	uint32 video_pitch;
553 	uint32 acc_mask, crtc_mask;
554 	uint32 max_crtc_width, max_acc_width;
555 	uint8 depth = 8;
556 
557 	/* determine pixel multiple based on 2D/3D engine constraints */
558 //via fixme.
559 	switch (si->ps.card_arch)
560 	{
561 	default:
562 		/* confirmed for:
563 		 * TNT1, TNT2, TNT2-M64, GeForce2 MX400, GeForce4 MX440, GeForceFX 5200 */
564 		switch (target->space)
565 		{
566 			case B_CMAP8: acc_mask = 0x0f; depth =  8; break;
567 			case B_RGB15: acc_mask = 0x07; depth = 16; break;
568 			case B_RGB16: acc_mask = 0x07; depth = 16; break;
569 			case B_RGB24: acc_mask = 0x0f; depth = 24; break;
570 			case B_RGB32: acc_mask = 0x03; depth = 32; break;
571 			default:
572 				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
573 				return B_ERROR;
574 		}
575 		break;
576 	}
577 
578 //via ok:
579 	/* determine pixel multiple based on CRTC memory pitch constraints.
580 	 * (Note: Don't mix this up with CRTC timing contraints! Those are
581 	 *        multiples of 8 for horizontal, 1 for vertical timing.) */
582 	switch (si->ps.card_type)
583 	{
584 	default:
585 		switch (target->space)
586 		{
587 			case B_CMAP8: crtc_mask = 0x07; break;
588 			case B_RGB15: crtc_mask = 0x03; break;
589 			case B_RGB16: crtc_mask = 0x03; break;
590 			case B_RGB24: crtc_mask = 0x07; break;
591 			case B_RGB32: crtc_mask = 0x01; break;
592 			default:
593 				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
594 				return B_ERROR;
595 		}
596 		break;
597 	}
598 
599 	/* set virtual_width limit for accelerated modes */
600 //via fixme:
601 	switch (si->ps.card_arch)
602 	{
603 	case NV04A:
604 		/* confirmed for:
605 		 * TNT1, TNT2, TNT2-M64 */
606 		switch(target->space)
607 		{
608 			case B_CMAP8: max_acc_width = 8176; break;
609 			case B_RGB15: max_acc_width = 4088; break;
610 			case B_RGB16: max_acc_width = 4088; break;
611 			case B_RGB24: max_acc_width = 2720; break;
612 			case B_RGB32: max_acc_width = 2044; break;
613 			default:
614 				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
615 				return B_ERROR;
616 		}
617 		break;
618 	default:
619 		/* confirmed for:
620 		 * GeForce2 MX400, GeForce4 MX440, GeForceFX 5200 */
621 		switch(target->space)
622 		{
623 			case B_CMAP8: max_acc_width = 16368; break;
624 			case B_RGB15: max_acc_width =  8184; break;
625 			case B_RGB16: max_acc_width =  8184; break;
626 			case B_RGB24: max_acc_width =  5456; break;
627 			case B_RGB32: max_acc_width =  4092; break;
628 			default:
629 				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
630 				return B_ERROR;
631 		}
632 		/* NV31 (confirmed GeForceFX 5600) has NV20A granularity!
633 		 * So let it fall through... */
634 		if (si->ps.card_type != NV31) break;
635 	case NV20A:
636 		/* confirmed for:
637 		 * GeForce4 Ti4200 */
638 		switch(target->space)
639 		{
640 			case B_CMAP8: max_acc_width = 16320; break;
641 			case B_RGB15: max_acc_width =  8160; break;
642 			case B_RGB16: max_acc_width =  8160; break;
643 			case B_RGB24: max_acc_width =  5440; break;
644 			case B_RGB32: max_acc_width =  4080; break;
645 			default:
646 				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
647 				return B_ERROR;
648 		}
649 		break;
650 	}
651 
652 //via ok:
653 	/* set virtual_width limit for unaccelerated modes */
654 	switch (si->ps.card_type)
655 	{
656 	default:
657 		switch(target->space)
658 		{
659 			case B_CMAP8: max_crtc_width = 16376; break;
660 			case B_RGB15: max_crtc_width =  8188; break;
661 			case B_RGB16: max_crtc_width =  8188; break;
662 			case B_RGB24: max_crtc_width =  5456; break;
663 			case B_RGB32: max_crtc_width =  4094; break;
664 			default:
665 				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
666 				return B_ERROR;
667 		}
668 		break;
669 	}
670 
671 	/* check for acc capability, and adjust mode to adhere to hardware constraints */
672 	if (max_acc_width <= max_crtc_width)
673 	{
674 		/* check if we can setup this mode with acceleration */
675 //		*acc_mode = true;
676 //blocking acc totally:
677 *acc_mode = false;
678 		/* virtual_width */
679 		if (target->virtual_width > max_acc_width) *acc_mode = false;
680 		/* virtual_height */
681 		/* (NV cards can even do more than this(?)...
682 		 *  but 4096 is confirmed on all cards at max. accelerated width.) */
683 		if (target->virtual_height > 4096) *acc_mode = false;
684 
685 		/* now check virtual_size based on CRTC constraints */
686 		if (target->virtual_width > max_crtc_width) target->virtual_width = max_crtc_width;
687 		/* virtual_height: The only constraint here is the cards memory size which is
688 		 * checked later on in ProposeMode: virtual_height is adjusted then if needed.
689 		 * 'Limiting here' to the variable size that's at least available (uint16). */
690 		if (target->virtual_height > 65535) target->virtual_height = 65535;
691 
692 		/* OK, now we know that virtual_width is valid, and it's needing no slopspace if
693 		 * it was confined above, so we can finally calculate safely if we need slopspace
694 		 * for this mode... */
695 		if (*acc_mode)
696 		{
697 			/* the mode needs to adhere to the largest granularity imposed... */
698 			if (acc_mask < crtc_mask)
699 				video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
700 			else
701 				video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask);
702 		}
703 		else /* unaccelerated mode */
704 			video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
705 	}
706 	else /* max_acc_width > max_crtc_width */
707 	{
708 		/* check if we can setup this mode with acceleration */
709 //		*acc_mode = true;
710 //blocking acc totally:
711 *acc_mode = false;
712 		/* (we already know virtual_width will be no problem) */
713 		/* virtual_height */
714 		/* (NV cards can even do more than this(?)...
715 		 *  but 4096 is confirmed on all cards at max. accelerated width.) */
716 		if (target->virtual_height > 4096) *acc_mode = false;
717 
718 		/* now check virtual_size based on CRTC constraints */
719 		if (*acc_mode)
720 		{
721 			/* note that max_crtc_width already adheres to crtc_mask */
722 			if (target->virtual_width > (max_crtc_width & ~acc_mask))
723 					target->virtual_width = (max_crtc_width & ~acc_mask);
724 		}
725 		else /* unaccelerated mode */
726 		{
727 			if (target->virtual_width > max_crtc_width)
728 					target->virtual_width = max_crtc_width;
729 		}
730 		/* virtual_height: The only constraint here is the cards memory size which is
731 		 * checked later on in ProposeMode: virtual_height is adjusted then if needed.
732 		 * 'Limiting here' to the variable size that's at least available (uint16). */
733 		if (target->virtual_height > 65535) target->virtual_height = 65535;
734 
735 		/* OK, now we know that virtual_width is valid, and it's needing no slopspace if
736 		 * it was confined above, so we can finally calculate safely if we need slopspace
737 		 * for this mode... */
738 		if (*acc_mode)
739 		{
740 			/* the mode needs to adhere to the largest granularity imposed... */
741 			if (acc_mask < crtc_mask)
742 				video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
743 			else
744 				video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask);
745 		}
746 		else /* unaccelerated mode */
747 			video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
748 	}
749 
750 	LOG(2,("INIT: memory pitch will be set to %d pixels for colorspace 0x%08x\n",
751 														video_pitch, target->space));
752 	if (target->virtual_width != video_pitch)
753 		LOG(2,("INIT: effective mode slopspace is %d pixels\n",
754 											(video_pitch - target->virtual_width)));
755 
756 	/* now calculate bytes_per_row for this mode */
757 	*bytes_per_row = video_pitch * (depth >> 3);
758 
759 	return B_OK;
760 }
761