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