added via accelerant, a copy of skeleton driver yet.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13601 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rudolf Cornelissen 2005-07-10 17:57:38 +00:00
parent 2beedcaece
commit ef583633a4
1 changed files with 858 additions and 0 deletions

View File

@ -0,0 +1,858 @@
/* Authors:
Mark Watson 12/1999,
Apsed,
Rudolf Cornelissen 10/2002-11/2004
*/
#define MODULE_BIT 0x00008000
#include "std.h"
static status_t test_ram(void);
static status_t engxx_general_powerup (void);
static status_t eng_general_bios_to_powergraphics(void);
static void eng_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", \
ENCFG_##reg, #reg, value)); \
} while (0)
DUMP_CFG (DEVID, 0);
DUMP_CFG (DEVCTRL, 0);
DUMP_CFG (CLASS, 0);
DUMP_CFG (HEADER, 0);
DUMP_CFG (BASE1REGS,0);
DUMP_CFG (BASE2FB, 0);
DUMP_CFG (BASE3, 0);
DUMP_CFG (BASE4, 0);
DUMP_CFG (BASE5, 0);
DUMP_CFG (BASE6, 0);
DUMP_CFG (BASE7, 0);
DUMP_CFG (SUBSYSID1,0);
DUMP_CFG (ROMBASE, 0);
DUMP_CFG (CAPPTR, 0);
DUMP_CFG (CFG_1, 0);
DUMP_CFG (INTERRUPT,0);
DUMP_CFG (SUBSYSID2,0);
DUMP_CFG (AGPREF, 0);
DUMP_CFG (AGPSTAT, 0);
DUMP_CFG (AGPCMD, 0);
DUMP_CFG (ROMSHADOW,0);
DUMP_CFG (VGA, 0);
DUMP_CFG (SCHRATCH, 0);
DUMP_CFG (CFG_10, 0);
DUMP_CFG (CFG_11, 0);
DUMP_CFG (CFG_12, 0);
DUMP_CFG (CFG_13, 0);
DUMP_CFG (CFG_14, 0);
DUMP_CFG (CFG_15, 0);
DUMP_CFG (CFG_16, 0);
DUMP_CFG (CFG_17, 0);
DUMP_CFG (CFG_18, 0);
DUMP_CFG (CFG_19, 0);
DUMP_CFG (CFG_20, 0);
DUMP_CFG (CFG_21, 0);
DUMP_CFG (CFG_22, 0);
DUMP_CFG (CFG_23, 0);
DUMP_CFG (CFG_24, 0);
DUMP_CFG (CFG_25, 0);
DUMP_CFG (CFG_26, 0);
DUMP_CFG (CFG_27, 0);
DUMP_CFG (CFG_28, 0);
DUMP_CFG (CFG_29, 0);
DUMP_CFG (CFG_30, 0);
DUMP_CFG (CFG_31, 0);
DUMP_CFG (CFG_32, 0);
DUMP_CFG (CFG_33, 0);
DUMP_CFG (CFG_34, 0);
DUMP_CFG (CFG_35, 0);
DUMP_CFG (CFG_36, 0);
DUMP_CFG (CFG_37, 0);
DUMP_CFG (CFG_38, 0);
DUMP_CFG (CFG_39, 0);
DUMP_CFG (CFG_40, 0);
DUMP_CFG (CFG_41, 0);
DUMP_CFG (CFG_42, 0);
DUMP_CFG (CFG_43, 0);
DUMP_CFG (CFG_44, 0);
DUMP_CFG (CFG_45, 0);
DUMP_CFG (CFG_46, 0);
DUMP_CFG (CFG_47, 0);
DUMP_CFG (CFG_48, 0);
DUMP_CFG (CFG_49, 0);
DUMP_CFG (CFG_50, 0);
#undef DUMP_CFG
}
status_t eng_general_powerup()
{
status_t status;
LOG(1,("POWERUP: Haiku skeleton Accelerant 0.01 running.\n"));
/* preset no laptop */
si->ps.laptop = false;
/* detect card type and power it up */
switch(CFGR(DEVID))
{
/* Vendor Via */
case 0x31221106: /* */
si->ps.card_type = NV04;
si->ps.card_arch = NV04A;
LOG(4,("POWERUP: Detected Nvidia TNT1 (NV04)\n"));
status = engxx_general_powerup();
break;
default:
LOG(8,("POWERUP: Failed to detect valid card 0x%08x\n",CFGR(DEVID)));
return B_ERROR;
}
return status;
}
static status_t test_ram()
{
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 NV setup on some (DRAM) boards) */
status_t eng_set_cas_latency()
{
status_t result = B_ERROR;
uint8 latency = 0;
/* 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 */
if (si->ps.pins_status != B_OK)
{
LOG(4,("INIT: RAM access errors; not fixable: PINS was not read from cardBIOS.\n"));
return B_ERROR;
}
/* OK. We might have a problem, try to fix it now.. */
LOG(4,("INIT: RAM access errors; tuning CAS latency if prudent...\n"));
switch(si->ps.card_type)
{
default:
LOG(4,("INIT: RAM CAS tuning not implemented for this card, aborting.\n"));
return B_OK;
break;
}
if (result == B_OK)
LOG(4,("INIT: RAM access OK. CAS latency set to %d cycles.\n", latency));
else
LOG(4,("INIT: RAM access not fixable. CAS latency set to %d cycles.\n", latency));
return result;
}
void setup_virtualized_heads(bool cross)
{
if (cross)
{
head1_validate_timing = (crtc_validate_timing) eng_crtc2_validate_timing;
head1_set_timing = (crtc_set_timing) eng_crtc2_set_timing;
head1_depth = (crtc_depth) eng_crtc2_depth;
head1_dpms = (crtc_dpms) eng_crtc2_dpms;
head1_dpms_fetch = (crtc_dpms_fetch) eng_crtc2_dpms_fetch;
head1_set_display_pitch = (crtc_set_display_pitch) eng_crtc2_set_display_pitch;
head1_set_display_start = (crtc_set_display_start) eng_crtc2_set_display_start;
head1_cursor_init = (crtc_cursor_init) eng_crtc2_cursor_init;
head1_cursor_show = (crtc_cursor_show) eng_crtc2_cursor_show;
head1_cursor_hide = (crtc_cursor_hide) eng_crtc2_cursor_hide;
head1_cursor_define = (crtc_cursor_define) eng_crtc2_cursor_define;
head1_cursor_position = (crtc_cursor_position) eng_crtc2_cursor_position;
head1_mode = (dac_mode) eng_dac2_mode;
head1_palette = (dac_palette) eng_dac2_palette;
head1_set_pix_pll = (dac_set_pix_pll) eng_dac2_set_pix_pll;
head1_pix_pll_find = (dac_pix_pll_find) eng_dac2_pix_pll_find;
head2_validate_timing = (crtc_validate_timing) eng_crtc_validate_timing;
head2_set_timing = (crtc_set_timing) eng_crtc_set_timing;
head2_depth = (crtc_depth) eng_crtc_depth;
head2_dpms = (crtc_dpms) eng_crtc_dpms;
head2_dpms_fetch = (crtc_dpms_fetch) eng_crtc_dpms_fetch;
head2_set_display_pitch = (crtc_set_display_pitch) eng_crtc_set_display_pitch;
head2_set_display_start = (crtc_set_display_start) eng_crtc_set_display_start;
head2_cursor_init = (crtc_cursor_init) eng_crtc_cursor_init;
head2_cursor_show = (crtc_cursor_show) eng_crtc_cursor_show;
head2_cursor_hide = (crtc_cursor_hide) eng_crtc_cursor_hide;
head2_cursor_define = (crtc_cursor_define) eng_crtc_cursor_define;
head2_cursor_position = (crtc_cursor_position) eng_crtc_cursor_position;
head2_mode = (dac_mode) eng_dac_mode;
head2_palette = (dac_palette) eng_dac_palette;
head2_set_pix_pll = (dac_set_pix_pll) eng_dac_set_pix_pll;
head2_pix_pll_find = (dac_pix_pll_find) eng_dac_pix_pll_find;
}
else
{
head1_validate_timing = (crtc_validate_timing) eng_crtc_validate_timing;
head1_set_timing = (crtc_set_timing) eng_crtc_set_timing;
head1_depth = (crtc_depth) eng_crtc_depth;
head1_dpms = (crtc_dpms) eng_crtc_dpms;
head1_dpms_fetch = (crtc_dpms_fetch) eng_crtc_dpms_fetch;
head1_set_display_pitch = (crtc_set_display_pitch) eng_crtc_set_display_pitch;
head1_set_display_start = (crtc_set_display_start) eng_crtc_set_display_start;
head1_cursor_init = (crtc_cursor_init) eng_crtc_cursor_init;
head1_cursor_show = (crtc_cursor_show) eng_crtc_cursor_show;
head1_cursor_hide = (crtc_cursor_hide) eng_crtc_cursor_hide;
head1_cursor_define = (crtc_cursor_define) eng_crtc_cursor_define;
head1_cursor_position = (crtc_cursor_position) eng_crtc_cursor_position;
head1_mode = (dac_mode) eng_dac_mode;
head1_palette = (dac_palette) eng_dac_palette;
head1_set_pix_pll = (dac_set_pix_pll) eng_dac_set_pix_pll;
head1_pix_pll_find = (dac_pix_pll_find) eng_dac_pix_pll_find;
head2_validate_timing = (crtc_validate_timing) eng_crtc2_validate_timing;
head2_set_timing = (crtc_set_timing) eng_crtc2_set_timing;
head2_depth = (crtc_depth) eng_crtc2_depth;
head2_dpms = (crtc_dpms) eng_crtc2_dpms;
head2_dpms_fetch = (crtc_dpms_fetch) eng_crtc2_dpms_fetch;
head2_set_display_pitch = (crtc_set_display_pitch) eng_crtc2_set_display_pitch;
head2_set_display_start = (crtc_set_display_start) eng_crtc2_set_display_start;
head2_cursor_init = (crtc_cursor_init) eng_crtc2_cursor_init;
head2_cursor_show = (crtc_cursor_show) eng_crtc2_cursor_show;
head2_cursor_hide = (crtc_cursor_hide) eng_crtc2_cursor_hide;
head2_cursor_define = (crtc_cursor_define) eng_crtc2_cursor_define;
head2_cursor_position = (crtc_cursor_position) eng_crtc2_cursor_position;
head2_mode = (dac_mode) eng_dac2_mode;
head2_palette = (dac_palette) eng_dac2_palette;
head2_set_pix_pll = (dac_set_pix_pll) eng_dac2_set_pix_pll;
head2_pix_pll_find = (dac_pix_pll_find) eng_dac2_pix_pll_find;
}
}
void set_crtc_owner(bool head)
{
if (si->ps.secondary_head)
{
if (!head)
{
/* note: 'OWNER' is a non-standard register in behaviour(!) on NV11's,
* while non-NV11 cards behave normally.
*
* Double-write action needed on those strange NV11 cards: */
/* RESET: needed on NV11 */
CRTCW(OWNER, 0xff);
/* enable access to CRTC1, SEQ1, GRPH1, ATB1, ??? */
CRTCW(OWNER, 0x00);
}
else
{
/* note: 'OWNER' is a non-standard register in behaviour(!) on NV11's,
* while non-NV11 cards behave normally.
*
* Double-write action needed on those strange NV11 cards: */
/* RESET: needed on NV11 */
CRTC2W(OWNER, 0xff);
/* enable access to CRTC2, SEQ2, GRPH2, ATB2, ??? */
CRTC2W(OWNER, 0x03);
}
}
}
static status_t engxx_general_powerup()
{
LOG(4, ("INIT: card powerup\n"));
/* setup cardspecs */
/* note:
* this MUST be done before the driver attempts a card coldstart */
set_specs();
/* only process BIOS for finetuning specs and coldstarting card if requested
* by the user;
* note:
* this in fact frees the driver from relying on the BIOS to be executed
* at system power-up POST time. */
if (!si->settings.usebios)
{
LOG(2, ("INIT: Attempting card coldstart!\n"));
/* update the cardspecs in the shared_info PINS struct according to reported
* specs as much as is possible;
* this also coldstarts the card if possible (executes BIOS CMD script(s)) */
// parse_pins();
}
else
{
LOG(2, ("INIT: Skipping card coldstart!\n"));
}
/* get RAM size and fake panel startup (panel init code is still missing) */
fake_panel_start();
/* log the final card specifications */
dump_pins();
/* dump config space as it is after a possible coldstart attempt */
if (si->settings.logmask & 0x80000000) eng_dump_configuration_space();
/* setup CRTC and DAC functions access: determined in fake_panel_start */
setup_virtualized_heads(si->ps.crtc2_prim);
/* do powerup needed from pre-inited card state as done by system POST cardBIOS
* execution or driver coldstart above */
return eng_general_bios_to_powergraphics();
}
/* this routine switches the CRTC/DAC sets to 'connectors', but only for analog
* outputs. We need this to make sure the analog 'switch' is set in the same way the
* digital 'switch' is set by the BIOS or we might not be able to use dualhead. */
status_t eng_general_output_select(bool cross)
{
/* make sure this call is warranted */
if (si->ps.secondary_head)
{
/* NV11 cards can't switch heads (confirmed) */
if (si->ps.card_type != NV11)
{
if (cross)
{
LOG(4,("INIT: switching analog outputs to be cross-connected\n"));
/* enable head 2 on connector 1 */
/* (b8 = select CRTC (head) for output,
* b4 = ??? (confirmed not to be a FP switch),
* b0 = enable CRT) */
DACW(OUTPUT, 0x00000101);
/* enable head 1 on connector 2 */
DAC2W(OUTPUT, 0x00000001);
}
else
{
LOG(4,("INIT: switching analog outputs to be straight-through\n"));
/* enable head 1 on connector 1 */
DACW(OUTPUT, 0x00000001);
/* enable head 2 on connector 2 */
DAC2W(OUTPUT, 0x00000101);
}
}
else
{
LOG(4,("INIT: NV11 analog outputs are hardwired to be straight-through\n"));
}
return B_OK;
}
else
{
return B_ERROR;
}
}
/* this routine switches CRTC/DAC set use. We need this because it's unknown howto
* switch digital panels to/from a specific CRTC/DAC set. */
status_t eng_general_head_select(bool cross)
{
/* make sure this call is warranted */
if (si->ps.secondary_head)
{
/* invert CRTC/DAC use to do switching */
if (cross)
{
LOG(4,("INIT: switching CRTC/DAC use to be cross-connected\n"));
si->crtc_switch_mode = !si->ps.crtc2_prim;
}
else
{
LOG(4,("INIT: switching CRTC/DAC use to be straight-through\n"));
si->crtc_switch_mode = si->ps.crtc2_prim;
}
/* update CRTC and DAC functions access */
setup_virtualized_heads(si->crtc_switch_mode);
return B_OK;
}
else
{
return B_ERROR;
}
}
/* basic change of card state from VGA to enhanced mode:
* Should work from VGA BIOS POST init state. */
static status_t eng_general_bios_to_powergraphics()
{
/* let acc engine make power off/power on cycle to start 'fresh' */
// ENG_RG32(RG32_PWRUPCTRL) = 0x13110011;
snooze(1000);
/* power-up all hardware function blocks */
/* bit 28: OVERLAY ENGINE (BES),
* bit 25: CRTC2, (> NV04A)
* bit 24: CRTC1,
* bit 20: framebuffer,
* bit 16: PPMI,
* bit 12: PGRAPH,
* bit 8: PFIFO,
* bit 4: PMEDIA,
* bit 0: TVOUT. (> NV04A) */
// ENG_RG32(RG32_PWRUPCTRL) = 0x13111111;
/* select colormode CRTC registers base adresses */
// ENG_REG8(RG8_MISCW) = 0xcb;
/* enable access to primary head */
// set_crtc_owner(0);
/* unlock head's registers for R/W access */
// CRTCW(LOCK, 0x57);
// CRTCW(VSYNCE ,(CRTCR(VSYNCE) & 0x7f));
// if (si->ps.secondary_head)
if (0)
{
/* enable access to secondary head */
set_crtc_owner(1);
/* unlock head's registers for R/W access */
CRTC2W(LOCK, 0x57);
CRTC2W(VSYNCE ,(CRTCR(VSYNCE) & 0x7f));
}
/* turn off both displays and the hardcursors (also disables transfers) */
// head1_dpms(false, false, false);
// head1_cursor_hide();
// if (si->ps.secondary_head)
if (0)
{
// head2_dpms(false, false, false);
// head2_cursor_hide();
}
// if (si->ps.secondary_head)
if (0)
{
/* switch overlay engine to CRTC1 */
/* bit 17: GPU FP port #1 (confirmed NV25, NV28, confirmed not on NV34),
* bit 16: GPU FP port #2 (confirmed NV25, NV28, NV34),
* bit 12: overlay engine (all cards),
* bit 9: TVout chip #2 (confirmed on NV18, NV25, NV28),
* bit 8: TVout chip #1 (all cards),
* bit 4: both I2C busses (all cards) */
ENG_RG32(RG32_2FUNCSEL) &= ~0x00001000;
ENG_RG32(RG32_FUNCSEL) |= 0x00001000;
}
si->overlay.crtc = false;
/* enable 'enhanced' mode on primary head: */
/* enable access to primary head */
// set_crtc_owner(0);
/* note: 'BUFFER' is a non-standard register in behaviour(!) on most
* NV11's like the GeForce2 MX200, while the MX400 and non-NV11 cards
* behave normally.
* Also readback is not nessesarily what was written before!
*
* Double-write action needed on those strange NV11 cards: */
/* RESET: don't doublebuffer CRTC access: set programmed values immediately... */
// CRTCW(BUFFER, 0xff);
/* ... and use fine pitched CRTC granularity on > NV4 cards (b2 = 0) */
/* note: this has no effect on possible bandwidth issues. */
// CRTCW(BUFFER, 0xfb);
/* select VGA mode (old VGA register) */
// CRTCW(MODECTL, 0xc3);
/* select graphics mode (old VGA register) */
// SEQW(MEMMODE, 0x0e);
/* select 8 dots character clocks (old VGA register) */
// SEQW(CLKMODE, 0x21);
/* select VGA mode (old VGA register) */
// GRPHW(MODE, 0x00);
/* select graphics mode (old VGA register) */
// GRPHW(MISC, 0x01);
/* select graphics mode (old VGA register) */
// ATBW(MODECTL, 0x01);
/* enable 'enhanced mode', enable Vsync & Hsync,
* set DAC palette to 8-bit width, disable large screen */
// CRTCW(REPAINT1, 0x04);
/* enable 'enhanced' mode on secondary head: */
// if (si->ps.secondary_head)
if (0)
{
/* enable access to secondary head */
set_crtc_owner(1);
/* select colormode CRTC2 registers base adresses */
ENG_REG8(RG8_MISCW) = 0xcb;
/* note: 'BUFFER' is a non-standard register in behaviour(!) on most
* NV11's like the GeForce2 MX200, while the MX400 and non-NV11 cards
* behave normally.
* Also readback is not nessesarily what was written before!
*
* Double-write action needed on those strange NV11 cards: */
/* RESET: don't doublebuffer CRTC2 access: set programmed values immediately... */
CRTC2W(BUFFER, 0xff);
/* ... and use fine pitched CRTC granularity on > NV4 cards (b2 = 0) */
/* note: this has no effect on possible bandwidth issues. */
CRTC2W(BUFFER, 0xfb);
/* select VGA mode (old VGA register) */
CRTC2W(MODECTL, 0xc3);
/* select graphics mode (old VGA register) */
SEQW(MEMMODE, 0x0e);
/* select 8 dots character clocks (old VGA register) */
SEQW(CLKMODE, 0x21);
/* select VGA mode (old VGA register) */
GRPHW(MODE, 0x00);
/* select graphics mode (old VGA register) */
GRPHW(MISC, 0x01);
/* select graphics mode (old VGA register) */
ATB2W(MODECTL, 0x01);
/* enable 'enhanced mode', enable Vsync & Hsync,
* set DAC palette to 8-bit width, disable large screen */
CRTC2W(REPAINT1, 0x04);
}
/* enable palettes */
// DACW(GENCTRL, 0x00100100);
// if (si->ps.secondary_head) DAC2W(GENCTRL, 0x00100100);
/* enable programmable PLLs */
// DACW(PLLSEL, 0x10000700);
// if (si->ps.secondary_head) DACW(PLLSEL, (DACR(PLLSEL) | 0x20000800));
/* turn on DAC and make sure detection testsignal routing is disabled
* (b16 = disable DAC,
* b12 = enable testsignal output */
// DACW(TSTCTRL, (DACR(TSTCTRL) & 0xfffeefff));
/* turn on DAC2 if it exists
* (NOTE: testsignal function block resides in DAC1 only (!)) */
// if (si->ps.secondary_head) DAC2W(TSTCTRL, (DAC2R(TSTCTRL) & 0xfffeefff));
/* setup AGP:
* Note:
* This may only be done when no transfers are in progress on the bus, so now
* is probably a good time.. */
eng_agp_setup();
/* turn screen one on */
// head1_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.
* Also: check if virtual_width adheres to the cards granularity constraints, and
* create mode slopspace if not so.
* We use acc or crtc granularity constraints based on the 'worst case' scenario.
*
* Mode slopspace is reflected in fbc->bytes_per_row BTW. */
status_t eng_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode)
{
uint32 video_pitch;
uint32 acc_mask, crtc_mask;
uint32 max_crtc_width, max_acc_width;
uint8 depth = 8;
/* determine pixel multiple based on 2D/3D engine constraints */
switch (si->ps.card_arch)
{
default:
/* confirmed for:
* TNT1, TNT2, TNT2-M64, GeForce2 MX400, GeForce4 MX440, GeForceFX 5200 */
switch (target->space)
{
case B_CMAP8: acc_mask = 0x0f; depth = 8; break;
case B_RGB15: acc_mask = 0x07; depth = 16; break;
case B_RGB16: acc_mask = 0x07; depth = 16; break;
case B_RGB24: acc_mask = 0x0f; depth = 24; break;
case B_RGB32: acc_mask = 0x03; depth = 32; break;
default:
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
return B_ERROR;
}
/* NV31 (confirmed GeForceFX 5600) has NV20A granularity!
* So let it fall through... */
if (si->ps.card_type != NV31) break;
case NV20A:
/* confirmed for:
* GeForce4 Ti4200 */
switch (target->space)
{
case B_CMAP8: acc_mask = 0x3f; depth = 8; break;
case B_RGB15: acc_mask = 0x1f; depth = 16; break;
case B_RGB16: acc_mask = 0x1f; depth = 16; break;
case B_RGB24: acc_mask = 0x3f; depth = 24; break;
case B_RGB32: acc_mask = 0x0f; depth = 32; break;
default:
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
return B_ERROR;
}
break;
}
/* determine pixel multiple based on CRTC memory pitch constraints:
* -> all NV cards have same granularity constraints on CRTC1 and CRTC2,
* provided that the CRTC1 and CRTC2 BUFFER register b2 = 0;
*
* (Note: Don't mix this up with CRTC timing contraints! Those are
* multiples of 8 for horizontal, 1 for vertical timing.) */
switch (si->ps.card_type)
{
default:
// case NV04:
/* confirmed for:
* TNT1 always;
* TNT2, TNT2-M64, GeForce2 MX400, GeForce4 MX440, GeForce4 Ti4200,
* GeForceFX 5200: if the CRTC1 (and CRTC2) BUFFER register b2 = 0 */
/* NOTE:
* Unfortunately older cards have a hardware fault that prevents use.
* We need doubled granularity on those to prevent the single top line
* from shifting to the left!
* This is confirmed for TNT2, GeForce2 MX200, GeForce2 MX400.
* Confirmed OK are:
* GeForce4 MX440, GeForce4 Ti4200, GeForceFX 5200. */
switch (target->space)
{
case B_CMAP8: crtc_mask = 0x0f; break; /* 0x07 */
case B_RGB15: crtc_mask = 0x07; break; /* 0x03 */
case B_RGB16: crtc_mask = 0x07; break; /* 0x03 */
case B_RGB24: crtc_mask = 0x0f; break; /* 0x07 */
case B_RGB32: crtc_mask = 0x03; break; /* 0x01 */
default:
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
return B_ERROR;
}
break;
// default:
/* confirmed for:
* TNT2, TNT2-M64, GeForce2 MX400, GeForce4 MX440, GeForce4 Ti4200,
* GeForceFX 5200: if the CRTC1 (and CRTC2) BUFFER register b2 = 1 */
/* switch (target->space)
{
case B_CMAP8: crtc_mask = 0x1f; break;
case B_RGB15: crtc_mask = 0x0f; break;
case B_RGB16: crtc_mask = 0x0f; break;
case B_RGB24: crtc_mask = 0x1f; break;
case B_RGB32: crtc_mask = 0x07; break;
default:
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
return B_ERROR;
}
break;
*/ }
/* set virtual_width limit for accelerated modes */
switch (si->ps.card_arch)
{
case NV04A:
/* confirmed for:
* TNT1, TNT2, TNT2-M64 */
switch(target->space)
{
case B_CMAP8: max_acc_width = 8176; break;
case B_RGB15: max_acc_width = 4088; break;
case B_RGB16: max_acc_width = 4088; break;
case B_RGB24: max_acc_width = 2720; break;
case B_RGB32: max_acc_width = 2044; break;
default:
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
return B_ERROR;
}
break;
default:
/* confirmed for:
* GeForce2 MX400, GeForce4 MX440, GeForceFX 5200 */
switch(target->space)
{
case B_CMAP8: max_acc_width = 16368; break;
case B_RGB15: max_acc_width = 8184; break;
case B_RGB16: max_acc_width = 8184; break;
case B_RGB24: max_acc_width = 5456; break;
case B_RGB32: max_acc_width = 4092; break;
default:
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
return B_ERROR;
}
/* NV31 (confirmed GeForceFX 5600) has NV20A granularity!
* So let it fall through... */
if (si->ps.card_type != NV31) break;
case NV20A:
/* confirmed for:
* GeForce4 Ti4200 */
switch(target->space)
{
case B_CMAP8: max_acc_width = 16320; break;
case B_RGB15: max_acc_width = 8160; break;
case B_RGB16: max_acc_width = 8160; break;
case B_RGB24: max_acc_width = 5440; break;
case B_RGB32: max_acc_width = 4080; break;
default:
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
return B_ERROR;
}
break;
}
/* set virtual_width limit for unaccelerated modes */
switch (si->ps.card_type)
{
default:
// case NV04:
/* confirmed for:
* TNT1 always;
* TNT2, TNT2-M64, GeForce2 MX400, GeForce4 MX440, GeForce4 Ti4200,
* GeForceFX 5200: if the CRTC1 (and CRTC2) BUFFER register b2 = 0 */
/* NOTE:
* Unfortunately older cards have a hardware fault that prevents use.
* We need doubled granularity on those to prevent the single top line
* from shifting to the left!
* This is confirmed for TNT2, GeForce2 MX200, GeForce2 MX400.
* Confirmed OK are:
* GeForce4 MX440, GeForce4 Ti4200, GeForceFX 5200. */
switch(target->space)
{
case B_CMAP8: max_crtc_width = 16368; break; /* 16376 */
case B_RGB15: max_crtc_width = 8184; break; /* 8188 */
case B_RGB16: max_crtc_width = 8184; break; /* 8188 */
case B_RGB24: max_crtc_width = 5456; break; /* 5456 */
case B_RGB32: max_crtc_width = 4092; break; /* 4094 */
default:
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
return B_ERROR;
}
break;
// default:
/* confirmed for:
* TNT2, TNT2-M64, GeForce2 MX400, GeForce4 MX440, GeForce4 Ti4200,
* GeForceFX 5200: if the CRTC1 (and CRTC2) BUFFER register b2 = 1 */
/* switch(target->space)
{
case B_CMAP8: max_crtc_width = 16352; break;
case B_RGB15: max_crtc_width = 8176; break;
case B_RGB16: max_crtc_width = 8176; break;
case B_RGB24: max_crtc_width = 5440; break;
case B_RGB32: max_crtc_width = 4088; break;
default:
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
return B_ERROR;
}
break;
*/ }
/* check for acc capability, and adjust mode to adhere to hardware constraints */
if (max_acc_width <= max_crtc_width)
{
/* check if we can setup this mode with acceleration */
// *acc_mode = true;
//blocking acc totally:
*acc_mode = false;
/* virtual_width */
if (target->virtual_width > max_acc_width) *acc_mode = false;
/* virtual_height */
/* (NV cards can even do more than this(?)...
* but 4096 is confirmed on all cards at max. accelerated width.) */
if (target->virtual_height > 4096) *acc_mode = false;
/* now check virtual_size based on CRTC constraints */
if (target->virtual_width > max_crtc_width) target->virtual_width = max_crtc_width;
/* 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)
{
/* the mode needs to adhere to the largest granularity imposed... */
if (acc_mask < crtc_mask)
video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
else
video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask);
}
else /* unaccelerated mode */
video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
}
else /* max_acc_width > max_crtc_width */
{
/* check if we can setup this mode with acceleration */
*acc_mode = true;
/* (we already know virtual_width will be no problem) */
/* virtual_height */
/* (NV cards can even do more than this(?)...
* but 4096 is confirmed on all cards at max. accelerated width.) */
if (target->virtual_height > 4096) *acc_mode = false;
/* now check virtual_size based on CRTC constraints */
if (*acc_mode)
{
/* note that max_crtc_width already adheres to crtc_mask */
if (target->virtual_width > (max_crtc_width & ~acc_mask))
target->virtual_width = (max_crtc_width & ~acc_mask);
}
else /* unaccelerated mode */
{
if (target->virtual_width > max_crtc_width)
target->virtual_width = max_crtc_width;
}
/* 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)
{
/* the mode needs to adhere to the largest granularity imposed... */
if (acc_mask < crtc_mask)
video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
else
video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask);
}
else /* unaccelerated mode */
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;
}