xref: /haiku/src/add-ons/accelerants/neomagic/engine/nm_general.c (revision f2b4344867e97c3f4e742a1b4a15e6879644601a)
1 /* Author:
2    Rudolf Cornelissen 4/2003-1/2006
3 */
4 
5 #define MODULE_BIT 0x00008000
6 
7 #include "nm_std.h"
8 
9 static status_t test_ram(void);
10 static status_t nmxxxx_general_powerup (void);
11 static status_t nm_general_bios_to_powergraphics(void);
12 
13 static void nm_dump_configuration_space (void)
14 {
15 #define DUMP_CFG(reg, type) if (si->ps.card_type >= type) do { \
16 	uint32 value = CFGR(reg); \
17 	MSG(("configuration_space 0x%02x %20s 0x%08x\n", \
18 		NMCFG_##reg, #reg, value)); \
19 } while (0)
20 	DUMP_CFG (DEVID,	0);
21 	DUMP_CFG (DEVCTRL,	0);
22 	DUMP_CFG (CLASS,	0);
23 	DUMP_CFG (HEADER,	0);
24 	DUMP_CFG (BASE1FB,	0);
25 	DUMP_CFG (BASE2REG1,0);
26 	DUMP_CFG (BASE3REG2,0);
27 	DUMP_CFG (BASE4,	0);
28 	DUMP_CFG (BASE5,	0);
29 	DUMP_CFG (BASE6,	0);
30 	DUMP_CFG (BASE7,	0);
31 	DUMP_CFG (SUBSYSID1,0);
32 	DUMP_CFG (ROMBASE,	0);
33 	DUMP_CFG (CAPPTR,	0);
34 	DUMP_CFG (CFG_1,	0);
35 	DUMP_CFG (INTERRUPT,0);
36 	DUMP_CFG (CFG_3,	0);
37 	DUMP_CFG (CFG_4,	0);
38 	DUMP_CFG (CFG_5,	0);
39 	DUMP_CFG (CFG_6,	0);
40 	DUMP_CFG (CFG_7,	0);
41 	DUMP_CFG (CFG_8,	0);
42 	DUMP_CFG (CFG_9,	0);
43 	DUMP_CFG (CFG_10,	0);
44 	DUMP_CFG (CFG_11,	0);
45 	DUMP_CFG (CFG_12,	0);
46 	DUMP_CFG (CFG_13,	0);
47 	DUMP_CFG (CFG_14,	0);
48 	DUMP_CFG (CFG_15,	0);
49 	DUMP_CFG (CFG_16,	0);
50 	DUMP_CFG (CFG_17,	0);
51 	DUMP_CFG (CFG_18,	0);
52 	DUMP_CFG (CFG_19,	0);
53 	DUMP_CFG (CFG_20,	0);
54 	DUMP_CFG (CFG_21,	0);
55 	DUMP_CFG (CFG_22,	0);
56 	DUMP_CFG (CFG_23,	0);
57 	DUMP_CFG (CFG_24,	0);
58 	DUMP_CFG (CFG_25,	0);
59 	DUMP_CFG (CFG_26,	0);
60 	DUMP_CFG (CFG_27,	0);
61 	DUMP_CFG (CFG_28,	0);
62 	DUMP_CFG (CFG_29,	0);
63 	DUMP_CFG (CFG_30,	0);
64 	DUMP_CFG (CFG_31,	0);
65 	DUMP_CFG (CFG_32,	0);
66 	DUMP_CFG (CFG_33,	0);
67 	DUMP_CFG (CFG_34,	0);
68 	DUMP_CFG (CFG_35,	0);
69 	DUMP_CFG (CFG_36,	0);
70 	DUMP_CFG (CFG_37,	0);
71 	DUMP_CFG (CFG_38,	0);
72 	DUMP_CFG (CFG_39,	0);
73 	DUMP_CFG (CFG_40,	0);
74 	DUMP_CFG (CFG_41,	0);
75 	DUMP_CFG (CFG_42,	0);
76 	DUMP_CFG (CFG_43,	0);
77 	DUMP_CFG (CFG_44,	0);
78 	DUMP_CFG (CFG_45,	0);
79 	DUMP_CFG (CFG_46,	0);
80 	DUMP_CFG (CFG_47,	0);
81 	DUMP_CFG (CFG_48,	0);
82 	DUMP_CFG (CFG_49,	0);
83 	DUMP_CFG (CFG_50,	0);
84 #undef DUMP_CFG
85 }
86 
87 status_t nm_general_powerup()
88 {
89 	status_t status;
90 
91 	LOG(1,("POWERUP: Haiku Neomagic Accelerant 0.14 running.\n"));
92 
93 	/* log VBLANK INT usability status */
94 	if (si->ps.int_assigned)
95 		LOG(4,("POWERUP: Usable INT assigned to HW; Vblank semaphore enabled\n"));
96 	else
97 		LOG(4,("POWERUP: No (usable) INT assigned to HW; Vblank semaphore disabled\n"));
98 
99 	/* WARNING:
100 	 * _adi.name_ and _adi.chipset_ can contain 31 readable characters max.!!! */
101 
102 	/* detect card type and power it up */
103 	switch(CFGR(DEVID))
104 	{
105 	case 0x000110c8: //NM2070 ISA
106 		si->ps.card_type = NM2070;
107 		sprintf(si->adi.name, "Neomagic MagicGraph 128");
108 		sprintf(si->adi.chipset, "NM2070 (ISA)");
109 		break;
110 	case 0x000210c8: //NM2090 ISA
111 		si->ps.card_type = NM2090;
112 		sprintf(si->adi.name, "Neomagic MagicGraph 128V");
113 		sprintf(si->adi.chipset, "NM2090 (ISA)");
114 		break;
115 	case 0x000310c8: //NM2093 ISA
116 		si->ps.card_type = NM2093;
117 		sprintf(si->adi.name, "Neomagic MagicGraph 128ZV");
118 		sprintf(si->adi.chipset, "NM2093 (ISA)");
119 		break;
120 	case 0x008310c8: //NM2097 PCI
121 		si->ps.card_type = NM2097;
122 		sprintf(si->adi.name, "Neomagic MagicGraph 128ZV+");
123 		sprintf(si->adi.chipset, "NM2097 (PCI)");
124 		break;
125 	case 0x000410c8: //NM2160 PCI
126 		si->ps.card_type = NM2160;
127 		sprintf(si->adi.name, "Neomagic MagicGraph 128XD");
128 		sprintf(si->adi.chipset, "NM2160 (PCI)");
129 		break;
130 	case 0x000510c8: //NM2200
131 		si->ps.card_type = NM2200;
132 		sprintf(si->adi.name, "Neomagic MagicMedia 256AV");
133 		sprintf(si->adi.chipset, "NM2200");
134 		break;
135 	case 0x002510c8: //NM2230
136 		si->ps.card_type = NM2230;
137 		sprintf(si->adi.name, "Neomagic MagicMedia 256AV+");
138 		sprintf(si->adi.chipset, "NM2230");
139 		break;
140 	case 0x000610c8: //NM2360
141 		si->ps.card_type = NM2360;
142 		sprintf(si->adi.name, "Neomagic MagicMedia 256ZX");
143 		sprintf(si->adi.chipset, "NM2360");
144 		break;
145 	case 0x001610c8: //NM2380
146 		si->ps.card_type = NM2380;
147 		sprintf(si->adi.name, "Neomagic MagicMedia 256XL+");
148 		sprintf(si->adi.chipset, "NM2380");
149 		break;
150 	default:
151 		LOG(8,("POWERUP: Failed to detect valid card 0x%08x\n",CFGR(DEVID)));
152 		return B_ERROR;
153 	}
154 
155 	/* power up the card */
156 	status = nmxxxx_general_powerup();
157 
158 	/* override memory detection if requested by user */
159 	if (si->settings.memory != 0)
160 		si->ps.memory_size = si->settings.memory;
161 
162 	return status;
163 }
164 
165 static status_t test_ram(void)
166 {
167 	uint32 value, offset;
168 	status_t result = B_OK;
169 
170 	/* make sure we don't corrupt the hardware cursor by using fbc.frame_buffer. */
171 	if (si->fbc.frame_buffer == NULL)
172 	{
173 		LOG(8,("INIT: test_ram detected NULL pointer.\n"));
174 		return B_ERROR;
175 	}
176 
177 	for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
178 	{
179 		/* write testpattern to cardRAM */
180 		((uint32 *)si->fbc.frame_buffer)[offset] = value;
181 		/* toggle testpattern */
182 		value = 0xffffffff - value;
183 	}
184 
185 	for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
186 	{
187 		/* readback and verify testpattern from cardRAM */
188 		if (((uint32 *)si->fbc.frame_buffer)[offset] != value) result = B_ERROR;
189 		/* toggle testpattern */
190 		value = 0xffffffff - value;
191 	}
192 	return result;
193 }
194 
195 /* NOTE:
196  * This routine *has* to be done *after* SetDispplayMode has been executed,
197  * or test results will not be representative!
198  * (CAS latency is dependant on nm setup on some (DRAM) boards) */
199 status_t nm_set_cas_latency()
200 {
201 	/* check current RAM access to see if we need to change anything */
202 	if (test_ram() == B_OK)
203 	{
204 		LOG(4,("INIT: RAM access OK.\n"));
205 		return B_OK;
206 	}
207 
208 	/* check if we read PINS at starttime so we have valid registersettings at our disposal */
209 	LOG(4,("INIT: RAM access errors; not fixable: missing coldstart specs.\n"));
210 	return B_ERROR;
211 }
212 
213 void nm_unlock()
214 {
215 	/* unlock cards GRAPHICS registers (any other value than 0x26 should lock it again) */
216     ISAGRPHW(GRPHXLOCK, 0x26);
217 }
218 
219 static status_t nmxxxx_general_powerup()
220 {
221 	uint8 temp;
222 //	status_t result;
223 
224 	LOG(4, ("INIT: powerup\n"));
225 	LOG(4, ("INIT: Detected %s (%s)\n", si->adi.name, si->adi.chipset));
226 	if (si->settings.logmask & 0x80000000) nm_dump_configuration_space();
227 
228 	/* set ISA registermapping to VGA colormode */
229 	temp = (ISARB(MISCR) | 0x01);
230 	/* we need to wait a bit or the card will mess-up it's register values.. */
231 	snooze(10);
232 	ISAWB(MISCW, temp);
233 
234 	/* unlock cards GRAPHICS registers (any other value than 0x26 should lock it again) */
235     ISAGRPHW(GRPHXLOCK, 0x26);
236 
237 	/* unlock cards CRTC registers */
238 //don't touch: most cards get into trouble on this!
239 //	ISAGRPHW(GENLOCK, 0x00);
240 
241 	/* initialize the shared_info struct */
242 	set_specs();
243 	/* log the struct settings */
244 	dump_specs();
245 
246 	/* activate PCI access: b7 = framebuffer, b6 = registers */
247 	ISAGRPHW(IFACECTRL2, 0xc0);
248 
249 	/* disable VGA-mode cursor (just to be sure) */
250 	ISACRTCW(VGACURCTRL, 0x00);
251 
252 	/* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */
253 	/*if (si->settings.usebios || (result != B_OK)) */return nm_general_bios_to_powergraphics();
254 
255 	/*power up the PLLs,LUT,DAC*/
256 	LOG(2,("INIT: powerup\n"));
257 
258 	/* turn off both displays and the hardcursor (also disables transfers) */
259 	nm_crtc_dpms(false, false, false);
260 	nm_crtc_cursor_hide();
261 
262 	/* setup sequencer clocking mode */
263 	ISASEQW(CLKMODE, 0x21);
264 
265 	//fixme: setup coldstart capability...
266 
267 	/* turn on display */
268 	nm_crtc_dpms(true, true, true);
269 
270 	return B_OK;
271 }
272 
273 status_t nm_general_output_select()
274 {
275 	/* log currently selected output */
276 	switch (nm_general_output_read() & 0x03)
277 	{
278 	case 0x01:
279 		LOG(2, ("INIT: external CRT only mode active\n"));
280 		break;
281 	case 0x02:
282 		LOG(2, ("INIT: internal LCD only mode active\n"));
283 		break;
284 	case 0x03:
285 		LOG(2, ("INIT: simultaneous LCD/CRT mode active\n"));
286 		break;
287 	}
288 	return B_OK;
289 }
290 
291 uint8 nm_general_output_read()
292 {
293 	uint8 size_outputs;
294 
295 	/* read panelsize and currently active outputs */
296 	size_outputs = ISAGRPHR(PANELCTRL1);
297 
298 	/* update noted currently active outputs if prudent:
299 	 * - tracks active output devices, even if the keyboard shortcut is used because
300 	 *   using that key will take the selected output devices out of DPMS sleep mode
301 	 *   if programmed via these bits;
302 	 * - when the shortcut key is not used, and DPMS was in a power-saving mode while
303 	 *   programmed via these bits, an output device will (still) be shut-off. */
304 	if (si->ps.card_type < NM2200)
305 	{
306 		/* both output devices do DPMS via these bits.
307 		 * if one of the bits is on we have a valid setting if no power-saving mode
308 		 * is active, or the keyboard shortcut key for selecting output devices has
309 		 * been used during power-saving mode. */
310 		if (size_outputs & 0x03) si->ps.outputs = (size_outputs & 0x03);
311 	}
312 	else
313 	{
314 		/* check if any power-saving mode active */
315 		if 	(!(ISASEQR(CLKMODE) & 0x20))
316 		{
317 			/* screen is on:
318 			 * we can 'safely' copy both output devices settings... */
319 			if (size_outputs & 0x03)
320 			{
321 				si->ps.outputs = (size_outputs & 0x03);
322 			}
323 			else
324 			{
325 				/* ... unless no output is active, as this is illegal then */
326 				si->ps.outputs = 0x02;
327 
328 				LOG(4, ("INIT: illegal outputmode detected, assuming internal mode!\n"));
329 			}
330 		}
331 		else
332 		{
333 			/* screen is off:
334 			 * only the internal panel does DPMS via these bits, so the external setting
335 			 * can always be copied */
336 			si->ps.outputs &= 0xfe;
337 			si->ps.outputs |= (size_outputs & 0x01);
338 			/* if the panel is on, we can note that (the shortcut key has been used) */
339 			if (size_outputs & 0x02) si->ps.outputs |= 0x02;
340 		}
341 	}
342 
343 	return ((size_outputs & 0xfc) | (si->ps.outputs & 0x03));
344 }
345 
346 /* basic change of card state from VGA to powergraphics -> should work from BIOS init state*/
347 static
348 status_t nm_general_bios_to_powergraphics()
349 {
350 	uint8 temp;
351 
352 	LOG(2, ("INIT: Skipping card coldstart!\n"));
353 
354 	/* turn off display */
355 	nm_crtc_dpms(false, false, false);
356 
357 	/* set card to 'enhanced' mode: (only VGA standard registers used for NeoMagic cards) */
358 	/* (keep) card enabled, set plain normal memory usage, no old VGA 'tricks' ... */
359 	ISACRTCW(MODECTL, 0xc3);
360 	/* ... plain sequential memory use, more than 64Kb RAM installed,
361 	 * switch to graphics mode ... */
362 	ISASEQW(MEMMODE, 0x0e);
363 	/* ... disable bitplane tweaking ... */
364 	/* note:
365 	 * NeoMagic cards have custom b4-b7 use in this register! */
366 	ISAGRPHW(ENSETRESET, 0x80);
367 	/* ... no logical function tweaking with display data, no data rotation ... */
368 	ISAGRPHW(DATAROTATE, 0x00);
369 	/* ... reset read map select to plane 0 ... */
370 	ISAGRPHW(READMAPSEL, 0x00);
371 	/* ... set standard mode ... */
372 	ISAGRPHW(MODE, 0x00);
373 	/* ... ISA framebuffer mapping is 64Kb window, switch to graphics mode (again),
374 	 * select standard adressing ... */
375 	ISAGRPHW(MISC, 0x05);
376 	/* ... disable bit masking ... */
377 	ISAGRPHW(BITMASK, 0xff);
378 	/* ... attributes are in color, switch to graphics mode (again) ... */
379 	ISAATBW(MODECTL, 0x01);
380 	/* ... set overscan color to black ... */
381 	ISAATBW(OSCANCOLOR, 0x00);
382 	/* ... enable all color planes ... */
383 	ISAATBW(COLPLANE_EN, 0x0f);
384 	/* ... reset horizontal pixelpanning ... */
385 	ISAATBW(HORPIXPAN, 0x00);
386 	/* ...  reset colorpalette groupselect bits ... */
387 	ISAATBW(COLSEL, 0x00);
388 	/* ... do unknown standard VGA register ... */
389 	/* note:
390 	 * NeoMagic cards have custom b6 use in this register! */
391 	ISAATBW(0x16, 0x01);
392 	/* ... and enable all four byteplanes. */
393 	ISASEQW(MAPMASK, 0x0f);
394 
395 	/* setup sequencer clocking mode */
396 	ISASEQW(CLKMODE, 0x21);
397 
398 	/* enable memory above 256Kb: set b4 (disables adress wraparound at 256Kb boundary) */
399 	ISAGRPHW(FBSTADDE, 0x10);
400 
401 	/* this register has influence on the CRTC framebuffer offset, so reset! */
402 	//fixme: investigate further...
403 	ISAGRPHW(0x15, 0x00);
404 
405 	/* enable fast PCI write bursts (b4-5) */
406 	temp = ((ISAGRPHR(IFACECTRL1) & 0x0f) | 0x30);
407 	/* we need to wait a bit or the card will mess-up it's register values.. */
408 	snooze(10);
409 	ISAGRPHW(IFACECTRL1, temp);
410 
411 	/* this speeds up RAM writes according to XFree driver */
412 //	fixme: don't touch until more is known: part of RAM or CORE PLL???
413 //	ISAGRPHW(SPEED, 0xc0);
414 
415 	/* turn on display */
416 	nm_crtc_dpms(true, true, true);
417 
418 	return B_OK;
419 }
420 
421 /* Check if mode virtual_size adheres to the cards _maximum_ contraints, and modify
422  * virtual_size to the nearest valid maximum for the mode on the card if not so.
423  * Then: check if virtual_width adheres to the cards _multiple_ constraints, and
424  * create mode slopspace if not so.
425  * We use acc multiple constraints here if we expect we can use acceleration, because
426  * acc constraints are worse than CRTC constraints.
427  *
428  * Mode slopspace is reflected in fbc->bytes_per_row BTW. */
429 status_t nm_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode)
430 {
431 	/* Note:
432 	 * This routine assumes that the CRTC memory pitch granularity is 'smaller than',
433 	 * or 'equals' the acceleration engine memory pitch granularity! */
434 
435 	uint32 video_pitch = 0;
436 	uint32 crtc_mask;
437 	uint8 depth = 8;
438 
439 	/* determine pixel multiple based on CRTC memory pitch constraints.
440 	 * (Note: Don't mix this up with CRTC timing contraints! Those are
441 	 *        multiples of 8 for horizontal, 1 for vertical timing.)
442 	 *
443 	 * CRTC pitch constraints are 'officially' the same for all Neomagic cards */
444 	switch (si->ps.card_type)
445 	{
446 	case NM2070:
447 		switch (target->space)
448 		{
449 			case B_CMAP8: crtc_mask = 0x07; depth =  8; break;
450 			/* Note for NM2070 only:
451 			 * The following depths have bandwidth trouble (pixel noise) with the
452 			 * 'official' crtc_masks (used as defaults below). Masks of 0x1f are
453 			 * needed (confirmed 15 and 16 bit spaces) to minimize this. */
454 			//fixme: doublecheck for NM2090 and NM2093: correct code if needed!
455 			case B_RGB15: crtc_mask = 0x1f; depth = 16; break;
456 			case B_RGB16: crtc_mask = 0x1f; depth = 16; break;
457 			case B_RGB24: crtc_mask = 0x1f; depth = 24; break;
458 			default:
459 				LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space));
460 				return B_ERROR;
461 		}
462 		break;
463 	default:
464 		switch (target->space)
465 		{
466 			case B_CMAP8: crtc_mask = 0x07; depth =  8; break;
467 			case B_RGB15: crtc_mask = 0x03; depth = 16; break;
468 			case B_RGB16: crtc_mask = 0x03; depth = 16; break;
469 			case B_RGB24: crtc_mask = 0x07; depth = 24; break;
470 			default:
471 				LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space));
472 				return B_ERROR;
473 		}
474 		break;
475 	}
476 
477 	/* check if we can setup this mode with acceleration: */
478 	*acc_mode = true;
479 
480 	/* pre-NM2200 cards don't support accelerated 24bit modes */
481 	if ((si->ps.card_type < NM2200) && (target->space == B_RGB24)) *acc_mode = false;
482 
483 	/* virtual_width */
484 	if (si->ps.card_type == NM2070)
485 	{
486 		/* confirmed NM2070 */
487 		if (target->virtual_width > 1024) *acc_mode = false;
488 	}
489 	else
490 	{
491 		/* confirmed for all cards */
492 		if (target->virtual_width > 1600) *acc_mode = false;
493 	}
494 
495 	/* virtual_height (confirmed NM2070, NM2097, NM2160 and NM2200 */
496 	if (target->virtual_height > 1024) *acc_mode = false;
497 
498 	/* now check virtual_size based on CRTC constraints and modify if needed */
499 //fixme: checkout cardspecs here!! (NM2160 can do 8192 _bytes_ at least (in theory))
500 	{
501 		/* virtual_width */
502 		switch(target->space)
503 		{
504 		case B_CMAP8:
505 			if (target->virtual_width > 16368)
506 				target->virtual_width = 16368;
507 			break;
508 		case B_RGB15_LITTLE:
509 		case B_RGB16_LITTLE:
510 			if (target->virtual_width > 8184)
511 				target->virtual_width = 8184;
512 			break;
513 		case B_RGB24_LITTLE:
514 			if (target->virtual_width > 5456)
515 				target->virtual_width = 5456;
516 			break;
517 		}
518 
519 		/* virtual_height: The only constraint here is the cards memory size which is
520 		 * checked later on in ProposeMode: virtual_height is adjusted then if needed.
521 		 * 'Limiting here' to the variable size that's at least available (uint16). */
522 		if (target->virtual_height > 65535) target->virtual_height = 65535;
523 	}
524 
525 	/* OK, now we know that virtual_width is valid, and it's needing no slopspace if
526 	 * it was confined above, so we can finally calculate safely if we need slopspace
527 	 * for this mode... */
528 	if (*acc_mode)
529 	{
530 		if (si->ps.card_type == NM2070)
531 		{
532 			uint32 acc_mask = 0;
533 
534 			/* determine pixel multiple based on 2D engine constraints */
535 			switch (target->space)
536 			{
537 				case B_CMAP8: acc_mask = 0x07; break;
538 				/* Note:
539 				 * The following depths have actual acc_masks of 0x03. 0x1f is used
540 				 * because on lower acc_masks more bandwidth trouble arises.
541 				 * (pixel noise) */
542 				//fixme: doublecheck for NM2090 and NM2093: correct code if needed!
543 				case B_RGB15: acc_mask = 0x1f; break;
544 				case B_RGB16: acc_mask = 0x1f; break;
545 			}
546 			video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask);
547 		}
548 		else
549 		{
550 			/* Note:
551 			 * We prefer unaccelerated modes above accelerated ones here if not enough
552 			 * RAM exists and the mode can be closer matched to the requested one if
553 			 * unaccelerated. We do this because of the large amount of slopspace
554 			 * sometimes needed here to keep a mode accelerated. */
555 
556 			uint32 mem_avail, bytes_X_height;
557 
558 			/* calculate amount of available memory */
559 			mem_avail = (si->ps.memory_size * 1024);
560 			if (si->settings.hardcursor) mem_avail -= si->ps.curmem_size;
561 			/* helper */
562 			bytes_X_height = (depth >> 3) * target->virtual_height;
563 
564 			/* Accelerated modes work with a table, there are very few fixed settings.. */
565 			if (target->virtual_width == 640) video_pitch = 640;
566 			else
567 				if (target->virtual_width <= 800)
568 				{
569 					if (((800 * bytes_X_height) > mem_avail) &&
570 						(target->virtual_width < (800 - crtc_mask)))
571 						*acc_mode = false;
572 					else
573 						video_pitch = 800;
574 				}
575 				else
576 					if (target->virtual_width <= 1024)
577 					{
578 						if (((1024 * bytes_X_height) > mem_avail) &&
579 							(target->virtual_width < (1024 - crtc_mask)))
580 							*acc_mode = false;
581 						else
582 							video_pitch = 1024;
583 					}
584 					else
585 						if (target->virtual_width <= 1152)
586 						{
587 							if (((1152 * bytes_X_height) > mem_avail) &&
588 								(target->virtual_width < (1152 - crtc_mask)))
589 								*acc_mode = false;
590 							else
591 								video_pitch = 1152;
592 						}
593 						else
594 							if (target->virtual_width <= 1280)
595 							{
596 								if (((1280 * bytes_X_height) > mem_avail) &&
597 									(target->virtual_width < (1280 - crtc_mask)))
598 									*acc_mode = false;
599 								else
600 									video_pitch = 1280;
601 							}
602 							else
603 								if (target->virtual_width <= 1600)
604 								{
605 									if (((1600 * bytes_X_height) > mem_avail) &&
606 										(target->virtual_width < (1600 - crtc_mask)))
607 										*acc_mode = false;
608 									else
609 										video_pitch = 1600;
610 								}
611 		}
612 	}
613 	if (!*acc_mode)
614 		video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
615 
616 	LOG(2,("INIT: memory pitch will be set to %d pixels for colorspace 0x%08x\n",
617 														video_pitch, target->space));
618 	if (target->virtual_width != video_pitch)
619 		LOG(2,("INIT: effective mode slopspace is %d pixels\n",
620 											(video_pitch - target->virtual_width)));
621 
622 	/* now calculate bytes_per_row for this mode */
623 	*bytes_per_row = video_pitch * (depth >> 3);
624 
625 	return B_OK;
626 }
627