xref: /haiku/src/add-ons/accelerants/matrox/engine/mga_general.c (revision 68fd17064312ae3ffc00ad14fa2e19f279cba7fe)
1 /* Authors:
2    Mark Watson 12/1999,
3    Apsed,
4    Rudolf Cornelissen 10/2002-3/2004
5 */
6 
7 #define MODULE_BIT 0x00008000
8 
9 #include "mga_std.h"
10 
11 static status_t test_ram(void);
12 static status_t mil_general_powerup (void);
13 static status_t g100_general_powerup (void);
14 static status_t g200_general_powerup (void);
15 static status_t g400_general_powerup (void);
16 static status_t g450_general_powerup (void);
17 static status_t gx00_general_bios_to_powergraphics(void);
18 
19 static void mga_dump_configuration_space (void)
20 {
21 #define DUMP_CFG(reg, type) if (si->ps.card_type >= type) do { \
22 	uint32 value = CFGR(reg); \
23 	MSG(("configuration_space 0x%02x %20s 0x%08x\n", \
24 		MGACFG_##reg, #reg, value)); \
25 } while (0)
26 	DUMP_CFG (DEVID,     0);
27 	DUMP_CFG (DEVCTRL,   0);
28 	DUMP_CFG (CLASS,     0);
29 	DUMP_CFG (HEADER,    0);
30 	DUMP_CFG (MGABASE2,  0);
31 	DUMP_CFG (MGABASE1,  0);
32 	DUMP_CFG (MGABASE3,  MYST);
33 	DUMP_CFG (SUBSYSIDR, MYST);
34 	DUMP_CFG (ROMBASE,   0);
35 	DUMP_CFG (CAP_PTR,   MIL2);
36 	DUMP_CFG (INTCTRL,   0);
37 	DUMP_CFG (OPTION,    0);
38 	DUMP_CFG (MGA_INDEX, 0);
39 	DUMP_CFG (MGA_DATA,  0);
40 	DUMP_CFG (SUBSYSIDW, MYST);
41 	DUMP_CFG (OPTION2,   G100);
42 	DUMP_CFG (OPTION3,   G400);
43 	DUMP_CFG (OPTION4,   G400);
44 	DUMP_CFG (PM_IDENT,  G100);
45 	DUMP_CFG (PM_CSR,    G100);
46 	DUMP_CFG (AGP_IDENT, MIL2);
47 	DUMP_CFG (AGP_STS,   MIL2);
48 	DUMP_CFG (AGP_CMD,   MIL2);
49 #undef DUMP_CFG
50 }
51 
52 status_t gx00_general_powerup()
53 {
54 	status_t status;
55 	uint32 card_class;
56 
57 	LOG(1,("POWERUP: Haiku Matrox Accelerant 0.22 running.\n"));
58 
59 	/* detect card type and power it up */
60 	switch(CFGR(DEVID))
61 	{
62 	case 0x051a102b: //MGA-1064 Mystic PCI
63 		LOG(8,("POWERUP: Unimplemented Matrox device %08x\n",CFGR(DEVID)));
64 		return B_ERROR;
65 	case 0x0519102b: //MGA-2064 Millenium PCI
66 		si->ps.card_type = MIL1;
67 		LOG(4,("POWERUP: Detected MGA-2064 Millennium 1\n"));
68 		status = mil_general_powerup();
69 		break;
70 	case 0x051b102b:case 0x051f102b: //MGA-2164 Millenium 2 PCI/AGP
71 		si->ps.card_type = MIL2;
72 		LOG(4,("POWERUP: Detected MGA-2164 Millennium 2\n"));
73 		status = mil_general_powerup();
74 		break;
75 	case 0x1000102b:case 0x1001102b: //G100
76 		si->ps.card_type = G100;
77 		LOG(4,("POWERUP: Detected G100\n"));
78 		status = g100_general_powerup();
79 		break;
80 	case 0x0520102b:case 0x0521102b: //G200
81 		si->ps.card_type = G200;
82 		LOG(4,("POWERUP: Detected G200\n"));
83 		status = g200_general_powerup();
84 		break;
85 	case 0x0525102b: //G400, G400MAX or G450
86 		LOG(4,("POWERUP: Detected G4"));
87 		/* get classinfo to distinguish different types */
88 		card_class = CFGR(CLASS) & 0xff;
89 		if (card_class & 0x80)
90 		{
91 			/* G450 */
92 			si->ps.card_type = G450;
93 			LOG(4, ("50 revision %x\n", card_class & 0x7f));
94 			status = g450_general_powerup();
95 		}
96 		else
97 		{
98 			/* standard G400, G400MAX */
99 			/* the only difference is the max RAMDAC speed, accounted for via pins. */
100 			si->ps.card_type = G400;
101 			LOG(4, ("00 revision %x\n", card_class & 0x7f));
102 			status = g400_general_powerup();
103 		}
104 		break;
105 	case 0x2527102b://G550 patch from Jean-Michel Batto
106 		si->ps.card_type = G450;
107 		LOG(4,("POWERUP: Detected G550\n"));
108 		status = g450_general_powerup();
109 		break;
110 	default:
111 		LOG(8,("POWERUP: Failed to detect valid card 0x%08x\n",CFGR(DEVID)));
112 		return B_ERROR;
113 	}
114 
115 	/* override memory detection if requested by user */
116 	if (si->settings.memory != 0)
117 		si->ps.memory_size = si->settings.memory;
118 
119 	return status;
120 }
121 
122 static status_t test_ram()
123 {
124 	uint32 value, offset;
125 	status_t result = B_OK;
126 
127 	/* make sure we don't corrupt the hardware cursor by using fbc.frame_buffer. */
128 	if (si->fbc.frame_buffer == NULL)
129 	{
130 		LOG(8,("INIT: test_ram detected NULL pointer.\n"));
131 		return B_ERROR;
132 	}
133 
134 	for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
135 	{
136 		/* write testpattern to cardRAM */
137 		((uint32 *)si->fbc.frame_buffer)[offset] = value;
138 		/* toggle testpattern */
139 		value = 0xffffffff - value;
140 	}
141 
142 	for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
143 	{
144 		/* readback and verify testpattern from cardRAM */
145 		if (((uint32 *)si->fbc.frame_buffer)[offset] != value) result = B_ERROR;
146 		/* toggle testpattern */
147 		value = 0xffffffff - value;
148 	}
149 	return result;
150 }
151 
152 /* NOTE:
153  * This routine *has* to be done *after* SetDispplayMode has been executed,
154  * or test results will not be representative!
155  * (CAS latency is dependant on MGA setup on some (DRAM) boards) */
156 status_t mga_set_cas_latency()
157 {
158 	status_t result = B_ERROR;
159 	uint8 latency = 0;
160 
161 	/* check current RAM access to see if we need to change anything */
162 	if (test_ram() == B_OK)
163 	{
164 		LOG(4,("INIT: RAM access OK.\n"));
165 		return B_OK;
166 	}
167 
168 	/* check if we read PINS at starttime so we have valid registersettings at our disposal */
169 	if (si->ps.pins_status != B_OK)
170 	{
171 		LOG(4,("INIT: RAM access errors; not fixable: PINS was not read from cardBIOS.\n"));
172 		return B_ERROR;
173 	}
174 
175 	/* OK. We might have a problem, try to fix it now.. */
176 	LOG(4,("INIT: RAM access errors; tuning CAS latency if prudent...\n"));
177 
178 	switch(si->ps.card_type)
179 	{
180 	case G100:
181 			if (!si->ps.sdram)
182 			{
183 				LOG(4,("INIT: G100 SGRAM CAS tuning not permitted, aborting.\n"));
184 				return B_OK;
185 			}
186 			/* SDRAM card */
187 			for (latency = 4; latency >= 2; latency-- )
188 			{
189 				/* MCTLWTST is a write-only register! */
190 				ACCW(MCTLWTST, ((si->ps.mctlwtst_reg & 0xfffffffc) | (latency - 2)));
191 				result = test_ram();
192 				if (result == B_OK) break;
193 			}
194 			break;
195 	case G200:
196 			/* fixme: implement this */
197 			LOG(4,("INIT: G200 RAM CAS tuning not implemented, aborting.\n"));
198 			return B_OK;
199 			break;
200 	case G400:
201 	case G400MAX:
202 			/* fixme: implement this if needed */
203 			LOG(4,("INIT: G400/G400MAX RAM CAS tuning not implemented, aborting.\n"));
204 			return B_OK;
205 			break;
206 	case G450:
207 	case G550:
208 			/* fixme: implement this if needed */
209 			LOG(4,("INIT: G450/G550 RAM CAS tuning not implemented, aborting.\n"));
210 			return B_OK;
211 			break;
212 	default:
213 			/* fixme: Millenium2 and others if needed */
214 			LOG(4,("INIT: RAM CAS tuning not implemented for this card, aborting.\n"));
215 			return B_OK;
216 			break;
217 	}
218 	if (result == B_OK)
219 		LOG(4,("INIT: RAM access OK. CAS latency set to %d cycles.\n", latency));
220 	else
221 		LOG(4,("INIT: RAM access not fixable. CAS latency set to %d cycles.\n", latency));
222 
223 	return result;
224 }
225 
226 static
227 status_t mil_general_powerup()
228 {
229 	status_t result;
230 
231 	LOG(4, ("INIT: Millenium I/II powerup\n"));
232 	if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
233 
234 	/* initialize the shared_info PINS struct */
235 	result = parse_pins();
236 	if (result != B_OK) fake_pins();
237 
238 	/* log the PINS struct settings */
239 	dump_pins();
240 
241 //remove this:
242 	fake_pins();
243 	LOG(2, ("INIT: Using faked PINS for now:\n"));
244 	dump_pins();
245 //end remove this.
246 
247 	/* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */
248 //restore this line:
249 //	if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
250 
251 	//set to powergraphics etc.
252 	LOG(2, ("INIT: Skipping card coldstart!\n"));
253 	mil2_dac_init();
254 
255 //ok:
256 	/* disable overscan, select 0 IRE, select straight-through sync signals from CRTC */
257 	DXIW (GENCTRL, (DXIR (GENCTRL) & 0x0c));
258 	/* fixme: checkout if we need this sync inverting stuff: already done via CRTC!?!
259 		| (vsync_pos?  0x00:0x02)
260 		| (hsync_pos?  0x00:0x01)); */
261 
262 	/* 8-bit DAC, enable DAC */
263 	DXIW(MISCCTRL, 0x0c);
264 //
265 
266 	VGAW_I(SEQ,1,0x00);
267 	/*enable screen*/
268 
269 	return B_OK;
270 }
271 
272 static
273 status_t g100_general_powerup()
274 {
275 	status_t result;
276 
277 	LOG(4, ("INIT: G100 powerup\n"));
278 	if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
279 
280 	/* initialize the shared_info PINS struct */
281 	result = parse_pins();
282 	if (result != B_OK) fake_pins();
283 
284 	/* log the PINS struct settings */
285 	dump_pins();
286 
287 	/* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */
288 	if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
289 
290 	/*power up the PLLs,LUT,DAC*/
291 	LOG(2,("INIT: PLL/LUT/DAC powerup\n"));
292 	/* turn off both displays and the hardcursor (also disables transfers) */
293 	gx00_crtc_dpms(false, false, false);
294 	gx00_crtc_cursor_hide();
295 	/* G100 SGRAM and SDRAM use external pix and dac refs, do *not* activate internals!
296 	 * (this would create electrical shortcuts,
297 	 * resulting in extra chip heat and distortions visible on screen */
298 	/* set voltage reference - using DAC reference block partly */
299 	DXIW(VREFCTRL,0x03);
300 	/* wait for 100ms for voltage reference to stabilize */
301 	delay(100000);
302 	/* power up the SYSPLL */
303 	CFGW(OPTION,CFGR(OPTION)|0x20);
304 	/* power up the PIXPLL */
305 	DXIW(PIXCLKCTRL,0x08);
306 
307 	/* disable pixelclock oscillations before switching on CLUT */
308 	DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
309 	/* disable 15bit mode CLUT-overlay function */
310 	DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
311 	/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
312 	DXIW(MISCCTRL,0x1b);
313 	snooze(250);
314 	/* re-enable pixelclock oscillations */
315 	DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
316 
317 	/* setup i2c bus */
318 	i2c_init();
319 
320 	/*make sure card is in powergraphics mode*/
321 	VGAW_I(CRTCEXT,3,0x80);
322 
323 	/*set the system clocks to powergraphics speed*/
324 	LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
325 	g100_dac_set_sys_pll();
326 
327 	/* 'official' RAM initialisation */
328 	LOG(2,("INIT: RAM init\n"));
329 	/* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
330 	ACCW(PLNWT,0x00000000);
331 	ACCW(PLNWT,0xffffffff);
332 	/* program memory control waitstates */
333 	ACCW(MCTLWTST,si->ps.mctlwtst_reg);
334 	/* set memory configuration including:
335 	 * - no split framebuffer.
336 	 * - Mark says b14 (G200) should be done also though not defined for G100 in spec,
337 	 * - b3 v3_mem_type was included by Mark for memconfig setup: but looks like not defined */
338 	CFGW(OPTION,(CFGR(OPTION)&0xFFFF8FFF) | ((si->ps.v3_mem_type & 0x04) << 10));
339 	/* set memory buffer type:
340 	 * - Mark says: if((v3_mem_type & 0x03) == 0x03) then do not or-in bits in option2;
341 	 *   but looks like v3_mem_type b1 is not defined,
342 	 * - Mark also says: place v3_mem_type b1 in option2 bit13 (if not 0x03) but b13 = reserved. */
343 	CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|((si->ps.v3_mem_type & 0x01) << 12));
344 	/* set RAM read tap delay */
345 	CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFFFF0) | ((si->ps.v3_mem_type & 0xf0) >> 4));
346 	/* wait 200uS minimum */
347 	snooze(250);
348 
349 	/* reset memory (MACCESS is a write only register!) */
350 	ACCW(MACCESS, 0x00000000);
351 	/* select JEDEC reset method */
352 	ACCW(MACCESS, 0x00004000);
353 	/* perform actual RAM reset */
354 	ACCW(MACCESS, 0x0000c000);
355 	snooze(250);
356 	/* start memory refresh */
357 	CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
358 	/* set memory control waitstate again AFTER the RAM reset */
359 	ACCW(MCTLWTST,si->ps.mctlwtst_reg);
360 	/* end 'official' RAM initialisation. */
361 
362 	/* Bus parameters: enable retries, use advanced read */
363 	CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29)));
364 
365 	/*enable writing to crtc registers*/
366 	VGAW_I(CRTC,0x11,0);
367 
368 	/*turn on display one*/
369 	gx00_crtc_dpms(true, true, true);
370 
371 	return B_OK;
372 }
373 
374 static
375 status_t g200_general_powerup()
376 {
377 	status_t result;
378 
379 	LOG(4, ("INIT: G200 powerup\n"));
380 	if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
381 
382 	/* initialize the shared_info PINS struct */
383 	result = parse_pins();
384 	if (result != B_OK) fake_pins();
385 
386 	/* log the PINS struct settings */
387 	dump_pins();
388 
389 	/* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */
390 	if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
391 
392 	/*power up the PLLs,LUT,DAC*/
393 	LOG(2,("INIT: PLL/LUT/DAC powerup\n"));
394 	/* turn off both displays and the hardcursor (also disables transfers) */
395 	gx00_crtc_dpms(false, false, false);
396 	gx00_crtc_cursor_hide();
397 	/* G200 SGRAM and SDRAM use external pix and dac refs, do *not* activate internals!
398 	 * (this would create electrical shortcuts,
399 	 * resulting in extra chip heat and distortions visible on screen */
400 	/* set voltage reference - using DAC reference block partly */
401 	DXIW(VREFCTRL,0x03);
402 	/* wait for 100ms for voltage reference to stabilize */
403 	delay(100000);
404 	/* power up the SYSPLL */
405 	CFGW(OPTION,CFGR(OPTION)|0x20);
406 	/* power up the PIXPLL */
407 	DXIW(PIXCLKCTRL,0x08);
408 
409 	/* disable pixelclock oscillations before switching on CLUT */
410 	DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
411 	/* disable 15bit mode CLUT-overlay function */
412 	DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
413 	/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
414 	DXIW(MISCCTRL,0x1b);
415 	snooze(250);
416 	/* re-enable pixelclock oscillations */
417 	DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
418 
419 	/* setup i2c bus */
420 	i2c_init();
421 
422 	/*make sure card is in powergraphics mode*/
423 	VGAW_I(CRTCEXT,3,0x80);
424 
425 	/*set the system clocks to powergraphics speed*/
426 	LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
427 	g200_dac_set_sys_pll();
428 
429 	/* 'official' RAM initialisation */
430 	LOG(2,("INIT: RAM init\n"));
431 	/* disable hardware plane write mask if SDRAM card */
432 	if (si->ps.sdram) CFGW(OPTION,(CFGR(OPTION) & 0xffffbfff));
433 	/* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
434 	ACCW(PLNWT,0x00000000);
435 	ACCW(PLNWT,0xffffffff);
436 	/* program memory control waitstates */
437 	ACCW(MCTLWTST,si->ps.mctlwtst_reg);
438 	/* set memory configuration including:
439 	 * - SDRAM / SGRAM special functions select. */
440 	CFGW(OPTION,(CFGR(OPTION)&0xFFFF83FF) | ((si->ps.v3_mem_type & 0x07) << 10));
441 	if (!si->ps.sdram) CFGW(OPTION,(CFGR(OPTION) | (0x01 << 14)));
442 	/* set memory buffer type */
443 	CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|((si->ps.v3_option2_reg & 0x03) << 12));
444 	/* set mode register opcode and streamer flow control */
445 	ACCW(MEMRDBK,(ACCR(MEMRDBK)&0x0000FFFF)|(si->ps.memrdbk_reg & 0xffff0000));
446 	/* set RAM read tap delays */
447 	ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF0000)|(si->ps.memrdbk_reg & 0x0000ffff));
448 	/* wait 200uS minimum */
449 	snooze(250);
450 
451 	/* reset memory (MACCESS is a write only register!) */
452 	ACCW(MACCESS, 0x00000000);
453 	/* perform actual RAM reset */
454 	ACCW(MACCESS, 0x00008000);
455 	snooze(250);
456 	/* start memory refresh */
457 	CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
458 	/* set memory control waitstate again AFTER the RAM reset */
459 	ACCW(MCTLWTST,si->ps.mctlwtst_reg);
460 	/* end 'official' RAM initialisation. */
461 
462 	/* Bus parameters: enable retries, use advanced read */
463 	CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29)));
464 
465 	/*enable writing to crtc registers*/
466 	VGAW_I(CRTC,0x11,0);
467 
468 	/*turn on display one*/
469 	gx00_crtc_dpms(true, true, true);
470 
471 	return B_OK;
472 }
473 
474 static
475 status_t g400_general_powerup()
476 {
477 	status_t result;
478 
479 	LOG(4, ("INIT: G400/G400MAX powerup\n"));
480 	if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
481 
482 	/* initialize the shared_info PINS struct */
483 	result = parse_pins();
484 	if (result != B_OK) fake_pins();
485 
486 	/* log the PINS struct settings */
487 	dump_pins();
488 
489 	/* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */
490 	if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
491 
492 	/* reset MAVEN so we know the sync polarity is at reset situation (Hpos, Vpos) */
493 	if (si->ps.secondary_tvout)
494 	{
495 		ACCW(RST, 0x00000002);
496 		snooze(1000);
497 		ACCW(RST, 0x00000000);
498 	}
499 
500 	/*power up the PLLs,LUT,DAC*/
501 	LOG(4,("INIT: PLL/LUT/DAC powerup\n"));
502 	/* turn off both displays and the hardcursor (also disables transfers) */
503 	gx00_crtc_dpms(false, false, false);
504 	g400_crtc2_dpms(false, false, false);
505 	gx00_crtc_cursor_hide();
506 
507 	/* set voltage reference - not using DAC reference block */
508 	DXIW(VREFCTRL,0x00);
509 	/* wait for 100ms for voltage reference to stabilize */
510 	delay(100000);
511 	/* power up the SYSPLL */
512 	CFGW(OPTION,CFGR(OPTION)|0x20);
513 	/* power up the PIXPLL */
514 	DXIW(PIXCLKCTRL,0x08);
515 
516 	/* disable pixelclock oscillations before switching on CLUT */
517 	DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
518 	/* disable 15bit mode CLUT-overlay function */
519 	DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
520 	/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
521 	DXIW(MISCCTRL,0x9b);
522 	snooze(250);
523 	/* re-enable pixelclock oscillations */
524 	DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
525 
526 	DXIW(MAFCDEL,0x02);                 /*makes CRTC2 stable! Matrox specify 8, but use 4 - grrrr!*/
527 	DXIW(PANELMODE,0x00);               /*eclipse panellink*/
528 
529 	/* setup i2c bus */
530 	i2c_init();
531 
532 	/* make sure card is in powergraphics mode */
533 	VGAW_I(CRTCEXT,3,0x80);
534 
535 	/* set the system clocks to powergraphics speed */
536 	LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
537 	g400_dac_set_sys_pll();
538 
539 	/* 'official' RAM initialisation */
540 	LOG(2,("INIT: RAM init\n"));
541 	/* disable hardware plane write mask if SDRAM card */
542 	if (si->ps.sdram) CFGW(OPTION,(CFGR(OPTION) & 0xffffbfff));
543 	/* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
544 	ACCW(PLNWT,0x00000000);
545 	ACCW(PLNWT,0xffffffff);
546 	/* program memory control waitstates */
547 	ACCW(MCTLWTST, si->ps.mctlwtst_reg);
548 	/* set memory configuration including:
549 	 * - SDRAM / SGRAM special functions select. */
550 	CFGW(OPTION,(CFGR(OPTION)&0xFFFF83FF) | (si->ps.option_reg & 0x00001c00));
551 	if (!si->ps.sdram) CFGW(OPTION,(CFGR(OPTION) | (0x01 << 14)));
552 	/* set mode register opcode and streamer flow control */
553 	ACCW(MEMRDBK,(ACCR(MEMRDBK)&0x0000FFFF)|(si->ps.memrdbk_reg & 0xffff0000));
554 	/* set RAM read tap delays */
555 	ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF0000)|(si->ps.memrdbk_reg & 0x0000ffff));
556 	/* wait 200uS minimum */
557 	snooze(250);
558 
559 	/* reset memory (MACCESS is a write only register!) */
560 	ACCW(MACCESS, 0x00000000);
561 	/* perform actual RAM reset */
562 	ACCW(MACCESS, 0x00008000);
563 	snooze(250);
564 	/* start memory refresh */
565 	CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
566 	/* set memory control waitstate again AFTER the RAM reset */
567 	ACCW(MCTLWTST,si->ps.mctlwtst_reg);
568 	/* end 'official' RAM initialisation. */
569 
570 	/* 'advance read' busparameter and 'memory priority' enable/disable setup */
571 	CFGW(OPTION, ((CFGR(OPTION) & 0xefbfffff) | (si->ps.option_reg & 0x10400000)));
572 
573 	/*enable writing to crtc registers*/
574 	VGAW_I(CRTC,0x11,0);
575 	if (si->ps.secondary_head)
576 	{
577 		MAVW(LOCK,0x01);
578 		CR2W(DATACTL,0x00000000);
579 	}
580 
581 	/*turn on display one*/
582 	gx00_crtc_dpms(true, true, true);
583 
584 	return B_OK;
585 }
586 
587 static
588 status_t g450_general_powerup()
589 {
590 	status_t result;
591 	uint32 pwr_cas[] = {0, 1, 5, 6, 7, 5, 2, 3};
592 
593 	/* used for convenience: MACCESS is a write only register! */
594 	uint32 maccess = 0x00000000;
595 
596 	LOG(4, ("INIT: G450/G550 powerup\n"));
597 	if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
598 
599 	/* initialize the shared_info PINS struct */
600 	result = parse_pins();
601 	if (result != B_OK) fake_pins();
602 
603 	/* log the PINS struct settings */
604 	dump_pins();
605 
606 	/* check output connector setup */
607 	if (si->ps.primary_dvi && si->ps.secondary_head &&
608 		si->ps.secondary_tvout && (i2c_sec_tv_adapter() != B_OK))
609 	{
610 		/* signal CRTC2 DPMS which connector to program or readout */
611 		si->crossed_conns = true;
612 	}
613 
614 	/* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */
615 	if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
616 
617 	/* power up the PLLs,LUT,DAC */
618 	LOG(4,("INIT: PLL/LUT/DAC powerup\n"));
619 	/* disable outputs */
620 	DXIW(OUTPUTCONN,0x00);
621 	/* turn off both displays and the hardcursor (also disables transfers) */
622 	gx00_crtc_dpms(false, false, false);
623 	g400_crtc2_dpms(false, false, false);
624 	gx00_crtc_cursor_hide();
625 
626 	/* power up everything except DVI electronics (for now) */
627 	DXIW(PWRCTRL,0x1b);
628 	/* set voltage reference - not using DAC reference block */
629 	DXIW(VREFCTRL,0x00);
630 	/* wait for 100ms for voltage reference to stabilize */
631 	delay(100000);
632 	/* power up the SYSPLL */
633 	CFGW(OPTION,CFGR(OPTION)|0x20);
634 	/* power up the PIXPLL */
635 	DXIW(PIXCLKCTRL,0x08);
636 
637 	/* disable pixelclock oscillations before switching on CLUT */
638 	DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
639 	/* disable 15bit mode CLUT-overlay function */
640 	DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
641 	/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
642 	DXIW(MISCCTRL,0x9b);
643 	snooze(250);
644 
645 	/* re-enable pixelclock oscillations */
646 	DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
647 
648 	//fixme:
649 	DXIW(MAFCDEL,0x02);                 /*makes CRTC2 stable! Matrox specify 8, but use 4 - grrrr!*/
650 	DXIW(PANELMODE,0x00);               /*eclipse panellink*/
651 
652 	/* setup i2c bus */
653 	i2c_init();
654 
655 	/* make sure card is in powergraphics mode */
656 	VGAW_I(CRTCEXT,3,0x80);
657 
658 	/* set the system clocks to powergraphics speed */
659 	LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
660 	g450_dac_set_sys_pll();
661 
662 	/* 'official' RAM initialisation */
663 	LOG(2,("INIT: RAM init\n"));
664 	/* stop memory refresh, and setup b9, memconfig, b13, sgram planemask function, b21 fields,
665 	 * and don't touch the rest */
666 	CFGW(OPTION, ((CFGR(OPTION) & 0xf8400164) | (si->ps.option_reg & 0x00207e00)));
667 	/* setup b10-b15 unknown field */
668 	CFGW(OPTION2, ((CFGR(OPTION2) & 0xffff0200) | (si->ps.option2_reg & 0x0000fc00)));
669 
670 	/* program memory control waitstates */
671 	ACCW(MCTLWTST, si->ps.mctlwtst_reg);
672 	/* program option4 b0-3 and b29-30 fields, reset the rest: stop memory clock */
673 	CFGW(OPTION4, (si->ps.option4_reg & 0x6000000f));
674 	/* set RAM read tap delays and mode register opcode / streamer flow control */
675 	ACCW(MEMRDBK, si->ps.memrdbk_reg);
676 	/* b7 v5_mem_type = done by Mark Watson. fixme: still confirm! (unknown bits) */
677 	maccess = ((((uint32)si->ps.v5_mem_type) & 0x80) >> 1);
678 	ACCW(MACCESS, maccess);
679 	/* clear b0-1 and 3, and set b31 in option4: re-enable memory clock */
680 	CFGW(OPTION4, ((si->ps.option4_reg & 0x60000004) | 0x80000000));
681 	snooze(250);
682 
683 	/* if DDR RAM */
684 	if ((si->ps.v5_mem_type & 0x0060) == 0x0020)
685 	{
686 		/* if not 'EMRSW RAM-option' available */
687 		if (!(si->ps.v5_mem_type & 0x0100))
688 		{
689 			/* clear unknown bits */
690 			maccess = 0x00000000;
691 			ACCW(MACCESS, maccess);
692 			/* clear b12: unknown bit */
693 			ACCW(MEMRDBK, (si->ps.memrdbk_reg & 0xffffefff));
694 		}
695 		else
696 			/* if not 'DLL RAM-option' available */
697 			if (!(si->ps.v5_mem_type & 0x0200))
698 			{
699 				/* clear b12: unknown bit */
700 				ACCW(MEMRDBK, (si->ps.memrdbk_reg & 0xffffefff));
701 			}
702 	}
703 
704 	/* create positive flank to generate memory reset */
705 	ACCW(MACCESS, (maccess & 0xffff7fff));
706 	ACCW(MACCESS, (maccess | 0x00008000));
707 	snooze(250);
708 
709 	/* start memory refresh */
710 	CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
711 
712 	/* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
713 	ACCW(PLNWT,0x00000000);
714 	ACCW(PLNWT,0xffffffff);
715 
716 	/* if not 'MEMCASLT RAM-option' available */
717 	if (!(si->ps.v5_mem_type & 0x0400))
718 	{
719 		/* calculate powergraphics CAS-latency from pins CAS-latency, and update register setting */
720 		ACCW(MCTLWTST,
721 			((si->ps.mctlwtst_reg & 0xfffffff8) | pwr_cas[(si->ps.mctlwtst_reg & 0x07)]));
722 
723 	}
724 
725 	/*enable writing to crtc registers*/
726 	VGAW_I(CRTC,0x11,0);
727 	//fixme..
728 	if (si->ps.secondary_head)
729 	{
730 		//MAVW(LOCK,0x01);
731 		CR2W(DATACTL,0x00000000);
732 	}
733 
734 	/* enable primary analog output */
735 	gx50_general_output_select();
736 
737 	/*turn on display one*/
738 	gx00_crtc_dpms(true, true, true);
739 
740 	/* enable 'straight-through' sync outputs on both analog output connectors and
741 	 * make sure CRTC1 sync outputs are patched through! */
742 	DXIW(SYNCCTRL,0x00);
743 
744 	return B_OK;
745 }
746 
747 status_t gx50_general_output_select()
748 {
749 	/* make sure this call is warranted */
750 	if ((si->ps.card_type != G450) && (si->ps.card_type != G550)) return B_ERROR;
751 
752 	/* choose primary analog outputconnector */
753 	if (si->ps.primary_dvi && si->ps.secondary_head && si->ps.secondary_tvout)
754 	{
755 		if (i2c_sec_tv_adapter() == B_OK)
756 		{
757 			LOG(4,("INIT: secondary TV-adapter detected, using primary connector\n"));
758 			DXIW(OUTPUTCONN,0x01);
759 			/* signal CRTC2 DPMS which connector to program */
760 			si->crossed_conns = false;
761 		}
762 		else
763 		{
764 			LOG(4,("INIT: no secondary TV-adapter detected, using secondary connector\n"));
765 			DXIW(OUTPUTCONN,0x04);
766 			/* signal CRTC2 DPMS which connector to program */
767 			si->crossed_conns = true;
768 		}
769 	}
770 	else
771 	{
772 		LOG(4,("INIT: using primary connector\n"));
773 		DXIW(OUTPUTCONN,0x01);
774 		/* signal CRTC2 DPMS which connector to program */
775 		si->crossed_conns = false;
776 	}
777 	return B_OK;
778 }
779 
780 /*connect CRTC1 to the specified DAC*/
781 status_t gx00_general_dac_select(int dac)
782 {
783 	if (!si->ps.secondary_head)
784 		return B_ERROR;
785 
786 	/*MISCCTRL, clock src,...*/
787 	switch(dac)
788 	{
789 		/* G400 */
790 		case DS_CRTC1DAC_CRTC2MAVEN:
791 			/* connect CRTC1 to pixPLL */
792 			DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1);
793 			/* connect CRTC2 to vidPLL, connect CRTC1 to internal DAC and
794 			 * enable CRTC2 external video timing reset signal.
795 			 * (Setting for MAVEN 'master mode' TVout signal generation.) */
796 			CR2W(CTL,(CR2R(CTL)&0xffe00779)|0xD0000002);
797 			/* disable CRTC1 external video timing reset signal */
798 			VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0x77));
799 			/* select CRTC2 RGB24 MAFC mode: connects CRTC2 to MAVEN DAC */
800 			DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x82);
801 			break;
802 		case DS_CRTC1MAVEN_CRTC2DAC:
803 			/* connect CRTC1 to vidPLL */
804 			DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x2);
805 			/* connect CRTC2 to pixPLL and internal DAC and
806 			 * disable CRTC2 external video timing reset signal */
807 			CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x1<<20));
808 			/* enable CRTC1 external video timing reset signal.
809 			 * note: this is nolonger used as G450/G550 cannot do TVout on CRTC1 */
810 			VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)|0x88));
811 			/* select CRTC1 RGB24 MAFC mode: connects CRTC1 to MAVEN DAC */
812 			DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x02);
813 			break;
814 		/* G450/G550 */
815 		case DS_CRTC1CON1_CRTC2CON2:
816 			/* connect CRTC1 to pixPLL */
817 			DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1);
818 			/* connect CRTC2 to vidPLL, connect CRTC1 to DAC1, disable CRTC2
819 			 * external video timing reset signal, set CRTC2 progressive scan mode
820 			 * and disable TVout mode (b12).
821 			 * (Setting for MAVEN 'slave mode' TVout signal generation.) */
822 			//fixme: enable timing resets if TVout is used in master mode!
823 			//otherwise keep it disabled.
824 			CR2W(CTL,(CR2R(CTL)&0x2de00779)|0x6|(0x0<<20));
825 			/* connect DAC1 to CON1, CRTC2/'DAC2' to CON2 (monitor mode) */
826 			DXIW(OUTPUTCONN,0x09);
827 			/* Select 1.5 Volt MAVEN DAC ref. for monitor mode */
828 			DXIW(GENIOCTRL, DXIR(GENIOCTRL) & ~0x40);
829 			DXIW(GENIODATA, 0x00);
830 			/* signal CRTC2 DPMS which connector to program */
831 			si->crossed_conns = false;
832 			break;
833 		//fixme: toggle PLL's below if possible:
834 		//       otherwise toggle PLL's for G400 2nd case?
835 		case DS_CRTC1CON2_CRTC2CON1:
836 			/* connect CRTC1 to pixPLL */
837 			DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1);
838 			/* connect CRTC2 to vidPLL and DAC1, disable CRTC2 external
839 			 * video timing reset signal, and set CRTC2 progressive scan mode and
840 			 * disable TVout mode (b12). */
841 			CR2W(CTL,(CR2R(CTL)&0x2de00779)|0x6|(0x1<<20));
842 			/* connect DAC1 to CON2 (monitor mode), CRTC2/'DAC2' to CON1 */
843 			DXIW(OUTPUTCONN,0x05);
844 			/* Select 1.5 Volt MAVEN DAC ref. for monitor mode */
845 			DXIW(GENIOCTRL, DXIR(GENIOCTRL) & ~0x40);
846 			DXIW(GENIODATA, 0x00);
847 			/* signal CRTC2 DPMS which connector to program */
848 			si->crossed_conns = true;
849 			break;
850 		default:
851 			return B_ERROR;
852 	}
853 	return B_OK;
854 }
855 
856 /* basic change of card state from VGA to powergraphics -> should work from BIOS init state*/
857 static
858 status_t gx00_general_bios_to_powergraphics()
859 {
860 	LOG(2, ("INIT: Skipping card coldstart!\n"));
861 
862 	//set to powergraphics etc.
863 	CFGW(DEVCTRL,(2|CFGR(DEVCTRL)));
864 	/*enable device response (already enabled here!)*/
865 
866 	VGAW_I(CRTC,0x11,0);
867 	/*allow me to change CRTC*/
868 
869 	VGAW_I(CRTCEXT,3,0x80);
870 	/*use powergraphix (+ trash other bits, they are set later)*/
871 
872 	VGAW(MISCW,0x08);
873 	/*set only MGA pixel clock in MISC - I don't want to map VGA stuff under this OS*/
874 
875 	switch (si->ps.card_type)
876 	{
877 		case G400:
878 		case G400MAX:
879 			/* reset MAVEN so we know the sync polarity is at reset situation (Hpos, Vpos) */
880 			if (si->ps.secondary_tvout)
881 			{
882 				ACCW(RST, 0x00000002);
883 				snooze(1000);
884 				ACCW(RST, 0x00000000);
885 			}
886 			/* makes CRTC2 stable! Matrox specify 8, but use 4 - grrrr! */
887 			DXIW(MAFCDEL,0x02);
888 			break;
889 		case G450:
890 		case G550:
891 			/* power up everything except DVI electronics (for now) */
892 			DXIW(PWRCTRL,0x1b);
893 			/* enable 'straight-through' sync outputs on both analog output
894 			 * connectors and make sure CRTC1 sync outputs are patched through! */
895 			DXIW(SYNCCTRL,0x00);
896 			break;
897 		default:
898 			break;
899 	}
900 
901 	if (si->ps.card_type >= G100)
902 	{
903 		DXIW(MISCCTRL,0x9b);
904 		/*CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC*/
905 
906 		DXIW(MULCTRL,0x4);
907 		/*RGBA direct mode*/
908 	}
909 	else
910 	{
911 		LOG(8, ("INIT: < G100 DAC powerup badly implemented, MISC 0x%02x\n", VGAR(MISCR)));
912 	} // apsed TODO MIL2
913 
914 	VGAW_I(SEQ,1,0x00);
915 	/*enable screen*/
916 
917 	return B_OK;
918 }
919 
920 /* Check if mode virtual_size adheres to the cards _maximum_ contraints, and modify
921  * virtual_size to the nearest valid maximum for the mode on the card if not so.
922  * Then: check if virtual_width adheres to the cards _multiple_ constraints, and
923  * create mode slopspace if not so.
924  * We use acc multiple constraints here if we expect we can use acceleration, because
925  * acc constraints are worse than CRTC constraints.
926  *
927  * Mode slopspace is reflected in fbc->bytes_per_row BTW. */
928 //fixme: seperate heads for real dualhead modes:
929 //CRTC1 and 2 constraints differ!
930 status_t gx00_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode)
931 {
932 	/* Note:
933 	 * This routine assumes that the CRTC memory pitch granularity is 'smaller than',
934 	 * or 'equals' the acceleration engine memory pitch granularity! */
935 
936 	uint32 video_pitch;
937 	uint32 acc_mask, crtc_mask;
938 	uint8 depth = 8;
939 
940 	/* determine pixel multiple based on 2D/3D engine constraints */
941 	switch (si->ps.card_type)
942 	{
943 	case MIL1:
944 	case MIL2:
945 		/* see MIL1/2 specs:
946 		 * these cards always use a 64bit RAMDAC (TVP3026) and interleaved memory */
947 		switch (target->space)
948 		{
949 			case B_CMAP8: acc_mask = 0x7f; depth =  8; break;
950 			case B_RGB15: acc_mask = 0x3f; depth = 16; break;
951 			case B_RGB16: acc_mask = 0x3f; depth = 16; break;
952 			case B_RGB24: acc_mask = 0x7f; depth = 24; break;
953 			case B_RGB32: acc_mask = 0x1f; depth = 32; break;
954 			default:
955 				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
956 				return B_ERROR;
957 		}
958 		break;
959 	default:
960 		/* see G100 and up specs:
961 		 * these cards can do 2D as long as multiples of 32 are used.
962 		 * (Note: don't mix this up with adress linearisation!) */
963 		switch (target->space)
964 		{
965 			case B_CMAP8: depth =  8; break;
966 			case B_RGB15: depth = 16; break;
967 			case B_RGB16: depth = 16; break;
968 			case B_RGB24: depth = 24; break;
969 			case B_RGB32: depth = 32; break;
970 			default:
971 				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
972 				return B_ERROR;
973 		}
974 		acc_mask = 0x1f;
975 		break;
976 	}
977 
978 	/* determine pixel multiple based on CRTC memory pitch constraints.
979 	 * (Note: Don't mix this up with CRTC timing contraints! Those are
980 	 *        multiples of 8 for horizontal, 1 for vertical timing.) */
981 	switch (si->ps.card_type)
982 	{
983 	case MIL1:
984 	case MIL2:
985 		/* see MIL1/2 specs:
986 		 * these cards always use a 64bit RAMDAC and interleaved memory */
987 		switch (target->space)
988 		{
989 			case B_CMAP8: crtc_mask = 0x7f; break;
990 			case B_RGB15: crtc_mask = 0x3f; break;
991 			case B_RGB16: crtc_mask = 0x3f; break;
992 			/* for B_RGB24 crtc_mask 0x7f is worst case scenario (MIL2 constraint) */
993 			case B_RGB24: crtc_mask = 0x7f; break;
994 			case B_RGB32: crtc_mask = 0x1f; break;
995 			default:
996 				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
997 				return B_ERROR;
998 		}
999 		break;
1000 	default:
1001 		/* see G100 and up specs */
1002 		switch (target->space)
1003 		{
1004 			case B_CMAP8: crtc_mask = 0x0f; break;
1005 			case B_RGB15: crtc_mask = 0x07; break;
1006 			case B_RGB16: crtc_mask = 0x07; break;
1007 			case B_RGB24: crtc_mask = 0x0f; break;
1008 			case B_RGB32: crtc_mask = 0x03; break;
1009 			default:
1010 				LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
1011 				return B_ERROR;
1012 		}
1013 		/* see G400 specs: CRTC2 has different constraints */
1014 		/* Note:
1015 		 * set for RGB and B_YCbCr422 modes. Other modes need larger multiples! */
1016 		if (target->flags & DUALHEAD_BITS)
1017 		{
1018 			switch (target->space)
1019 			{
1020 				case B_RGB16: crtc_mask = 0x1f; break;
1021 				case B_RGB32: crtc_mask = 0x0f; break;
1022 				default:
1023 					LOG(8,("INIT: illegal DH color space: 0x%08x\n", target->space));
1024 					return B_ERROR;
1025 			}
1026 		}
1027 		break;
1028 	}
1029 
1030 	/* check if we can setup this mode with acceleration:
1031 	 * Max sizes need to adhere to both the acceleration engine _and_ the CRTC constraints! */
1032 	*acc_mode = true;
1033 	/* check virtual_width */
1034 	switch (si->ps.card_type)
1035 	{
1036 	case MIL1:
1037 	case MIL2:
1038 	case G100:
1039 		/* acc constraint: */
1040 		if (target->virtual_width > 2048) *acc_mode = false;
1041 		break;
1042 	default:
1043 		/* G200-G550 */
1044 		/* acc constraint: */
1045 		if (target->virtual_width > 4096) *acc_mode = false;
1046 		/* for 32bit mode a lower CRTC1 restriction applies! */
1047 		if ((target->space == B_RGB32_LITTLE) && (target->virtual_width > (4092 & ~acc_mask)))
1048 			*acc_mode = false;
1049 		break;
1050 	}
1051 	/* virtual_height */
1052 	if (target->virtual_height > 2048) *acc_mode = false;
1053 
1054 	/* now check virtual_size based on CRTC constraints,
1055 	 * making sure virtual_width stays within the 'mask' constraint: which is only
1056 	 * nessesary because of an extra constraint in MIL1/2 cards that exists here. */
1057 	{
1058 		/* virtual_width */
1059 		//fixme for CRTC2 (identical on all G400+ cards):
1060 		//16bit mode: max. virtual_width == 16352 (no extra mask needed);
1061 		//32bit mode: max. virtual_width == 8176 (no extra mask needed);
1062 		//other colordepths are unsupported on CRTC2.
1063 		switch(target->space)
1064 		{
1065 		case B_CMAP8:
1066 			if (target->virtual_width > (16368 & ~crtc_mask))
1067 				target->virtual_width = (16368 & ~crtc_mask);
1068 			break;
1069 		case B_RGB15_LITTLE:
1070 		case B_RGB16_LITTLE:
1071 			if (target->virtual_width > (8184 & ~crtc_mask))
1072 				target->virtual_width = (8184 & ~crtc_mask);
1073 			break;
1074 		case B_RGB24_LITTLE:
1075 			if (target->virtual_width > (5456 & ~crtc_mask))
1076 				target->virtual_width = (5456 & ~crtc_mask);
1077 			break;
1078 		case B_RGB32_LITTLE:
1079 			if (target->virtual_width > (4092 & ~crtc_mask))
1080 				target->virtual_width = (4092 & ~crtc_mask);
1081 			break;
1082 		}
1083 
1084 		/* virtual_height: The only constraint here is the cards memory size which is
1085 		 * checked later on in ProposeMode: virtual_height is adjusted then if needed.
1086 		 * 'Limiting here' to the variable size that's at least available (uint16). */
1087 		if (target->virtual_height > 65535) target->virtual_height = 65535;
1088 	}
1089 
1090 	/* OK, now we know that virtual_width is valid, and it's needing no slopspace if
1091 	 * it was confined above, so we can finally calculate safely if we need slopspace
1092 	 * for this mode... */
1093 	if (*acc_mode)
1094 		video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask);
1095 	else
1096 		video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
1097 
1098 	LOG(2,("INIT: memory pitch will be set to %d pixels for colorspace 0x%08x\n",
1099 														video_pitch, target->space));
1100 	if (target->virtual_width != video_pitch)
1101 		LOG(2,("INIT: effective mode slopspace is %d pixels\n",
1102 											(video_pitch - target->virtual_width)));
1103 
1104 	/* now calculate bytes_per_row for this mode */
1105 	*bytes_per_row = video_pitch * (depth >> 3);
1106 
1107 	return B_OK;
1108 }
1109