/* Author: Rudolf Cornelissen 4/2003-1/2004 */ #define MODULE_BIT 0x00008000 #include "nm_std.h" static status_t test_ram(void); static status_t nmxxxx_general_powerup (void); static status_t nm_general_bios_to_powergraphics(void); static void nm_dump_configuration_space (void) { #define DUMP_CFG(reg, type) if (si->ps.card_type >= type) do { \ uint32 value = CFGR(reg); \ MSG(("configuration_space 0x%02x %20s 0x%08x\n", \ NMCFG_##reg, #reg, value)); \ } while (0) DUMP_CFG (DEVID, 0); DUMP_CFG (DEVCTRL, 0); DUMP_CFG (CLASS, 0); DUMP_CFG (HEADER, 0); DUMP_CFG (NMBASE2, 0); DUMP_CFG (NMBASE1, 0); DUMP_CFG (NMBASE3, 0); DUMP_CFG (SUBSYSIDR, 0); DUMP_CFG (ROMBASE, 0); DUMP_CFG (CAP_PTR, 0); DUMP_CFG (INTCTRL, 0); DUMP_CFG (OPTION, 0); DUMP_CFG (NM_INDEX, 0); DUMP_CFG (NM_DATA, 0); DUMP_CFG (SUBSYSIDW, 0); DUMP_CFG (OPTION2, G100); DUMP_CFG (OPTION3, 0); DUMP_CFG (OPTION4, 0); DUMP_CFG (PM_IDENT, G100); DUMP_CFG (PM_CSR, G100); DUMP_CFG (AGP_IDENT, 0); DUMP_CFG (AGP_STS, 0); DUMP_CFG (AGP_CMD, 0); #undef DUMP_CFG } status_t nm_general_powerup() { status_t status; LOG(1,("POWERUP: Neomagic (open)BeOS Accelerant 0.06-1 running.\n")); /* detect card type and power it up */ switch(CFGR(DEVID)) { case 0x000110c8: //NM2070 ISA si->ps.card_type = NM2070; LOG(4,("POWERUP: Detected MagicGraph 128 (NM2070)\n")); break; case 0x000210c8: //NM2090 ISA si->ps.card_type = NM2090; LOG(4,("POWERUP: Detected MagicGraph 128V (NM2090)\n")); break; case 0x000310c8: //NM2093 ISA si->ps.card_type = NM2093; LOG(4,("POWERUP: Detected MagicGraph 128ZV (NM2093)\n")); break; case 0x008310c8: //NM2097 PCI si->ps.card_type = NM2097; LOG(4,("POWERUP: Detected MagicGraph 128ZV+ (NM2097)\n")); break; case 0x000410c8: //NM2160 PCI si->ps.card_type = NM2160; LOG(4,("POWERUP: Detected MagicGraph 128XD (NM2160)\n")); break; case 0x000510c8: //NM2200 si->ps.card_type = NM2200; LOG(4,("POWERUP: Detected MagicMedia 256AV (NM2200)\n")); break; case 0x002510c8: //NM2230 si->ps.card_type = NM2230; LOG(4,("POWERUP: Detected MagicMedia 256AV+ (NM2230)\n")); break; case 0x000610c8: //NM2360 si->ps.card_type = NM2360; LOG(4,("POWERUP: Detected MagicMedia 256ZX (NM2360)\n")); break; case 0x001610c8: //NM2380 si->ps.card_type = NM2380; LOG(4,("POWERUP: Detected MagicMedia 256XL+ (NM2380)\n")); break; default: LOG(8,("POWERUP: Failed to detect valid card 0x%08x\n",CFGR(DEVID))); return B_ERROR; } /* power up the card */ status = nmxxxx_general_powerup(); /* override memory detection if requested by user */ if (si->settings.memory != 0) si->ps.memory_size = si->settings.memory; return status; } static status_t test_ram(void) { uint32 value, offset; status_t result = B_OK; /* make sure we don't corrupt the hardware cursor by using fbc.frame_buffer. */ if (si->fbc.frame_buffer == NULL) { LOG(8,("INIT: test_ram detected NULL pointer.\n")); return B_ERROR; } for (offset = 0, value = 0x55aa55aa; offset < 256; offset++) { /* write testpattern to cardRAM */ ((uint32 *)si->fbc.frame_buffer)[offset] = value; /* toggle testpattern */ value = 0xffffffff - value; } for (offset = 0, value = 0x55aa55aa; offset < 256; offset++) { /* readback and verify testpattern from cardRAM */ if (((uint32 *)si->fbc.frame_buffer)[offset] != value) result = B_ERROR; /* toggle testpattern */ value = 0xffffffff - value; } return result; } /* NOTE: * This routine *has* to be done *after* SetDispplayMode has been executed, * or test results will not be representative! * (CAS latency is dependant on nm setup on some (DRAM) boards) */ status_t nm_set_cas_latency() { /* check current RAM access to see if we need to change anything */ if (test_ram() == B_OK) { LOG(4,("INIT: RAM access OK.\n")); return B_OK; } /* check if we read PINS at starttime so we have valid registersettings at our disposal */ LOG(4,("INIT: RAM access errors; not fixable: missing coldstart specs.\n")); return B_ERROR; } static status_t nmxxxx_general_powerup() { uint8 temp; // status_t result; LOG(4, ("INIT: powerup\n")); if (si->settings.logmask & 0x80000000) nm_dump_configuration_space(); /* set ISA registermapping to VGA colormode */ temp = (ISARB(MISCR) | 0x01); /* we need to wait a bit or the card will mess-up it's register values.. */ snooze(10); ISAWB(MISCW, temp); /* unlock cards GRAPHICS registers (any other value than 0x26 should lock it again) */ ISAGRPHW(GRPHXLOCK, 0x26); /* unlock cards CRTC registers */ //don't touch: most cards get into trouble on this! // ISAGRPHW(GENLOCK, 0x00); /* initialize the shared_info struct */ set_specs(); /* log the struct settings */ dump_specs(); /* activate PCI access: b7 = framebuffer, b6 = registers */ ISAGRPHW(IFACECTRL, 0xc0); /* disable VGA-mode cursor (just to be sure) */ ISACRTCW(VGACURCTRL, 0x00); /* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */ /*if (si->settings.usebios || (result != B_OK)) */return nm_general_bios_to_powergraphics(); /*power up the PLLs,LUT,DAC*/ LOG(2,("INIT: powerup\n")); /* turn off both displays and the hardcursor (also disables transfers) */ nm_crtc_dpms(false, false, false); nm_crtc_cursor_hide(); /* setup sequencer clocking mode */ ISASEQW(CLKMODE, 0x21); /* G100 SGRAM and SDRAM use external pix and dac refs, do *not* activate internals! * (this would create electrical shortcuts, * resulting in extra chip heat and distortions visible on screen */ /* set voltage reference - using DAC reference block partly */ // DXIW(VREFCTRL,0x03); /* wait for 100ms for voltage reference to stabilize */ delay(100000); /* power up the SYSPLL */ // CFGW(OPTION,CFGR(OPTION)|0x20); /* power up the PIXPLL */ // DXIW(PIXCLKCTRL,0x08); /* disable pixelclock oscillations before switching on CLUT */ // DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04)); /* disable 15bit mode CLUT-overlay function */ // DXIW(GENCTRL, DXIR(GENCTRL & 0xfd)); /* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */ // DXIW(MISCCTRL,0x1b); // snooze(250); /* re-enable pixelclock oscillations */ // DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb)); /*make sure card is in powergraphics mode*/ // VGAW_I(CRTCEXT,3,0x80); /*set the system clocks to powergraphics speed*/ // LOG(2,("INIT: Setting system PLL to powergraphics speeds\n")); // g100_dac_set_sys_pll(); /* 'official' RAM initialisation */ // LOG(2,("INIT: RAM init\n")); /* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */ // ACCW(PLNWT,0x00000000); // ACCW(PLNWT,0xffffffff); /* program memory control waitstates */ // ACCW(MCTLWTST,si->ps.mctlwtst_reg); /* set memory configuration including: * - no split framebuffer. * - Mark says b14 (G200) should be done also though not defined for G100 in spec, * - b3 v3_mem_type was included by Mark for memconfig setup: but looks like not defined */ // CFGW(OPTION,(CFGR(OPTION)&0xFFFF8FFF) | ((si->ps.v3_mem_type & 0x04) << 10)); /* set memory buffer type: * - Mark says: if((v3_mem_type & 0x03) == 0x03) then do not or-in bits in option2; * but looks like v3_mem_type b1 is not defined, * - Mark also says: place v3_mem_type b1 in option2 bit13 (if not 0x03) but b13 = reserved. */ // CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|((si->ps.v3_mem_type & 0x01) << 12)); /* set RAM read tap delay */ // CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFFFF0) | ((si->ps.v3_mem_type & 0xf0) >> 4)); /* wait 200uS minimum */ // snooze(250); /* reset memory (MACCESS is a write only register!) */ // ACCW(MACCESS, 0x00000000); /* select JEDEC reset method */ // ACCW(MACCESS, 0x00004000); /* perform actual RAM reset */ // ACCW(MACCESS, 0x0000c000); // snooze(250); /* start memory refresh */ // CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000)); /* set memory control waitstate again AFTER the RAM reset */ // ACCW(MCTLWTST,si->ps.mctlwtst_reg); /* end 'official' RAM initialisation. */ /* Bus parameters: enable retries, use advanced read */ // CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29))); /*enable writing to crtc registers*/ // VGAW_I(CRTC,0x11,0); /* turn on display */ nm_crtc_dpms(true, true, true); return B_OK; } status_t nm_general_output_select() { /* log currently selected output */ switch (nm_general_output_read()) { case 0x01: LOG(2, ("INIT: external CRT only mode active\n")); break; case 0x02: LOG(2, ("INIT: internal LCD only mode active\n")); break; case 0x03: LOG(2, ("INIT: simultaneous LCD/CRT mode active\n")); break; } return B_OK; } uint8 nm_general_output_read() { uint8 output; output = (ISAGRPHR(PANELCTRL1) & 0x03); if (output == 0) { /* using 'failsafe' mode: the flatpanel needs all the protection it can get... */ LOG(4, ("INIT: illegal outputmode detected, reporting internal mode!\n")); output = 2; } return output; } /* basic change of card state from VGA to powergraphics -> should work from BIOS init state*/ static status_t nm_general_bios_to_powergraphics() { LOG(2, ("INIT: Skipping card coldstart!\n")); /* turn off display */ nm_crtc_dpms(false, false, false); /* set card to 'enhanced' mode: (only VGA standard registers used for NeoMagic cards) */ /* (keep) card enabled, set plain normal memory usage, no old VGA 'tricks' ... */ ISACRTCW(MODECTL, 0xc3); /* ... plain sequential memory use, more than 64Kb RAM installed, * switch to graphics mode ... */ ISASEQW(MEMMODE, 0x0e); /* ... disable bitplane tweaking ... */ ISAGRPHW(ENSETRESET, 0x00); /* ... no logical function tweaking with display data, no data rotation ... */ ISAGRPHW(DATAROTATE, 0x00); /* ... reset read map select to plane 0 ... */ ISAGRPHW(READMAPSEL, 0x00); /* ... set standard mode ... */ ISAGRPHW(MODE, 0x00); /* ... ISA framebuffer mapping is 64Kb window, switch to graphics mode (again), * select standard adressing ... */ ISAGRPHW(MISC, 0x05); /* ... disable bit masking ... */ ISAGRPHW(BITMASK, 0xff); /* ... attributes are in color, switch to graphics mode (again) ... */ ISAATBW(MODECTL, 0x01); /* ... set overscan color to black ... */ ISAATBW(OSCANCOLOR, 0x00); /* ... enable all color planes ... */ ISAATBW(COLPLANE_EN, 0x0f); /* ... reset horizontal pixelpanning ... */ ISAATBW(HORPIXPAN, 0x00); /* ... and reset colorpalette groupselect bits. */ ISAATBW(COLSEL, 0x00); /* setup sequencer clocking mode */ ISASEQW(CLKMODE, 0x21); /* enable memory above 256Kb: set b4 (disables adress wraparound at 256Kb boundary) */ ISAGRPHW(FBSTADDE, 0x10); /* turn on display */ nm_crtc_dpms(true, true, true); return B_OK; } /* Check if mode virtual_size adheres to the cards _maximum_ contraints, and modify * virtual_size to the nearest valid maximum for the mode on the card if not so. * Then: check if virtual_width adheres to the cards _multiple_ constraints, and * create mode slopspace if not so. * We use acc multiple constraints here if we expect we can use acceleration, because * acc constraints are worse than CRTC constraints. * * Mode slopspace is reflected in fbc->bytes_per_row BTW. */ status_t nm_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode) { /* Note: * This routine assumes that the CRTC memory pitch granularity is 'smaller than', * or 'equals' the acceleration engine memory pitch granularity! */ uint32 video_pitch; uint32 acc_mask, crtc_mask; uint8 depth = 8; //fixme: checkout the acc pitch constraints for all cards... /* determine pixel multiple based on 2D/3D engine constraints */ switch (si->ps.card_type) { /* case G100: switch (target->space) { case B_CMAP8: acc_mask = 0x7f; depth = 8; break; case B_RGB15: acc_mask = 0x3f; depth = 16; break; case B_RGB16: acc_mask = 0x3f; depth = 16; break; case B_RGB24: acc_mask = 0x7f; depth = 24; break; default: LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space)); return B_ERROR; } break; */ default: /* see G100 and up specs: * these cards can do 2D as long as multiples of 32 are used. * (Note: don't mix this up with adress linearisation!) */ switch (target->space) { case B_CMAP8: depth = 8; break; case B_RGB15: depth = 16; break; case B_RGB16: depth = 16; break; case B_RGB24: depth = 24; break; default: LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space)); return B_ERROR; } //assuming accpitch = 32 for now.. acc_mask = 0x1f; break; } /* determine pixel multiple based on CRTC memory pitch constraints. * (Note: Don't mix this up with CRTC timing contraints! Those are * multiples of 8 for horizontal, 1 for vertical timing.) * * CRTC pitch constraints are the same for all Neomagic cards */ switch (target->space) { case B_CMAP8: crtc_mask = 0x07; break; case B_RGB15: crtc_mask = 0x03; break; case B_RGB16: crtc_mask = 0x03; break; case B_RGB24: crtc_mask = 0x07; break; default: LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space)); return B_ERROR; } /* check if we can setup this mode with acceleration: * Max sizes need to adhere to both the acceleration engine _and_ the CRTC constraints! */ *acc_mode = true; /* check virtual_width */ switch (si->ps.card_type) { case G100: /* acc constraint: */ if (target->virtual_width > 2048) *acc_mode = false; break; default: /* G200-G550 */ /* acc constraint: */ if (target->virtual_width > 4096) *acc_mode = false; /* for 32bit mode a lower CRTC1 restriction applies! */ // if ((target->space == B_RGB32_LITTLE) && (target->virtual_width > (4092 & ~acc_mask))) // *acc_mode = false; break; } /* virtual_height */ if (target->virtual_height > 2048) *acc_mode = false; //fixme: (temp) *acc_mode = false; /* now check virtual_size based on CRTC constraints, * making sure virtual_width stays within the 'mask' constraint: which is only * nessesary because of an extra constraint in MIL1/2 cards that exists here. */ //fixme: checkout cardspecs here!! { /* virtual_width */ //fixme for CRTC2 (identical on all G400+ cards): //16bit mode: max. virtual_width == 16352 (no extra mask needed); //32bit mode: max. virtual_width == 8176 (no extra mask needed); //other colordepths are unsupported on CRTC2. switch(target->space) { case B_CMAP8: if (target->virtual_width > (16368 & ~crtc_mask)) target->virtual_width = (16368 & ~crtc_mask); break; case B_RGB15_LITTLE: case B_RGB16_LITTLE: if (target->virtual_width > (8184 & ~crtc_mask)) target->virtual_width = (8184 & ~crtc_mask); break; case B_RGB24_LITTLE: if (target->virtual_width > (5456 & ~crtc_mask)) target->virtual_width = (5456 & ~crtc_mask); break; } /* virtual_height: The only constraint here is the cards memory size which is * checked later on in ProposeMode: virtual_height is adjusted then if needed. * 'Limiting here' to the variable size that's at least available (uint16). */ if (target->virtual_height > 65535) target->virtual_height = 65535; } /* OK, now we know that virtual_width is valid, and it's needing no slopspace if * it was confined above, so we can finally calculate safely if we need slopspace * for this mode... */ if (*acc_mode) video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask); else video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask); LOG(2,("INIT: memory pitch will be set to %d pixels for colorspace 0x%08x\n", video_pitch, target->space)); if (target->virtual_width != video_pitch) LOG(2,("INIT: effective mode slopspace is %d pixels\n", (video_pitch - target->virtual_width))); /* now calculate bytes_per_row for this mode */ *bytes_per_row = video_pitch * (depth >> 3); return B_OK; }