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