xref: /haiku/src/add-ons/accelerants/neomagic/engine/nm_general.c (revision aa94570a34695672df9b47adda2257f75d8da880)
1 /* Author:
2    Rudolf Cornelissen 4/2003-1/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-1 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 static status_t nmxxxx_general_powerup()
155 {
156 	uint8 temp;
157 //	status_t result;
158 
159 	LOG(4, ("INIT: powerup\n"));
160 	if (si->settings.logmask & 0x80000000) nm_dump_configuration_space();
161 
162 	/* set ISA registermapping to VGA colormode */
163 	temp = (ISARB(MISCR) | 0x01);
164 	/* we need to wait a bit or the card will mess-up it's register values.. */
165 	snooze(10);
166 	ISAWB(MISCW, temp);
167 
168 	/* unlock cards GRAPHICS registers (any other value than 0x26 should lock it again) */
169     ISAGRPHW(GRPHXLOCK, 0x26);
170 
171 	/* unlock cards CRTC registers */
172 //don't touch: most cards get into trouble on this!
173 //	ISAGRPHW(GENLOCK, 0x00);
174 
175 	/* initialize the shared_info struct */
176 	set_specs();
177 	/* log the struct settings */
178 	dump_specs();
179 
180 	/* activate PCI access: b7 = framebuffer, b6 = registers */
181 	ISAGRPHW(IFACECTRL, 0xc0);
182 
183 	/* disable VGA-mode cursor (just to be sure) */
184 	ISACRTCW(VGACURCTRL, 0x00);
185 
186 	/* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */
187 	/*if (si->settings.usebios || (result != B_OK)) */return nm_general_bios_to_powergraphics();
188 
189 	/*power up the PLLs,LUT,DAC*/
190 	LOG(2,("INIT: powerup\n"));
191 
192 	/* turn off both displays and the hardcursor (also disables transfers) */
193 	nm_crtc_dpms(false, false, false);
194 	nm_crtc_cursor_hide();
195 
196 	/* setup sequencer clocking mode */
197 	ISASEQW(CLKMODE, 0x21);
198 
199 	/* G100 SGRAM and SDRAM use external pix and dac refs, do *not* activate internals!
200 	 * (this would create electrical shortcuts,
201 	 * resulting in extra chip heat and distortions visible on screen */
202 	/* set voltage reference - using DAC reference block partly */
203 //	DXIW(VREFCTRL,0x03);
204 	/* wait for 100ms for voltage reference to stabilize */
205 	delay(100000);
206 	/* power up the SYSPLL */
207 //	CFGW(OPTION,CFGR(OPTION)|0x20);
208 	/* power up the PIXPLL */
209 //	DXIW(PIXCLKCTRL,0x08);
210 
211 	/* disable pixelclock oscillations before switching on CLUT */
212 //	DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
213 	/* disable 15bit mode CLUT-overlay function */
214 //	DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
215 	/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
216 //	DXIW(MISCCTRL,0x1b);
217 //	snooze(250);
218 	/* re-enable pixelclock oscillations */
219 //	DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
220 
221 	/*make sure card is in powergraphics mode*/
222 //	VGAW_I(CRTCEXT,3,0x80);
223 
224 	/*set the system clocks to powergraphics speed*/
225 //	LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
226 //	g100_dac_set_sys_pll();
227 
228 	/* 'official' RAM initialisation */
229 //	LOG(2,("INIT: RAM init\n"));
230 	/* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
231 //	ACCW(PLNWT,0x00000000);
232 //	ACCW(PLNWT,0xffffffff);
233 	/* program memory control waitstates */
234 //	ACCW(MCTLWTST,si->ps.mctlwtst_reg);
235 	/* set memory configuration including:
236 	 * - no split framebuffer.
237 	 * - Mark says b14 (G200) should be done also though not defined for G100 in spec,
238 	 * - b3 v3_mem_type was included by Mark for memconfig setup: but looks like not defined */
239 //	CFGW(OPTION,(CFGR(OPTION)&0xFFFF8FFF) | ((si->ps.v3_mem_type & 0x04) << 10));
240 	/* set memory buffer type:
241 	 * - Mark says: if((v3_mem_type & 0x03) == 0x03) then do not or-in bits in option2;
242 	 *   but looks like v3_mem_type b1 is not defined,
243 	 * - Mark also says: place v3_mem_type b1 in option2 bit13 (if not 0x03) but b13 = reserved. */
244 //	CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|((si->ps.v3_mem_type & 0x01) << 12));
245 	/* set RAM read tap delay */
246 //	CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFFFF0) | ((si->ps.v3_mem_type & 0xf0) >> 4));
247 	/* wait 200uS minimum */
248 //	snooze(250);
249 
250 	/* reset memory (MACCESS is a write only register!) */
251 //	ACCW(MACCESS, 0x00000000);
252 	/* select JEDEC reset method */
253 //	ACCW(MACCESS, 0x00004000);
254 	/* perform actual RAM reset */
255 //	ACCW(MACCESS, 0x0000c000);
256 //	snooze(250);
257 	/* start memory refresh */
258 //	CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
259 	/* set memory control waitstate again AFTER the RAM reset */
260 //	ACCW(MCTLWTST,si->ps.mctlwtst_reg);
261 	/* end 'official' RAM initialisation. */
262 
263 	/* Bus parameters: enable retries, use advanced read */
264 //	CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29)));
265 
266 	/*enable writing to crtc registers*/
267 //	VGAW_I(CRTC,0x11,0);
268 
269 	/* turn on display */
270 	nm_crtc_dpms(true, true, true);
271 
272 	return B_OK;
273 }
274 
275 status_t nm_general_output_select()
276 {
277 	/* log currently selected output */
278 	switch (nm_general_output_read())
279 	{
280 	case 0x01:
281 		LOG(2, ("INIT: external CRT only mode active\n"));
282 		break;
283 	case 0x02:
284 		LOG(2, ("INIT: internal LCD only mode active\n"));
285 		break;
286 	case 0x03:
287 		LOG(2, ("INIT: simultaneous LCD/CRT mode active\n"));
288 		break;
289 	}
290 	return B_OK;
291 }
292 
293 uint8 nm_general_output_read()
294 {
295 	uint8 output;
296 
297 	output = (ISAGRPHR(PANELCTRL1) & 0x03);
298 
299 	if (output == 0)
300 	{
301 		/* using 'failsafe' mode: the flatpanel needs all the protection it can get... */
302 		LOG(4, ("INIT: illegal outputmode detected, reporting internal mode!\n"));
303 		output = 2;
304 	}
305 
306 	return output;
307 }
308 
309 /* basic change of card state from VGA to powergraphics -> should work from BIOS init state*/
310 static
311 status_t nm_general_bios_to_powergraphics()
312 {
313 	LOG(2, ("INIT: Skipping card coldstart!\n"));
314 
315 	/* turn off display */
316 	nm_crtc_dpms(false, false, false);
317 
318 	/* set card to 'enhanced' mode: (only VGA standard registers used for NeoMagic cards) */
319 	/* (keep) card enabled, set plain normal memory usage, no old VGA 'tricks' ... */
320 	ISACRTCW(MODECTL, 0xc3);
321 	/* ... plain sequential memory use, more than 64Kb RAM installed,
322 	 * switch to graphics mode ... */
323 	ISASEQW(MEMMODE, 0x0e);
324 	/* ... disable bitplane tweaking ... */
325 	ISAGRPHW(ENSETRESET, 0x00);
326 	/* ... no logical function tweaking with display data, no data rotation ... */
327 	ISAGRPHW(DATAROTATE, 0x00);
328 	/* ... reset read map select to plane 0 ... */
329 	ISAGRPHW(READMAPSEL, 0x00);
330 	/* ... set standard mode ... */
331 	ISAGRPHW(MODE, 0x00);
332 	/* ... ISA framebuffer mapping is 64Kb window, switch to graphics mode (again),
333 	 * select standard adressing ... */
334 	ISAGRPHW(MISC, 0x05);
335 	/* ... disable bit masking ... */
336 	ISAGRPHW(BITMASK, 0xff);
337 	/* ... attributes are in color, switch to graphics mode (again) ... */
338 	ISAATBW(MODECTL, 0x01);
339 	/* ... set overscan color to black ... */
340 	ISAATBW(OSCANCOLOR, 0x00);
341 	/* ... enable all color planes ... */
342 	ISAATBW(COLPLANE_EN, 0x0f);
343 	/* ... reset horizontal pixelpanning ... */
344 	ISAATBW(HORPIXPAN, 0x00);
345 	/* ...  and reset colorpalette groupselect bits. */
346 	ISAATBW(COLSEL, 0x00);
347 
348 	/* setup sequencer clocking mode */
349 	ISASEQW(CLKMODE, 0x21);
350 
351 	/* enable memory above 256Kb: set b4 (disables adress wraparound at 256Kb boundary) */
352 	ISAGRPHW(FBSTADDE, 0x10);
353 
354 	/* turn on display */
355 	nm_crtc_dpms(true, true, true);
356 
357 	return B_OK;
358 }
359 
360 /* Check if mode virtual_size adheres to the cards _maximum_ contraints, and modify
361  * virtual_size to the nearest valid maximum for the mode on the card if not so.
362  * Then: check if virtual_width adheres to the cards _multiple_ constraints, and
363  * create mode slopspace if not so.
364  * We use acc multiple constraints here if we expect we can use acceleration, because
365  * acc constraints are worse than CRTC constraints.
366  *
367  * Mode slopspace is reflected in fbc->bytes_per_row BTW. */
368 status_t nm_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode)
369 {
370 	/* Note:
371 	 * This routine assumes that the CRTC memory pitch granularity is 'smaller than',
372 	 * or 'equals' the acceleration engine memory pitch granularity! */
373 
374 	uint32 video_pitch;
375 	uint32 acc_mask, crtc_mask;
376 	uint8 depth = 8;
377 
378 //fixme: checkout the acc pitch constraints for all cards...
379 	/* determine pixel multiple based on 2D/3D engine constraints */
380 	switch (si->ps.card_type)
381 	{
382 /*	case G100:
383 		switch (target->space)
384 		{
385 			case B_CMAP8: acc_mask = 0x7f; depth =  8; break;
386 			case B_RGB15: acc_mask = 0x3f; depth = 16; break;
387 			case B_RGB16: acc_mask = 0x3f; depth = 16; break;
388 			case B_RGB24: acc_mask = 0x7f; depth = 24; break;
389 			default:
390 				LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space));
391 				return B_ERROR;
392 		}
393 		break;
394 */	default:
395 		/* see G100 and up specs:
396 		 * these cards can do 2D as long as multiples of 32 are used.
397 		 * (Note: don't mix this up with adress linearisation!) */
398 		switch (target->space)
399 		{
400 			case B_CMAP8: depth =  8; break;
401 			case B_RGB15: depth = 16; break;
402 			case B_RGB16: depth = 16; break;
403 			case B_RGB24: depth = 24; break;
404 			default:
405 				LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space));
406 				return B_ERROR;
407 		}
408 //assuming accpitch = 32 for now..
409 		acc_mask = 0x1f;
410 		break;
411 	}
412 
413 	/* determine pixel multiple based on CRTC memory pitch constraints.
414 	 * (Note: Don't mix this up with CRTC timing contraints! Those are
415 	 *        multiples of 8 for horizontal, 1 for vertical timing.)
416 	 *
417 	 * CRTC pitch constraints are the same for all Neomagic cards */
418 	switch (target->space)
419 	{
420 		case B_CMAP8: crtc_mask = 0x07; break;
421 		case B_RGB15: crtc_mask = 0x03; break;
422 		case B_RGB16: crtc_mask = 0x03; break;
423 		case B_RGB24: crtc_mask = 0x07; break;
424 		default:
425 			LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space));
426 			return B_ERROR;
427 	}
428 
429 	/* check if we can setup this mode with acceleration:
430 	 * Max sizes need to adhere to both the acceleration engine _and_ the CRTC constraints! */
431 	*acc_mode = true;
432 	/* check virtual_width */
433 	switch (si->ps.card_type)
434 	{
435 	case G100:
436 		/* acc constraint: */
437 		if (target->virtual_width > 2048) *acc_mode = false;
438 		break;
439 	default:
440 		/* G200-G550 */
441 		/* acc constraint: */
442 		if (target->virtual_width > 4096) *acc_mode = false;
443 		/* for 32bit mode a lower CRTC1 restriction applies! */
444 //		if ((target->space == B_RGB32_LITTLE) && (target->virtual_width > (4092 & ~acc_mask)))
445 //			*acc_mode = false;
446 		break;
447 	}
448 	/* virtual_height */
449 	if (target->virtual_height > 2048) *acc_mode = false;
450 
451 //fixme: (temp)
452 *acc_mode = false;
453 
454 	/* now check virtual_size based on CRTC constraints,
455 	 * making sure virtual_width stays within the 'mask' constraint: which is only
456 	 * nessesary because of an extra constraint in MIL1/2 cards that exists here. */
457 
458 //fixme: checkout cardspecs here!!
459 
460 	{
461 		/* virtual_width */
462 		//fixme for CRTC2 (identical on all G400+ cards):
463 		//16bit mode: max. virtual_width == 16352 (no extra mask needed);
464 		//32bit mode: max. virtual_width == 8176 (no extra mask needed);
465 		//other colordepths are unsupported on CRTC2.
466 		switch(target->space)
467 		{
468 		case B_CMAP8:
469 			if (target->virtual_width > (16368 & ~crtc_mask))
470 				target->virtual_width = (16368 & ~crtc_mask);
471 			break;
472 		case B_RGB15_LITTLE:
473 		case B_RGB16_LITTLE:
474 			if (target->virtual_width > (8184 & ~crtc_mask))
475 				target->virtual_width = (8184 & ~crtc_mask);
476 			break;
477 		case B_RGB24_LITTLE:
478 			if (target->virtual_width > (5456 & ~crtc_mask))
479 				target->virtual_width = (5456 & ~crtc_mask);
480 			break;
481 		}
482 
483 		/* virtual_height: The only constraint here is the cards memory size which is
484 		 * checked later on in ProposeMode: virtual_height is adjusted then if needed.
485 		 * 'Limiting here' to the variable size that's at least available (uint16). */
486 		if (target->virtual_height > 65535) target->virtual_height = 65535;
487 	}
488 
489 	/* OK, now we know that virtual_width is valid, and it's needing no slopspace if
490 	 * it was confined above, so we can finally calculate safely if we need slopspace
491 	 * for this mode... */
492 	if (*acc_mode)
493 		video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask);
494 	else
495 		video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
496 
497 	LOG(2,("INIT: memory pitch will be set to %d pixels for colorspace 0x%08x\n",
498 														video_pitch, target->space));
499 	if (target->virtual_width != video_pitch)
500 		LOG(2,("INIT: effective mode slopspace is %d pixels\n",
501 											(video_pitch - target->virtual_width)));
502 
503 	/* now calculate bytes_per_row for this mode */
504 	*bytes_per_row = video_pitch * (depth >> 3);
505 
506 	return B_OK;
507 }
508