xref: /haiku/src/add-ons/accelerants/neomagic/engine/nm_general.c (revision 67bce78b48ed6d01b5a8eef89f5694c372b7e0a1)
1 /* Author:
2    Rudolf Cornelissen 4/2003-4/2004
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 (NMBASE2,  0);
25 	DUMP_CFG (NMBASE1,  0);
26 	DUMP_CFG (NMBASE3,  0);
27 	DUMP_CFG (SUBSYSIDR, 0);
28 	DUMP_CFG (ROMBASE,   0);
29 	DUMP_CFG (CAP_PTR,   0);
30 	DUMP_CFG (INTCTRL,   0);
31 	DUMP_CFG (OPTION,    0);
32 	DUMP_CFG (NM_INDEX, 0);
33 	DUMP_CFG (NM_DATA,  0);
34 	DUMP_CFG (SUBSYSIDW, 0);
35 	DUMP_CFG (OPTION2,   G100);
36 	DUMP_CFG (OPTION3,   0);
37 	DUMP_CFG (OPTION4,   0);
38 	DUMP_CFG (PM_IDENT,  G100);
39 	DUMP_CFG (PM_CSR,    G100);
40 	DUMP_CFG (AGP_IDENT, 0);
41 	DUMP_CFG (AGP_STS,   0);
42 	DUMP_CFG (AGP_CMD,   0);
43 #undef DUMP_CFG
44 }
45 
46 status_t nm_general_powerup()
47 {
48 	status_t status;
49 
50 	LOG(1,("POWERUP: Neomagic (open)BeOS Accelerant 0.06-9 running.\n"));
51 
52 	/* detect card type and power it up */
53 	switch(CFGR(DEVID))
54 	{
55 	case 0x000110c8: //NM2070 ISA
56 		si->ps.card_type = NM2070;
57 		LOG(4,("POWERUP: Detected MagicGraph 128 (NM2070)\n"));
58 		break;
59 	case 0x000210c8: //NM2090 ISA
60 		si->ps.card_type = NM2090;
61 		LOG(4,("POWERUP: Detected MagicGraph 128V (NM2090)\n"));
62 		break;
63 	case 0x000310c8: //NM2093 ISA
64 		si->ps.card_type = NM2093;
65 		LOG(4,("POWERUP: Detected MagicGraph 128ZV (NM2093)\n"));
66 		break;
67 	case 0x008310c8: //NM2097 PCI
68 		si->ps.card_type = NM2097;
69 		LOG(4,("POWERUP: Detected MagicGraph 128ZV+ (NM2097)\n"));
70 		break;
71 	case 0x000410c8: //NM2160 PCI
72 		si->ps.card_type = NM2160;
73 		LOG(4,("POWERUP: Detected MagicGraph 128XD (NM2160)\n"));
74 		break;
75 	case 0x000510c8: //NM2200
76 		si->ps.card_type = NM2200;
77 		LOG(4,("POWERUP: Detected MagicMedia 256AV (NM2200)\n"));
78 		break;
79 	case 0x002510c8: //NM2230
80 		si->ps.card_type = NM2230;
81 		LOG(4,("POWERUP: Detected MagicMedia 256AV+ (NM2230)\n"));
82 		break;
83 	case 0x000610c8: //NM2360
84 		si->ps.card_type = NM2360;
85 		LOG(4,("POWERUP: Detected MagicMedia 256ZX (NM2360)\n"));
86 		break;
87 	case 0x001610c8: //NM2380
88 		si->ps.card_type = NM2380;
89 		LOG(4,("POWERUP: Detected MagicMedia 256XL+ (NM2380)\n"));
90 		break;
91 	default:
92 		LOG(8,("POWERUP: Failed to detect valid card 0x%08x\n",CFGR(DEVID)));
93 		return B_ERROR;
94 	}
95 
96 	/* power up the card */
97 	status = nmxxxx_general_powerup();
98 
99 	/* override memory detection if requested by user */
100 	if (si->settings.memory != 0)
101 		si->ps.memory_size = si->settings.memory;
102 
103 	return status;
104 }
105 
106 static status_t test_ram(void)
107 {
108 	uint32 value, offset;
109 	status_t result = B_OK;
110 
111 	/* make sure we don't corrupt the hardware cursor by using fbc.frame_buffer. */
112 	if (si->fbc.frame_buffer == NULL)
113 	{
114 		LOG(8,("INIT: test_ram detected NULL pointer.\n"));
115 		return B_ERROR;
116 	}
117 
118 	for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
119 	{
120 		/* write testpattern to cardRAM */
121 		((uint32 *)si->fbc.frame_buffer)[offset] = value;
122 		/* toggle testpattern */
123 		value = 0xffffffff - value;
124 	}
125 
126 	for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
127 	{
128 		/* readback and verify testpattern from cardRAM */
129 		if (((uint32 *)si->fbc.frame_buffer)[offset] != value) result = B_ERROR;
130 		/* toggle testpattern */
131 		value = 0xffffffff - value;
132 	}
133 	return result;
134 }
135 
136 /* NOTE:
137  * This routine *has* to be done *after* SetDispplayMode has been executed,
138  * or test results will not be representative!
139  * (CAS latency is dependant on nm setup on some (DRAM) boards) */
140 status_t nm_set_cas_latency()
141 {
142 	/* check current RAM access to see if we need to change anything */
143 	if (test_ram() == B_OK)
144 	{
145 		LOG(4,("INIT: RAM access OK.\n"));
146 		return B_OK;
147 	}
148 
149 	/* check if we read PINS at starttime so we have valid registersettings at our disposal */
150 	LOG(4,("INIT: RAM access errors; not fixable: missing coldstart specs.\n"));
151 	return B_ERROR;
152 }
153 
154 void nm_unlock()
155 {
156 	/* unlock cards GRAPHICS registers (any other value than 0x26 should lock it again) */
157     ISAGRPHW(GRPHXLOCK, 0x26);
158 }
159 
160 static status_t nmxxxx_general_powerup()
161 {
162 	uint8 temp;
163 //	status_t result;
164 
165 	LOG(4, ("INIT: powerup\n"));
166 	if (si->settings.logmask & 0x80000000) nm_dump_configuration_space();
167 
168 	/* set ISA registermapping to VGA colormode */
169 	temp = (ISARB(MISCR) | 0x01);
170 	/* we need to wait a bit or the card will mess-up it's register values.. */
171 	snooze(10);
172 	ISAWB(MISCW, temp);
173 
174 	/* unlock cards GRAPHICS registers (any other value than 0x26 should lock it again) */
175     ISAGRPHW(GRPHXLOCK, 0x26);
176 
177 	/* unlock cards CRTC registers */
178 //don't touch: most cards get into trouble on this!
179 //	ISAGRPHW(GENLOCK, 0x00);
180 
181 	/* initialize the shared_info struct */
182 	set_specs();
183 	/* log the struct settings */
184 	dump_specs();
185 
186 	/* activate PCI access: b7 = framebuffer, b6 = registers */
187 	ISAGRPHW(IFACECTRL2, 0xc0);
188 
189 	/* disable VGA-mode cursor (just to be sure) */
190 	ISACRTCW(VGACURCTRL, 0x00);
191 
192 	/* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */
193 	/*if (si->settings.usebios || (result != B_OK)) */return nm_general_bios_to_powergraphics();
194 
195 	/*power up the PLLs,LUT,DAC*/
196 	LOG(2,("INIT: powerup\n"));
197 
198 	/* turn off both displays and the hardcursor (also disables transfers) */
199 	nm_crtc_dpms(false, false, false);
200 	nm_crtc_cursor_hide();
201 
202 	/* setup sequencer clocking mode */
203 	ISASEQW(CLKMODE, 0x21);
204 
205 	/* G100 SGRAM and SDRAM use external pix and dac refs, do *not* activate internals!
206 	 * (this would create electrical shortcuts,
207 	 * resulting in extra chip heat and distortions visible on screen */
208 	/* set voltage reference - using DAC reference block partly */
209 //	DXIW(VREFCTRL,0x03);
210 	/* wait for 100ms for voltage reference to stabilize */
211 	delay(100000);
212 	/* power up the SYSPLL */
213 //	CFGW(OPTION,CFGR(OPTION)|0x20);
214 	/* power up the PIXPLL */
215 //	DXIW(PIXCLKCTRL,0x08);
216 
217 	/* disable pixelclock oscillations before switching on CLUT */
218 //	DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
219 	/* disable 15bit mode CLUT-overlay function */
220 //	DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
221 	/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
222 //	DXIW(MISCCTRL,0x1b);
223 //	snooze(250);
224 	/* re-enable pixelclock oscillations */
225 //	DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
226 
227 	/*make sure card is in powergraphics mode*/
228 //	VGAW_I(CRTCEXT,3,0x80);
229 
230 	/*set the system clocks to powergraphics speed*/
231 //	LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
232 //	g100_dac_set_sys_pll();
233 
234 	/* 'official' RAM initialisation */
235 //	LOG(2,("INIT: RAM init\n"));
236 	/* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
237 //	ACCW(PLNWT,0x00000000);
238 //	ACCW(PLNWT,0xffffffff);
239 	/* program memory control waitstates */
240 //	ACCW(MCTLWTST,si->ps.mctlwtst_reg);
241 	/* set memory configuration including:
242 	 * - no split framebuffer.
243 	 * - Mark says b14 (G200) should be done also though not defined for G100 in spec,
244 	 * - b3 v3_mem_type was included by Mark for memconfig setup: but looks like not defined */
245 //	CFGW(OPTION,(CFGR(OPTION)&0xFFFF8FFF) | ((si->ps.v3_mem_type & 0x04) << 10));
246 	/* set memory buffer type:
247 	 * - Mark says: if((v3_mem_type & 0x03) == 0x03) then do not or-in bits in option2;
248 	 *   but looks like v3_mem_type b1 is not defined,
249 	 * - Mark also says: place v3_mem_type b1 in option2 bit13 (if not 0x03) but b13 = reserved. */
250 //	CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|((si->ps.v3_mem_type & 0x01) << 12));
251 	/* set RAM read tap delay */
252 //	CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFFFF0) | ((si->ps.v3_mem_type & 0xf0) >> 4));
253 	/* wait 200uS minimum */
254 //	snooze(250);
255 
256 	/* reset memory (MACCESS is a write only register!) */
257 //	ACCW(MACCESS, 0x00000000);
258 	/* select JEDEC reset method */
259 //	ACCW(MACCESS, 0x00004000);
260 	/* perform actual RAM reset */
261 //	ACCW(MACCESS, 0x0000c000);
262 //	snooze(250);
263 	/* start memory refresh */
264 //	CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
265 	/* set memory control waitstate again AFTER the RAM reset */
266 //	ACCW(MCTLWTST,si->ps.mctlwtst_reg);
267 	/* end 'official' RAM initialisation. */
268 
269 	/* Bus parameters: enable retries, use advanced read */
270 //	CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29)));
271 
272 	/*enable writing to crtc registers*/
273 //	VGAW_I(CRTC,0x11,0);
274 
275 	/* turn on display */
276 	nm_crtc_dpms(true, true, true);
277 
278 	return B_OK;
279 }
280 
281 status_t nm_general_output_select()
282 {
283 	/* log currently selected output */
284 	switch (nm_general_output_read())
285 	{
286 	case 0x01:
287 		LOG(2, ("INIT: external CRT only mode active\n"));
288 		break;
289 	case 0x02:
290 		LOG(2, ("INIT: internal LCD only mode active\n"));
291 		break;
292 	case 0x03:
293 		LOG(2, ("INIT: simultaneous LCD/CRT mode active\n"));
294 		break;
295 	}
296 	return B_OK;
297 }
298 
299 uint8 nm_general_output_read()
300 {
301 	uint8 output;
302 
303 	output = (ISAGRPHR(PANELCTRL1) & 0x03);
304 
305 	if (output == 0)
306 	{
307 		/* using 'failsafe' mode: the flatpanel needs all the protection it can get... */
308 		LOG(4, ("INIT: illegal outputmode detected, reporting internal mode!\n"));
309 		output = 2;
310 	}
311 
312 	return output;
313 }
314 
315 /* basic change of card state from VGA to powergraphics -> should work from BIOS init state*/
316 static
317 status_t nm_general_bios_to_powergraphics()
318 {
319 	uint8 temp;
320 
321 	LOG(2, ("INIT: Skipping card coldstart!\n"));
322 
323 	/* turn off display */
324 	nm_crtc_dpms(false, false, false);
325 
326 	/* set card to 'enhanced' mode: (only VGA standard registers used for NeoMagic cards) */
327 	/* (keep) card enabled, set plain normal memory usage, no old VGA 'tricks' ... */
328 	ISACRTCW(MODECTL, 0xc3);
329 	/* ... plain sequential memory use, more than 64Kb RAM installed,
330 	 * switch to graphics mode ... */
331 	ISASEQW(MEMMODE, 0x0e);
332 	/* ... disable bitplane tweaking ... */
333 	/* note:
334 	 * NeoMagic cards have custom b4-b7 use in this register! */
335 	ISAGRPHW(ENSETRESET, 0x80);
336 	/* ... no logical function tweaking with display data, no data rotation ... */
337 	ISAGRPHW(DATAROTATE, 0x00);
338 	/* ... reset read map select to plane 0 ... */
339 	ISAGRPHW(READMAPSEL, 0x00);
340 	/* ... set standard mode ... */
341 	ISAGRPHW(MODE, 0x00);
342 	/* ... ISA framebuffer mapping is 64Kb window, switch to graphics mode (again),
343 	 * select standard adressing ... */
344 	ISAGRPHW(MISC, 0x05);
345 	/* ... disable bit masking ... */
346 	ISAGRPHW(BITMASK, 0xff);
347 	/* ... attributes are in color, switch to graphics mode (again) ... */
348 	ISAATBW(MODECTL, 0x01);
349 	/* ... set overscan color to black ... */
350 	ISAATBW(OSCANCOLOR, 0x00);
351 	/* ... enable all color planes ... */
352 	ISAATBW(COLPLANE_EN, 0x0f);
353 	/* ... reset horizontal pixelpanning ... */
354 	ISAATBW(HORPIXPAN, 0x00);
355 	/* ...  reset colorpalette groupselect bits ... */
356 	ISAATBW(COLSEL, 0x00);
357 	/* ... do unknown standard VGA register ... */
358 	/* note:
359 	 * NeoMagic cards have custom b6 use in this register! */
360 	ISAATBW(0x16, 0x01);
361 	/* ... and enable all four byteplanes. */
362 	ISASEQW(MAPMASK, 0x0f);
363 
364 	/* setup sequencer clocking mode */
365 	ISASEQW(CLKMODE, 0x21);
366 
367 	/* enable memory above 256Kb: set b4 (disables adress wraparound at 256Kb boundary) */
368 	ISAGRPHW(FBSTADDE, 0x10);
369 
370 	/* this register has influence on the CRTC framebuffer offset, so reset! */
371 	//fixme: investigate further...
372 	ISAGRPHW(0x15, 0x00);
373 
374 	/* enable fast PCI write bursts (b4-5) */
375 	temp = ((ISAGRPHR(IFACECTRL1) & 0x0f) | 0x30);
376 	/* we need to wait a bit or the card will mess-up it's register values.. */
377 	snooze(10);
378 	ISAGRPHW(IFACECTRL1, temp);
379 
380 	/* this speeds up RAM writes according to XFree driver */
381 //	fixme: don't touch until more is known: part of RAM or CORE PLL???
382 //	ISAGRPHW(SPEED, 0xc0);
383 
384 	/* turn on display */
385 	nm_crtc_dpms(true, true, true);
386 
387 	return B_OK;
388 }
389 
390 /* Check if mode virtual_size adheres to the cards _maximum_ contraints, and modify
391  * virtual_size to the nearest valid maximum for the mode on the card if not so.
392  * Then: check if virtual_width adheres to the cards _multiple_ constraints, and
393  * create mode slopspace if not so.
394  * We use acc multiple constraints here if we expect we can use acceleration, because
395  * acc constraints are worse than CRTC constraints.
396  *
397  * Mode slopspace is reflected in fbc->bytes_per_row BTW. */
398 status_t nm_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode)
399 {
400 	/* Note:
401 	 * This routine assumes that the CRTC memory pitch granularity is 'smaller than',
402 	 * or 'equals' the acceleration engine memory pitch granularity! */
403 
404 	uint32 video_pitch = 0;
405 	uint32 crtc_mask;
406 	uint8 depth = 8;
407 
408 	/* determine pixel multiple based on CRTC memory pitch constraints.
409 	 * (Note: Don't mix this up with CRTC timing contraints! Those are
410 	 *        multiples of 8 for horizontal, 1 for vertical timing.)
411 	 *
412 	 * CRTC pitch constraints are the same for all Neomagic cards */
413 	switch (target->space)
414 	{
415 		case B_CMAP8: crtc_mask = 0x07; depth =  8; break;
416 		case B_RGB15: crtc_mask = 0x03; depth = 16; break;
417 		case B_RGB16: crtc_mask = 0x03; depth = 16; break;
418 		case B_RGB24: crtc_mask = 0x07; depth = 24; break;
419 		default:
420 			LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space));
421 			return B_ERROR;
422 	}
423 
424 	/* check if we can setup this mode with acceleration:
425 	 * constraints are same for all cards */
426 	*acc_mode = true;
427 
428 	switch (si->ps.card_type)
429 	{
430 	case NM2097:
431 	case NM2160:
432 		if (target->space != B_RGB24) *acc_mode = true;
433 		else *acc_mode = false;
434 		break;
435 	default:
436 		*acc_mode = false;
437 		break;
438 	}
439 
440 	/* virtual_width */
441 	if (target->virtual_width > 1600) *acc_mode = false;
442 
443 	/* virtual_height */
444 	if (si->ps.card_type < NM2200)
445 	{
446 		/* confirmed NM2097 and NM2160 */
447 		if (target->virtual_height > 1024) *acc_mode = false;
448 	}
449 	else
450 	{
451 		/* fixme: needs confirmation, assuming this height will still work.. */
452 		if (target->virtual_height > 2048) *acc_mode = false;
453 	}
454 
455 	/* now check virtual_size based on CRTC constraints and modify if needed */
456 //fixme: checkout cardspecs here!! (NM2160 can do 8192 _bytes_ at least (in theory))
457 	{
458 		/* virtual_width */
459 		switch(target->space)
460 		{
461 		case B_CMAP8:
462 			if (target->virtual_width > 16368)
463 				target->virtual_width = 16368;
464 			break;
465 		case B_RGB15_LITTLE:
466 		case B_RGB16_LITTLE:
467 			if (target->virtual_width > 8184)
468 				target->virtual_width = 8184;
469 			break;
470 		case B_RGB24_LITTLE:
471 			if (target->virtual_width > 5456)
472 				target->virtual_width = 5456;
473 			break;
474 		}
475 
476 		/* virtual_height: The only constraint here is the cards memory size which is
477 		 * checked later on in ProposeMode: virtual_height is adjusted then if needed.
478 		 * 'Limiting here' to the variable size that's at least available (uint16). */
479 		if (target->virtual_height > 65535) target->virtual_height = 65535;
480 	}
481 
482 	/* OK, now we know that virtual_width is valid, and it's needing no slopspace if
483 	 * it was confined above, so we can finally calculate safely if we need slopspace
484 	 * for this mode... */
485 	/* note:
486 	 * we prefer unaccelerated modes above accelerated ones if not enough RAM exists
487 	 * and the mode can be closer matched to the requested one if unaccelerated. */
488 	if (*acc_mode)
489 	{
490 		uint32 mem_avail, bytes_X_height;
491 
492 		/* calculate amount of available memory */
493 		mem_avail = (si->ps.memory_size * 1024);
494 		if (si->settings.hardcursor) mem_avail -= si->ps.curmem_size;
495 		/* helper */
496 		bytes_X_height = (depth >> 3) * target->virtual_height;
497 
498 		/* Accelerated modes work with a table, there are very few fixed settings.. */
499 		if (target->virtual_width == 640) video_pitch = 640;
500 		else
501 			if (target->virtual_width <= 800)
502 			{
503 				if (((800 * bytes_X_height) > mem_avail) &&
504 					(target->virtual_width < (800 - crtc_mask)))
505 					*acc_mode = false;
506 				else
507 					video_pitch = 800;
508 			}
509 			else
510 				if (target->virtual_width <= 1024)
511 				{
512 					if (((1024 * bytes_X_height) > mem_avail) &&
513 						(target->virtual_width < (1024 - crtc_mask)))
514 						*acc_mode = false;
515 					else
516 						video_pitch = 1024;
517 				}
518 				else
519 					if (target->virtual_width <= 1152)
520 					{
521 						if (((1152 * bytes_X_height) > mem_avail) &&
522 							(target->virtual_width < (1152 - crtc_mask)))
523 							*acc_mode = false;
524 						else
525 							video_pitch = 1152;
526 					}
527 					else
528 						if (target->virtual_width <= 1280)
529 						{
530 							if (((1280 * bytes_X_height) > mem_avail) &&
531 								(target->virtual_width < (1280 - crtc_mask)))
532 								*acc_mode = false;
533 							else
534 								video_pitch = 1280;
535 						}
536 						else
537 							if (target->virtual_width <= 1600)
538 							{
539 								if (((1600 * bytes_X_height) > mem_avail) &&
540 									(target->virtual_width < (1600 - crtc_mask)))
541 									*acc_mode = false;
542 								else
543 									video_pitch = 1600;
544 							}
545 	}
546 	if (!*acc_mode)
547 		video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
548 
549 	LOG(2,("INIT: memory pitch will be set to %d pixels for colorspace 0x%08x\n",
550 														video_pitch, target->space));
551 	if (target->virtual_width != video_pitch)
552 		LOG(2,("INIT: effective mode slopspace is %d pixels\n",
553 											(video_pitch - target->virtual_width)));
554 
555 	/* now calculate bytes_per_row for this mode */
556 	*bytes_per_row = video_pitch * (depth >> 3);
557 
558 	return B_OK;
559 }
560