Mark Watson 12/1999,
Apsed,
Rudolf Cornelissen 10/2002-10/2009
*/
#define MODULE_BIT 0x00008000
#include "mga_std.h"
static status_t test_ram(void);
static status_t mil_general_powerup (void);
static status_t g100_general_powerup (void);
static status_t g200_general_powerup (void);
static status_t g400_general_powerup (void);
static status_t g450_general_powerup (void);
static status_t gx00_general_bios_to_powergraphics(void);
static void mga_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", \
MGACFG_##reg, #reg, value)); \
} while (0)
DUMP_CFG (DEVID, 0);
DUMP_CFG (DEVCTRL, 0);
DUMP_CFG (CLASS, 0);
DUMP_CFG (HEADER, 0);
DUMP_CFG (MGABASE2, 0);
DUMP_CFG (MGABASE1, 0);
DUMP_CFG (MGABASE3, MYST);
DUMP_CFG (SUBSYSIDR, MYST);
DUMP_CFG (ROMBASE, 0);
DUMP_CFG (CAP_PTR, MIL2);
DUMP_CFG (INTCTRL, 0);
DUMP_CFG (OPTION, 0);
DUMP_CFG (MGA_INDEX, 0);
DUMP_CFG (MGA_DATA, 0);
DUMP_CFG (SUBSYSIDW, MYST);
DUMP_CFG (OPTION2, G100);
DUMP_CFG (OPTION3, G400);
DUMP_CFG (OPTION4, G400);
DUMP_CFG (PM_IDENT, G100);
DUMP_CFG (PM_CSR, G100);
DUMP_CFG (AGP_IDENT, MIL2);
DUMP_CFG (AGP_STS, MIL2);
DUMP_CFG (AGP_CMD, MIL2);
#undef DUMP_CFG
}
status_t gx00_general_powerup()
{
status_t status;
uint8 card_class;
LOG(1,("POWERUP: Haiku Matrox Accelerant 0.33 running.\n"));
if (si->ps.int_assigned)
LOG(4,("POWERUP: Usable INT assigned to HW; Vblank semaphore enabled\n"));
else
LOG(4,("POWERUP: No (usable) INT assigned to HW; Vblank semaphore disabled\n"));
* _adi.name_ and _adi.chipset_ can contain 31 readable characters max.!!! */
switch(CFGR(DEVID))
{
case 0x051a102b:
sprintf(si->adi.name, "Matrox Mystique PCI");
sprintf(si->adi.chipset, "MGA-1064");
LOG(8,("POWERUP: Unimplemented Matrox device %08x\n",CFGR(DEVID)));
return B_ERROR;
case 0x0519102b:
si->ps.card_type = MIL1;
sprintf(si->adi.name, "Matrox Millennium I");
sprintf(si->adi.chipset, "MGA-2064");
status = mil_general_powerup();
break;
case 0x051b102b:case 0x051f102b:
si->ps.card_type = MIL2;
sprintf(si->adi.name, "Matrox Millennium II");
sprintf(si->adi.chipset, "MGA-2164");
status = mil_general_powerup();
break;
case 0x1000102b:case 0x1001102b:
si->ps.card_type = G100;
sprintf(si->adi.name, "Matrox MGA G100");
sprintf(si->adi.chipset, "G100");
status = g100_general_powerup();
break;
case 0x0520102b:case 0x0521102b:
si->ps.card_type = G200;
sprintf(si->adi.name, "Matrox MGA G200");
sprintf(si->adi.chipset, "G200");
status = g200_general_powerup();
break;
case 0x0525102b:
card_class = CFGR(CLASS) & 0xff;
if (card_class & 0x80)
{
si->ps.card_type = G450;
sprintf(si->adi.name, "Matrox MGA G450");
sprintf(si->adi.chipset, "G450 revision %x", (card_class & 0x7f));
LOG(4, ("50 revision %x\n", card_class & 0x7f));
status = g450_general_powerup();
}
else
{
si->ps.card_type = G400;
sprintf(si->adi.name, "Matrox MGA G400");
sprintf(si->adi.chipset, "G400 revision %x", (card_class & 0x7f));
status = g400_general_powerup();
}
break;
case 0x2527102b:
si->ps.card_type = G450;
sprintf(si->adi.name, "Matrox MGA G550");
sprintf(si->adi.chipset, "G550");
status = g450_general_powerup();
break;
default:
LOG(8,("POWERUP: Failed to detect valid card 0x%08x\n",CFGR(DEVID)));
return B_ERROR;
}
if (si->settings.memory != 0)
si->ps.memory_size = si->settings.memory;
return status;
}
static status_t test_ram()
{
uint32 value, offset;
status_t result = B_OK;
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++)
{
((vuint32 *)si->fbc.frame_buffer)[offset] = value;
value = 0xffffffff - value;
}
for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
{
if (((vuint32 *)si->fbc.frame_buffer)[offset] != value) result = B_ERROR;
value = 0xffffffff - value;
}
return result;
}
* This routine *has* to be done *after* SetDispplayMode has been executed,
* or test results will not be representative!
* (CAS latency is dependant on MGA setup on some (DRAM) boards) */
status_t mga_set_cas_latency()
{
status_t result = B_ERROR;
uint8 latency = 0;
if (test_ram() == B_OK)
{
LOG(4,("INIT: RAM access OK.\n"));
return B_OK;
}
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;
}
LOG(4,("INIT: RAM access errors; tuning CAS latency if prudent...\n"));
switch(si->ps.card_type)
{
case G100:
if (!si->ps.sdram)
{
LOG(4,("INIT: G100 SGRAM CAS tuning not permitted, aborting.\n"));
return B_OK;
}
for (latency = 4; latency >= 2; latency-- )
{
ACCW(MCTLWTST, ((si->ps.mctlwtst_reg & 0xfffffffc) | (latency - 2)));
result = test_ram();
if (result == B_OK) break;
}
break;
case G200:
LOG(4,("INIT: G200 RAM CAS tuning not implemented, aborting.\n"));
return B_OK;
break;
case G400:
case G400MAX:
LOG(4,("INIT: G400/G400MAX RAM CAS tuning not implemented, aborting.\n"));
return B_OK;
break;
case G450:
case G550:
LOG(4,("INIT: G450/G550 RAM CAS tuning not implemented, aborting.\n"));
return B_OK;
break;
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;
}
static
status_t mil_general_powerup()
{
status_t result;
LOG(4, ("INIT: Millenium I/II powerup\n"));
LOG(4, ("INIT: Detected %s (%s)\n", si->adi.name, si->adi.chipset));
if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
result = parse_pins();
if (result != B_OK) fake_pins();
dump_pins();
fake_pins();
LOG(2, ("INIT: Using faked PINS for now:\n"));
dump_pins();
LOG(2, ("INIT: Skipping card coldstart!\n"));
mil2_dac_init();
DXIW (GENCTRL, (DXIR (GENCTRL) & 0x0c));
| (vsync_pos? 0x00:0x02)
| (hsync_pos? 0x00:0x01)); */
DXIW(MISCCTRL, 0x0c);
VGAW_I(SEQ,1,0x00);
return B_OK;
}
static
status_t g100_general_powerup()
{
status_t result;
LOG(4, ("INIT: G100 powerup\n"));
LOG(4, ("INIT: Detected %s (%s)\n", si->adi.name, si->adi.chipset));
if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
result = parse_pins();
if (result != B_OK) fake_pins();
dump_pins();
if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
LOG(2,("INIT: PLL/LUT/DAC powerup\n"));
gx00_crtc_dpms(false, false, false);
if (si->ps.tvout) gx00_maven_dpms(false, false, false);
gx00_crtc_cursor_hide();
* (this would create electrical shortcuts,
* resulting in extra chip heat and distortions visible on screen */
DXIW(VREFCTRL,0x03);
delay(100000);
CFGW(OPTION,CFGR(OPTION)|0x20);
DXIW(PIXCLKCTRL,0x08);
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
DXIW(MISCCTRL,0x1b);
snooze(250);
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
i2c_init();
VGAW_I(CRTCEXT,3,0x80);
LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
g100_dac_set_sys_pll();
LOG(2,("INIT: RAM init\n"));
ACCW(PLNWT,0x00000000);
ACCW(PLNWT,0xffffffff);
ACCW(MCTLWTST,si->ps.mctlwtst_reg);
* - 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));
* - 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));
CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFFFF0) | ((si->ps.v3_mem_type & 0xf0) >> 4));
snooze(250);
ACCW(MACCESS, 0x00000000);
ACCW(MACCESS, 0x00004000);
ACCW(MACCESS, 0x0000c000);
snooze(250);
CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
ACCW(MCTLWTST,si->ps.mctlwtst_reg);
CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29)));
VGAW_I(CRTC,0x11,0);
return B_OK;
}
static
status_t g200_general_powerup()
{
status_t result;
LOG(4, ("INIT: G200 powerup\n"));
LOG(4, ("INIT: Detected %s (%s)\n", si->adi.name, si->adi.chipset));
if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
result = parse_pins();
if (result != B_OK) fake_pins();
dump_pins();
if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
LOG(2,("INIT: PLL/LUT/DAC powerup\n"));
gx00_crtc_dpms(false, false, false);
if (si->ps.tvout) gx00_maven_dpms(false, false, false);
gx00_crtc_cursor_hide();
* (this would create electrical shortcuts,
* resulting in extra chip heat and distortions visible on screen */
DXIW(VREFCTRL,0x03);
delay(100000);
CFGW(OPTION,CFGR(OPTION)|0x20);
DXIW(PIXCLKCTRL,0x08);
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
DXIW(MISCCTRL,0x1b);
snooze(250);
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
i2c_init();
VGAW_I(CRTCEXT,3,0x80);
LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
g200_dac_set_sys_pll();
LOG(2,("INIT: RAM init\n"));
if (si->ps.sdram) CFGW(OPTION,(CFGR(OPTION) & 0xffffbfff));
ACCW(PLNWT,0x00000000);
ACCW(PLNWT,0xffffffff);
ACCW(MCTLWTST,si->ps.mctlwtst_reg);
* - SDRAM / SGRAM special functions select. */
CFGW(OPTION,(CFGR(OPTION)&0xFFFF83FF) | ((si->ps.v3_mem_type & 0x07) << 10));
if (!si->ps.sdram) CFGW(OPTION,(CFGR(OPTION) | (0x01 << 14)));
CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|((si->ps.v3_option2_reg & 0x03) << 12));
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0x0000FFFF)|(si->ps.memrdbk_reg & 0xffff0000));
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF0000)|(si->ps.memrdbk_reg & 0x0000ffff));
snooze(250);
ACCW(MACCESS, 0x00000000);
ACCW(MACCESS, 0x00008000);
snooze(250);
CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
ACCW(MCTLWTST,si->ps.mctlwtst_reg);
CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29)));
VGAW_I(CRTC,0x11,0);
return B_OK;
}
static
status_t g400_general_powerup()
{
status_t result;
LOG(4, ("INIT: G400/G400MAX powerup\n"));
LOG(4, ("INIT: Detected %s (%s)\n", si->adi.name, si->adi.chipset));
if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
result = parse_pins();
if (result != B_OK) fake_pins();
dump_pins();
if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
if (si->ps.tvout)
{
ACCW(RST, 0x00000002);
snooze(1000);
ACCW(RST, 0x00000000);
}
LOG(4,("INIT: PLL/LUT/DAC powerup\n"));
gx00_crtc_dpms(false, false, false);
g400_crtc2_dpms(false, false, false);
gx00_crtc_cursor_hide();
DXIW(VREFCTRL,0x00);
delay(100000);
CFGW(OPTION,CFGR(OPTION)|0x20);
DXIW(PIXCLKCTRL,0x08);
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
DXIW(MISCCTRL,0x9b);
snooze(250);
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
DXIW(MAFCDEL,0x02);
DXIW(PANELMODE,0x00);
i2c_init();
VGAW_I(CRTCEXT,3,0x80);
LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
g400_dac_set_sys_pll();
LOG(2,("INIT: RAM init\n"));
if (si->ps.sdram) CFGW(OPTION,(CFGR(OPTION) & 0xffffbfff));
ACCW(PLNWT,0x00000000);
ACCW(PLNWT,0xffffffff);
ACCW(MCTLWTST, si->ps.mctlwtst_reg);
* - SDRAM / SGRAM special functions select. */
CFGW(OPTION,(CFGR(OPTION)&0xFFFF83FF) | (si->ps.option_reg & 0x00001c00));
if (!si->ps.sdram) CFGW(OPTION,(CFGR(OPTION) | (0x01 << 14)));
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0x0000FFFF)|(si->ps.memrdbk_reg & 0xffff0000));
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF0000)|(si->ps.memrdbk_reg & 0x0000ffff));
snooze(250);
ACCW(MACCESS, 0x00000000);
ACCW(MACCESS, 0x00008000);
snooze(250);
CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
ACCW(MCTLWTST,si->ps.mctlwtst_reg);
CFGW(OPTION, ((CFGR(OPTION) & 0xefbfffff) | (si->ps.option_reg & 0x10400000)));
VGAW_I(CRTC,0x11,0);
if (si->ps.secondary_head)
{
MAVW(LOCK,0x01);
CR2W(DATACTL,0x00000000);
}
return B_OK;
}
static
status_t g450_general_powerup()
{
status_t result;
uint32 pwr_cas[] = {0, 1, 5, 6, 7, 5, 2, 3};
uint32 maccess = 0x00000000;
LOG(4, ("INIT: G450/G550 powerup\n"));
LOG(4, ("INIT: Detected %s (%s)\n", si->adi.name, si->adi.chipset));
if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
result = parse_pins();
if (result != B_OK) fake_pins();
dump_pins();
if (si->ps.primary_dvi && si->ps.secondary_head &&
si->ps.tvout && (i2c_sec_tv_adapter() != B_OK))
{
si->crossed_conns = true;
}
if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
LOG(4,("INIT: PLL/LUT/DAC powerup\n"));
DXIW(OUTPUTCONN,0x00);
gx00_crtc_dpms(false, false, false);
g400_crtc2_dpms(false, false, false);
gx00_crtc_cursor_hide();
DXIW(PWRCTRL,0x1b);
DXIW(VREFCTRL,0x00);
delay(100000);
CFGW(OPTION,CFGR(OPTION)|0x20);
DXIW(PIXCLKCTRL,0x08);
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
DXIW(MISCCTRL,0x9b);
snooze(250);
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
DXIW(MAFCDEL,0x02);
DXIW(PANELMODE,0x00);
i2c_init();
VGAW_I(CRTCEXT,3,0x80);
LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
g450_dac_set_sys_pll();
LOG(2,("INIT: RAM init\n"));
* and don't touch the rest */
CFGW(OPTION, ((CFGR(OPTION) & 0xf8400164) | (si->ps.option_reg & 0x00207e00)));
CFGW(OPTION2, ((CFGR(OPTION2) & 0xffff0200) | (si->ps.option2_reg & 0x0000fc00)));
ACCW(MCTLWTST, si->ps.mctlwtst_reg);
CFGW(OPTION4, (si->ps.option4_reg & 0x6000000f));
ACCW(MEMRDBK, si->ps.memrdbk_reg);
maccess = ((((uint32)si->ps.v5_mem_type) & 0x80) >> 1);
ACCW(MACCESS, maccess);
CFGW(OPTION4, ((si->ps.option4_reg & 0x60000004) | 0x80000000));
snooze(250);
if ((si->ps.v5_mem_type & 0x0060) == 0x0020)
{
if (!(si->ps.v5_mem_type & 0x0100))
{
maccess = 0x00000000;
ACCW(MACCESS, maccess);
ACCW(MEMRDBK, (si->ps.memrdbk_reg & 0xffffefff));
}
else
if (!(si->ps.v5_mem_type & 0x0200))
{
ACCW(MEMRDBK, (si->ps.memrdbk_reg & 0xffffefff));
}
}
if (si->ps.card_type == G450) {
ACCW(MACCESS, (maccess & 0xffff3fff));
ACCW(MACCESS, (maccess | 0x0000c000));
} else {
ACCW(MACCESS, (maccess & 0xffff7fff));
ACCW(MACCESS, (maccess | 0x00008000));
}
snooze(250);
CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
ACCW(PLNWT,0x00000000);
ACCW(PLNWT,0xffffffff);
if (!(si->ps.v5_mem_type & 0x0400))
{
ACCW(MCTLWTST,
((si->ps.mctlwtst_reg & 0xfffffff8) | pwr_cas[(si->ps.mctlwtst_reg & 0x07)]));
}
VGAW_I(CRTC,0x11,0);
if (si->ps.secondary_head)
{
CR2W(DATACTL,0x00000000);
}
gx50_general_output_select();
* make sure CRTC1 sync outputs are patched through! */
DXIW(SYNCCTRL,0x00);
return B_OK;
}
status_t gx50_general_output_select()
{
if ((si->ps.card_type != G450) && (si->ps.card_type != G550)) return B_ERROR;
if (si->ps.primary_dvi && si->ps.secondary_head && si->ps.tvout)
{
if (i2c_sec_tv_adapter() == B_OK)
{
LOG(4,("INIT: secondary TV-adapter detected, using primary connector\n"));
DXIW(OUTPUTCONN,0x01);
si->crossed_conns = false;
}
else
{
LOG(4,("INIT: no secondary TV-adapter detected, using secondary connector\n"));
DXIW(OUTPUTCONN,0x04);
si->crossed_conns = true;
}
}
else
{
LOG(4,("INIT: using primary connector\n"));
DXIW(OUTPUTCONN,0x01);
si->crossed_conns = false;
}
return B_OK;
}
status_t gx00_general_dac_select(int dac)
{
switch(dac)
{
case DS_CRTC1DAC:
case DS_CRTC1DAC_CRTC2MAVEN:
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1);
* enable CRTC2 external video timing reset signal.
* (Setting for MAVEN 'master mode' TVout signal generation.) */
if (si->ps.secondary_head) CR2W(CTL,(CR2R(CTL)&0xffe00779)|0xD0000002);
VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0x77));
DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x82);
break;
case DS_CRTC1MAVEN:
case DS_CRTC1MAVEN_CRTC2DAC:
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x2);
* disable CRTC2 external video timing reset signal */
if (si->ps.secondary_head) CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x1<<20));
* note: this is nolonger used as G450/G550 cannot do TVout on CRTC1 */
VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)|0x88));
DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x02);
break;
case DS_CRTC1CON1_CRTC2CON2:
if (si->ps.card_type < G450) return B_ERROR;
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1);
* external video timing reset signal, set CRTC2 progressive scan mode
* and disable TVout mode (b12).
* (Setting for MAVEN 'slave mode' TVout signal generation.) */
CR2W(CTL,(CR2R(CTL)&0x2de00779)|0x6|(0x0<<20));
DXIW(OUTPUTCONN,0x09);
DXIW(GENIOCTRL, DXIR(GENIOCTRL) & ~0x40);
DXIW(GENIODATA, 0x00);
si->crossed_conns = false;
break;
case DS_CRTC1CON2_CRTC2CON1:
if (si->ps.card_type < G450) return B_ERROR;
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1);
* video timing reset signal, and set CRTC2 progressive scan mode and
* disable TVout mode (b12). */
CR2W(CTL,(CR2R(CTL)&0x2de00779)|0x6|(0x1<<20));
DXIW(OUTPUTCONN,0x05);
DXIW(GENIOCTRL, DXIR(GENIOCTRL) & ~0x40);
DXIW(GENIODATA, 0x00);
si->crossed_conns = true;
break;
default:
return B_ERROR;
}
return B_OK;
}
static
status_t gx00_general_bios_to_powergraphics()
{
LOG(2, ("INIT: Skipping card coldstart!\n"));
CFGW(DEVCTRL,(2|CFGR(DEVCTRL)));
VGAW_I(CRTC,0x11,0);
VGAW_I(CRTCEXT,3,0x80);
VGAW(MISCW,0x08);
switch (si->ps.card_type)
{
case G400:
case G400MAX:
if (si->ps.tvout)
{
ACCW(RST, 0x00000002);
snooze(1000);
ACCW(RST, 0x00000000);
}
DXIW(MAFCDEL,0x02);
break;
case G450:
case G550:
DXIW(PWRCTRL,0x1b);
* connectors and make sure CRTC1 sync outputs are patched through! */
DXIW(SYNCCTRL,0x00);
break;
default:
break;
}
if (si->ps.card_type >= G100)
{
DXIW(MISCCTRL,0x9b);
DXIW(MULCTRL,0x4);
}
else
{
LOG(8, ("INIT: < G100 DAC powerup badly implemented, MISC 0x%02x\n", VGAR(MISCR)));
}
VGAW_I(SEQ,1,0x00);
return B_OK;
}
* 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 gx00_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode)
{
* 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;
switch (si->ps.card_type)
{
case MIL1:
case MIL2:
* these cards always use a 64bit RAMDAC (TVP3026) and interleaved memory */
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;
case B_RGB32: acc_mask = 0x1f; depth = 32; break;
default:
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
return B_ERROR;
}
break;
default:
* 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;
case B_RGB32: depth = 32; break;
default:
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
return B_ERROR;
}
acc_mask = 0x1f;
break;
}
* (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)
{
case MIL1:
case MIL2:
* these cards always use a 64bit RAMDAC and interleaved memory */
switch (target->space)
{
case B_CMAP8: crtc_mask = 0x7f; break;
case B_RGB15: crtc_mask = 0x3f; break;
case B_RGB16: crtc_mask = 0x3f; break;
case B_RGB24: crtc_mask = 0x7f; break;
case B_RGB32: crtc_mask = 0x1f; break;
default:
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
return B_ERROR;
}
break;
default:
switch (target->space)
{
case B_CMAP8: crtc_mask = 0x0f; break;
case B_RGB15: crtc_mask = 0x07; break;
case B_RGB16: crtc_mask = 0x07; break;
case B_RGB24: crtc_mask = 0x0f; break;
case B_RGB32: crtc_mask = 0x03; break;
default:
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
return B_ERROR;
}
* set for RGB and B_YCbCr422 modes. Other modes need larger multiples! */
if (target->flags & DUALHEAD_BITS)
{
switch (target->space)
{
case B_RGB16: crtc_mask = 0x1f; break;
case B_RGB32: crtc_mask = 0x0f; break;
default:
LOG(8,("INIT: illegal DH color space: 0x%08x\n", target->space));
return B_ERROR;
}
}
break;
}
* Max sizes need to adhere to both the acceleration engine _and_ the CRTC constraints! */
*acc_mode = true;
switch (si->ps.card_type)
{
case MIL1:
case MIL2:
case G100:
if (target->virtual_width > 2048) *acc_mode = false;
break;
default:
if (target->virtual_width > 4096) *acc_mode = false;
if ((target->space == B_RGB32_LITTLE) && (target->virtual_width > (4092 & ~acc_mask)))
*acc_mode = false;
break;
}
if (target->virtual_height > 2048) *acc_mode = false;
* 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. */
{
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;
case B_RGB32_LITTLE:
if (target->virtual_width > (4092 & ~crtc_mask))
target->virtual_width = (4092 & ~crtc_mask);
break;
}
* 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;
}
* 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)));
*bytes_per_row = video_pitch * (depth >> 3);
return B_OK;
}