openBeOS_Matrox_V0.13beta2_src
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5536 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -158,8 +158,8 @@ status_t check_overlay_capability(uint32 feature)
|
||||
switch(si->ps.card_type)
|
||||
{
|
||||
case G200:
|
||||
case G400: /* is also G400MAX in accelerant for now? */
|
||||
case G400MAX: /* not used in accelerant yet? */
|
||||
case G400:
|
||||
case G400MAX:
|
||||
case G450: /* is also G550 in accelerant for now */
|
||||
case G550: /* not used in accelerant yet */
|
||||
/* export video overlay functions */
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Other authors:
|
||||
Mark Watson
|
||||
Rudolf Cornelissen 9/2002
|
||||
Rudolf Cornelissen 9-11/2002
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x02000000
|
||||
@@ -42,6 +42,7 @@ status_t GET_FRAME_BUFFER_CONFIG(frame_buffer_config *afb)
|
||||
status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high)
|
||||
{
|
||||
uint32 max_pclk = 0;
|
||||
uint32 min_pclk = 0;
|
||||
|
||||
/* check for NULL pointers */
|
||||
if ((dm == NULL) || (low == NULL) || (high == NULL)) return B_ERROR;
|
||||
@@ -123,7 +124,14 @@ status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high)
|
||||
}
|
||||
/* return values in kHz */
|
||||
*high = max_pclk * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
/* clamp lower limit to 48Hz vertical refresh for now.
|
||||
* Apparantly the BeOS screenprefs app does limit the upper refreshrate to 90Hz,
|
||||
* while it does not limit the lower refreshrate. */
|
||||
min_pclk = ((uint32)dm->timing.h_total * (uint32)dm->timing.v_total * 48) / 1000;
|
||||
if (min_pclk > *low) *low = min_pclk;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Written by Rudolf Cornelissen 05/09-2002 V0.13 beta1 */
|
||||
/* Written by Rudolf Cornelissen 05/10-2002 */
|
||||
|
||||
/* Note on 'missing features' in BeOS 5.0.3 and DANO:
|
||||
* BeOS needs to define more colorspaces! It would be nice if BeOS would support the FourCC 'definitions'
|
||||
@@ -7,20 +7,6 @@
|
||||
|
||||
#define MODULE_BIT 0x00000400
|
||||
|
||||
/* Note:
|
||||
* In order to enable OVERLAY logging, in file mga.settings include a line with:
|
||||
*
|
||||
* logmask 0x08000604 # log OVERLAY use in full
|
||||
*
|
||||
* Make sure you copy the resulting file to ~/config/settings/kernel/drivers/ !
|
||||
*
|
||||
* Beware that enabling OVERLAY logging will create a very large logfile quickly in
|
||||
* your home folder (named mga.accelerant.log) if you use double buffered overlay
|
||||
* playback (100Mb will be reached in 'no time', like in a few days or so.).
|
||||
*
|
||||
* For testing purposes, you might want to have full logging enabled though...
|
||||
*/
|
||||
|
||||
#include "acc_std.h"
|
||||
|
||||
/* define the supported overlay input colorspaces */
|
||||
@@ -591,11 +577,6 @@ status_t CONFIGURE_OVERLAY
|
||||
{
|
||||
int offset = 0; /* used for buffer index */
|
||||
|
||||
/* in BeOS R5.0.3 (maybe DANO works different):
|
||||
* '*ov' is the output size on the desktop: does not change if clipped.
|
||||
* h_start and v_start are always 0, width and heigth are the size of the window.
|
||||
* Because the width and height can also be found in '*ow', '*ov' is not used. */
|
||||
|
||||
LOG(4,("Overlay: Configure_overlay called: "));
|
||||
|
||||
/* Note:
|
||||
@@ -649,7 +630,7 @@ status_t CONFIGURE_OVERLAY
|
||||
{
|
||||
LOG(4,("succesfull, switching to buffer %d\n", offset));
|
||||
|
||||
gx00_configure_bes(ob, ow, offset);
|
||||
gx00_configure_bes(ob, ow, ov, offset);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Other authors:
|
||||
Mark Watson,
|
||||
Apsed,
|
||||
Rudolf Cornelissen 10/2002
|
||||
Rudolf Cornelissen 11-12/2002
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00200000
|
||||
@@ -29,16 +29,6 @@ static void interrupt_enable(bool flag) {
|
||||
result = ioctl(fd, GX00_RUN_INTERRUPTS, &sbs, sizeof(sbs));
|
||||
}
|
||||
|
||||
// apsed TODO gx00_crtc_mem_priority() ??
|
||||
// /*calculate if high priority request are needed and how many*/
|
||||
// Tpix = 1000000.0/(dm->timing.pixel_clock);
|
||||
// Tmclk = si->ps.mem_clk_period;
|
||||
// temp = (128/colour_depth);
|
||||
// HIPRILVL = 64*Tmclk + (1-46*(temp))*Tpix;
|
||||
// HIPRILVL/= -8*Tpix*temp;
|
||||
// gx00_crtc_mem_priority((uint8)HIPRILVL);
|
||||
// /*XXX - memory priority*/
|
||||
|
||||
/* First validate the mode, then call lots of bit banging stuff to set the mode(s)! */
|
||||
status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
{
|
||||
@@ -47,8 +37,6 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
uint8 colour_depth=32;
|
||||
status_t result;
|
||||
uint32 startadd,startadd_right;
|
||||
// double HIPRILVL;
|
||||
// double Tmclk,Tpix,temp;
|
||||
// apsed TODO startadd is 19 bits if < g200
|
||||
|
||||
uint8 display,h,v;
|
||||
@@ -100,7 +88,8 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
LOG(1,("DUALHEAD: %d\n",target.flags&DUALHEAD_BITS));
|
||||
if ((target.flags&DUALHEAD_BITS)) /*if some dualhead mode*/
|
||||
{
|
||||
|
||||
uint16 crtc1_vdisplay, crtc2_vdisplay;
|
||||
|
||||
/*set the pixel clock PLL(s)*/
|
||||
if (gx00_dac_set_pix_pll(target)==B_ERROR)
|
||||
LOG(8,("SET: error setting pixel clock (internal DAC)\n"));
|
||||
@@ -114,18 +103,20 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
LOG(8,("SET: not setting maven clock (G450?)\n"));
|
||||
}
|
||||
|
||||
/*set the colour depth for CRTC1, CRTC2 and the DAC*/
|
||||
/*set the colour depth for CRTC1, CRTC2, the DAC and the MAVEN */
|
||||
switch(target.space)
|
||||
{
|
||||
case B_RGB16_LITTLE:
|
||||
colour_depth=16;
|
||||
gx00_dac_mode(BPP16,1.0);
|
||||
gx00_dac_mode(BPP16, 1.0);
|
||||
gx00_maven_mode(BPP16, 1.0);
|
||||
gx00_crtc_depth(BPP16);
|
||||
g400_crtc2_depth(BPP16);
|
||||
break;
|
||||
case B_RGB32_LITTLE:
|
||||
colour_depth=32;
|
||||
gx00_dac_mode(BPP32,1.0);
|
||||
gx00_dac_mode(BPP32, 1.0);
|
||||
gx00_maven_mode(BPP32DIR, 1.0);
|
||||
gx00_crtc_depth(BPP32);
|
||||
g400_crtc2_depth(BPP32DIR);
|
||||
break;
|
||||
@@ -140,16 +131,130 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
/*work out where the "right" screen starts*/
|
||||
startadd_right=startadd+(target.timing.h_display*(colour_depth>>3));
|
||||
|
||||
/*set the output DAC*/
|
||||
/* calculate needed MAVEN-CRTC delay: formula valid for straight-through CRTC's */
|
||||
si->crtc_delay = 44 + 0 * (colour_depth == 16);
|
||||
|
||||
/* setup vertical timing adjust for crtc1 and crtc2 for straight-through CRTC's */
|
||||
crtc1_vdisplay = target.timing.v_display;
|
||||
/* (extra "blanking" line for MAVEN) */
|
||||
crtc2_vdisplay = target.timing.v_display + 1;
|
||||
|
||||
/* set the outputs */
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
case G450:
|
||||
gx00_general_dac_select(DS_CRTCDAC_CRTC2DAC2);
|
||||
switched_crtcs = false;
|
||||
case G400:
|
||||
case G400MAX:
|
||||
switch (target.flags&DUALHEAD_BITS)
|
||||
{
|
||||
case DUALHEAD_ON:
|
||||
case DUALHEAD_CLONE:
|
||||
gx00_general_dac_select(DS_CRTC1DAC_CRTC2MAVEN);
|
||||
switched_crtcs = false;
|
||||
break;
|
||||
case DUALHEAD_SWITCH:
|
||||
if (i2c_sec_tv_adapter() == B_OK)
|
||||
{
|
||||
/* Don't switch CRTC's because MAVEN YUV is impossible then,
|
||||
* and primary head output will be limited to 135Mhz pixelclock. */
|
||||
LOG(4,("SET: secondary TV-adapter detected, switching buffers\n"));
|
||||
gx00_general_dac_select(DS_CRTC1DAC_CRTC2MAVEN);
|
||||
switched_crtcs = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This limits the pixelclocks on both heads to 135Mhz,
|
||||
* but you can use overlay on the other output now. */
|
||||
LOG(4,("SET: no secondary TV-adapter detected, switching CRTCs\n"));
|
||||
gx00_general_dac_select(DS_CRTC1MAVEN_CRTC2DAC);
|
||||
switched_crtcs = false;
|
||||
/* re-calculate MAVEN-CRTC delay: formula valid for crossed CRTC's */
|
||||
si->crtc_delay = 17 + 4 * (colour_depth == 16);
|
||||
/* re-setup vertical timing adjust for crtc1 and crtc2 for crossed CRTC's */
|
||||
/* (extra "blanking" line for MAVEN) */
|
||||
crtc1_vdisplay = target.timing.v_display + 1;
|
||||
crtc2_vdisplay = target.timing.v_display;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case G400:case G400MAX:
|
||||
gx00_general_dac_select(DS_CRTCMAVEN_CRTC2DAC);
|
||||
switched_crtcs = false;
|
||||
//fixme:
|
||||
//use current SETMODE MAVEN programming only on G400/G400MAX;
|
||||
//and copy & modify/resetup this stuff for G450(?)/G550 cards!
|
||||
//warning:
|
||||
//setup crtc_delay and vertical timing adjust for G450(?)/G550,
|
||||
//and remove the '+1' in crtc2 vertical timing(?)
|
||||
case G450:
|
||||
case G550:
|
||||
if (!si->ps.primary_dvi)
|
||||
/* output connector use is always 'straight-through' */
|
||||
//fixme: re-evaluate when DVI is setup...
|
||||
{
|
||||
switch (target.flags&DUALHEAD_BITS)
|
||||
{
|
||||
case DUALHEAD_ON:
|
||||
case DUALHEAD_CLONE:
|
||||
gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2);
|
||||
switched_crtcs = false;
|
||||
break;
|
||||
case DUALHEAD_SWITCH:
|
||||
if (i2c_sec_tv_adapter() == B_OK)
|
||||
{
|
||||
/* Don't switch CRTC's because MAVEN YUV and TVout is impossible then,
|
||||
* and primary head output will be limited to 235Mhz pixelclock. */
|
||||
LOG(4,("SET: secondary TV-adapter detected, switching buffers\n"));
|
||||
gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2);
|
||||
switched_crtcs = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This limits the pixelclocks on both heads to 235Mhz,
|
||||
* but you can use overlay on the other output now. */
|
||||
LOG(4,("SET: no secondary TV-adapter detected, switching CRTCs\n"));
|
||||
gx00_general_dac_select(DS_CRTC1CON2_CRTC2CON1);
|
||||
switched_crtcs = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* output connector use is cross-linked if no TV cable connected! */
|
||||
//fixme: re-evaluate when DVI is setup...
|
||||
{
|
||||
switch (target.flags&DUALHEAD_BITS)
|
||||
{
|
||||
case DUALHEAD_ON:
|
||||
case DUALHEAD_CLONE:
|
||||
if (i2c_sec_tv_adapter() == B_OK)
|
||||
{
|
||||
gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2);
|
||||
switched_crtcs = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This limits the pixelclocks on both heads to 235Mhz,
|
||||
* but you can use overlay on the other output now. */
|
||||
gx00_general_dac_select(DS_CRTC1CON2_CRTC2CON1);
|
||||
switched_crtcs = false;
|
||||
}
|
||||
break;
|
||||
case DUALHEAD_SWITCH:
|
||||
if (i2c_sec_tv_adapter() == B_OK)
|
||||
{
|
||||
/* Don't switch CRTC's because MAVEN YUV and TVout is impossible then,
|
||||
* and primary head output will be limited to 235Mhz pixelclock. */
|
||||
LOG(4,("SET: secondary TV-adapter detected, switching buffers\n"));
|
||||
gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2);
|
||||
switched_crtcs = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(4,("SET: no secondary TV-adapter detected, switching CRTCs\n"));
|
||||
gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2);
|
||||
switched_crtcs = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -163,21 +268,17 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
}
|
||||
|
||||
/*Tell card what memory to display*/
|
||||
si->crtc_delay=17+4*(colour_depth==16);
|
||||
switch (target.flags&DUALHEAD_BITS)
|
||||
{
|
||||
case DUALHEAD_ON:
|
||||
gx00_crtc_set_display_start(startadd_right,colour_depth);
|
||||
g400_crtc2_set_display_start(startadd,colour_depth);
|
||||
case DUALHEAD_SWITCH:
|
||||
gx00_crtc_set_display_start(startadd,colour_depth);
|
||||
g400_crtc2_set_display_start(startadd_right,colour_depth);
|
||||
break;
|
||||
case DUALHEAD_CLONE:
|
||||
gx00_crtc_set_display_start(startadd,colour_depth);
|
||||
g400_crtc2_set_display_start(startadd,colour_depth);
|
||||
break;
|
||||
case DUALHEAD_SWITCH:
|
||||
gx00_crtc_set_display_start(startadd,colour_depth);
|
||||
g400_crtc2_set_display_start(startadd_right,colour_depth);
|
||||
break;
|
||||
}
|
||||
|
||||
/*set the timing*/
|
||||
@@ -187,7 +288,7 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
target.timing.h_sync_start,
|
||||
target.timing.h_sync_end,
|
||||
target.timing.h_total,
|
||||
(target.timing.v_display+1), /*extra "blanking" line for MAVEN*/
|
||||
crtc1_vdisplay,
|
||||
target.timing.v_sync_start,
|
||||
target.timing.v_sync_end,
|
||||
target.timing.v_total,
|
||||
@@ -201,7 +302,7 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
target.timing.h_sync_start,
|
||||
target.timing.h_sync_end,
|
||||
target.timing.h_total,
|
||||
(target.timing.v_display),
|
||||
crtc2_vdisplay,
|
||||
target.timing.v_sync_start,
|
||||
target.timing.v_sync_end,
|
||||
target.timing.v_total,
|
||||
@@ -216,7 +317,7 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
target.timing.h_sync_start,
|
||||
target.timing.h_sync_end,
|
||||
target.timing.h_total,
|
||||
(target.timing.v_display+1), /*extra "blanking" line*/
|
||||
(target.timing.v_display+1), /* The extra "blanking" line */
|
||||
target.timing.v_sync_start,
|
||||
target.timing.v_sync_end,
|
||||
target.timing.v_total,
|
||||
@@ -234,6 +335,7 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
/*TVout support*/
|
||||
if (si->ps.secondary_tvout && (target.flags&TV_BITS))
|
||||
{
|
||||
//fixme: re-tune if needed, checkout cross and straight crtc's seperately..
|
||||
si->crtc_delay+=5;
|
||||
|
||||
/*create a my tim(m)ing structure... for tvout*/
|
||||
@@ -251,12 +353,12 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
if (target.flags&TV_PAL)
|
||||
{
|
||||
LOG(2, ("OUTMODE: PAL\n"));
|
||||
maven_set_mode(2);
|
||||
maven_set_mode(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(2, ("OUTMODE: NTSC\n"));
|
||||
maven_set_mode(1);
|
||||
maven_set_mode(2);
|
||||
}
|
||||
|
||||
maven_out_compute(&tv_timing, &tv_regs);
|
||||
@@ -301,8 +403,23 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
|
||||
/*tell the card what memory to display*/
|
||||
gx00_crtc_set_display_start(startadd,colour_depth);
|
||||
if (si->ps.card_type >= G100)
|
||||
gx00_general_dac_select(DS_CRTCDAC_CRTC2MAVEN);
|
||||
/* enable primary analog output */
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
case G100:
|
||||
case G200:
|
||||
case G400:
|
||||
case G400MAX:
|
||||
gx00_general_dac_select(DS_CRTC1DAC_CRTC2MAVEN);
|
||||
break;
|
||||
case G450:
|
||||
case G550:
|
||||
gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2);
|
||||
gx50_general_output_select();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*set the timing*/
|
||||
result = gx00_crtc_set_timing /*crtc1*/
|
||||
@@ -344,6 +461,9 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
/* enable interrupts using the kernel driver */
|
||||
interrupt_enable(true);
|
||||
|
||||
/* optimize memory-access if needed */
|
||||
gx00_crtc_mem_priority(colour_depth);
|
||||
|
||||
/* Tune RAM CAS-latency if needed. Must be done *here*! */
|
||||
mga_set_cas_latency();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* MGA Acceleration functions */
|
||||
/* Authors:
|
||||
Mark Watson 2/2000,
|
||||
Rudolf Cornelissen 10/2002
|
||||
Rudolf Cornelissen 10-12/2002
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00080000
|
||||
@@ -44,21 +44,20 @@ status_t gx00_acc_init()
|
||||
{
|
||||
ACCW(OPMODE,0); // cleanup bitblt
|
||||
|
||||
/*Set the Z origin to the start of FB (otherwise lockup on blits)*/
|
||||
if (si->ps.card_type>=G100)
|
||||
ACCW(ZORG,0);
|
||||
/* Set the Z origin to the start of FB (otherwise lockup on blits) */
|
||||
if (si->ps.card_type>=G100) ACCW(ZORG,0);
|
||||
|
||||
/*MACCESS - for 2D, only pixel width is important > all others can be 0*/
|
||||
/* Set pixel width */
|
||||
switch(si->dm.space)
|
||||
{
|
||||
case B_CMAP8:
|
||||
ACCW(MACCESS,0);
|
||||
ACCW(MACCESS, ((ACCR(MACCESS) & 0xfffffffc) | 0x00));
|
||||
break;
|
||||
case B_RGB15_LITTLE:case B_RGB16_LITTLE:
|
||||
ACCW(MACCESS,1);
|
||||
ACCW(MACCESS, ((ACCR(MACCESS) & 0xfffffffc) | 0x01));
|
||||
break;
|
||||
case B_RGB32_LITTLE:case B_RGBA32_LITTLE:
|
||||
ACCW(MACCESS,2);
|
||||
ACCW(MACCESS, ((ACCR(MACCESS) & 0xfffffffc) | 0x02));
|
||||
break;
|
||||
default:
|
||||
LOG(8,("ACC: init, invalid bit depth\n"));
|
||||
@@ -81,9 +80,9 @@ if ((si->ps.card_type==MIL2) && (si->dm.space==B_CMAP8)) {
|
||||
// ylin shall be 1 if 800x600
|
||||
ACCW(PITCH, (1<<15) | (si->dm.virtual_width&0x0FFF));
|
||||
}
|
||||
/*PLNWT - plane write mask*/
|
||||
// if (si->ps.card_type>=G200) // apsed: PLNWT exists also in MIL2, G100
|
||||
ACCW(PLNWT,0xFFFFFFFF); /*all planes are written*/
|
||||
/* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
|
||||
ACCW(PLNWT,0x00000000);
|
||||
ACCW(PLNWT,0xffffffff);
|
||||
|
||||
if (si->ps.card_type>=G200) {
|
||||
/*DSTORG - location of active screen in framebuffer*/
|
||||
@@ -93,8 +92,7 @@ if ((si->ps.card_type==MIL2) && (si->dm.space==B_CMAP8)) {
|
||||
ACCW(SRCORG,(si->fbc.frame_buffer)-(si->framebuffer));
|
||||
}
|
||||
|
||||
/*YDSTORG - apsed, if not inited, BitBlts may fails on g200, see YTOP/BOT after */
|
||||
/* Used for G100, included in acceleration routines also: */
|
||||
/* init YDSTORG - apsed, if not inited, BitBlts may fails on g200 */
|
||||
src_dst = 0;
|
||||
ACCW(YDSTORG, src_dst);
|
||||
|
||||
@@ -120,13 +118,15 @@ if ((si->ps.card_type==MIL2) && (si->dm.space==B_CMAP8)) {
|
||||
}
|
||||
ACCW(YDSTORG,src_dst);
|
||||
|
||||
/*clipping*/
|
||||
ACCW(CXBNDRY,((si->dm.virtual_width -1)<<16)|(0)); /*i.e. highest and lowest right pixel value*/
|
||||
/* clipping */
|
||||
/* i.e. highest and lowest X pixel adresses */
|
||||
ACCW(CXBNDRY,((si->dm.virtual_width - 1) << 16) | (0));
|
||||
|
||||
// apsed TODO g200 shall be YDSTORG + value
|
||||
// apsed TODO why -1, must be a multiple of 32 since MIl2
|
||||
ACCW(YTOP,0);
|
||||
ACCW(YBOT,(si->dm.virtual_height*si->dm.virtual_width)-1); /*y address must be linear*/
|
||||
/* Y pixel addresses must be linear */
|
||||
/* lowest adress */
|
||||
ACCW(YTOP, 0 + src_dst);
|
||||
/* highest adress */
|
||||
ACCW(YBOT,((si->dm.virtual_height - 1) * si->dm.virtual_width) + src_dst);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,32 @@
|
||||
/* G200-G550 Back End Scaler functions V0.13 beta1 */
|
||||
/* Written by Rudolf Cornelissen 05/08-2002 */
|
||||
/* G200-G550 Back End Scaler functions */
|
||||
/* Written by Rudolf Cornelissen 05/11-2002 */
|
||||
|
||||
#define MODULE_BIT 0x00000200
|
||||
|
||||
#include "mga_std.h"
|
||||
|
||||
status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow, int offset)
|
||||
status_t gx00_configure_bes
|
||||
(const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov, int offset)
|
||||
{
|
||||
/* yuy2 (4:2:2) colorspace calculations */
|
||||
/* Note: Some calculations will have to be modified for other colorspaces if they are incorporated. */
|
||||
|
||||
/* Note:
|
||||
* in BeOS R5.0.3 (maybe DANO works different):
|
||||
* in BeOS R5.0.3 and DANO:
|
||||
* 'ow->offset_xxx' is always 0, so not used;
|
||||
* 'ow->width' and 'ow->height' are the output window size: does not change
|
||||
* if window is clipping;
|
||||
* 'ow->h_start' and 'ow->v_start' are the left-top position of the output
|
||||
* window. These values can be negative: this means the window is clipping
|
||||
* at the left or the top of the display, respectively. */
|
||||
|
||||
|
||||
/* 'ov' is the view in the source bitmap, so which part of the bitmap is actually
|
||||
* displayed on screen. This is used for the 'hardware zoom' function. */
|
||||
|
||||
/* calculated BES register values */
|
||||
uint32 hcoordv, vcoordv, hiscalv, hsrcstv, hsrcendv, hsrclstv,
|
||||
viscalv, a1orgv, v1wghtv, v1srclstv, globctlv, ctlv;
|
||||
/* misc used variables */
|
||||
uint32 temp32;
|
||||
uint16 temp1, temp2;
|
||||
/* interval representation, used for scaling calculations */
|
||||
uint16 intrep;
|
||||
@@ -28,6 +34,8 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
uint32 ifactor;
|
||||
/* used for vertical weight starting value */
|
||||
uint32 weight;
|
||||
/* copy of overlay view which has checked valid values */
|
||||
overlay_view my_ov;
|
||||
|
||||
/* Slowdown the G200-G550 BES if the pixelclock is too high for it to cope.
|
||||
* This will in fact half the horizontal resolution of the BES with high
|
||||
@@ -57,25 +65,32 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
*** sync to BES (Back End Scaler) ***
|
||||
*************************************/
|
||||
/**************************************************************************************
|
||||
*** copy, check and limit if needed the user-specified view into the intput bitmap ***
|
||||
**************************************************************************************/
|
||||
my_ov = *ov;
|
||||
/* check for valid 'coordinates' */
|
||||
if (my_ov.width == 0) my_ov.width++;
|
||||
if (my_ov.height == 0) my_ov.height++;
|
||||
if (my_ov.h_start > ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1))
|
||||
my_ov.h_start = ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1);
|
||||
if (((my_ov.h_start + my_ov.width) - 1) > ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1))
|
||||
my_ov.width = ((((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1) - my_ov.h_start) + 1);
|
||||
if (my_ov.v_start > (ob->height - 1))
|
||||
my_ov.v_start = (ob->height - 1);
|
||||
if (((my_ov.v_start + my_ov.height) - 1) > (ob->height - 1))
|
||||
my_ov.height = (((ob->height - 1) - my_ov.v_start) + 1);
|
||||
|
||||
/* Make sure reprogramming the BES completes before the next retrace occurs, to prevent
|
||||
* register-update glitches (double buffer feature).
|
||||
* Programming the BES needs about 50 lines with a 1600 x 1200 x 90Hz screen with
|
||||
* logging mostly disabled on a P3-500. */
|
||||
LOG(6,("Overlay: inputbuffer view (zoom) left %d, top %d, width %d, height %d\n",
|
||||
my_ov.h_start, my_ov.v_start, my_ov.width, my_ov.height));
|
||||
|
||||
LOG(3,("Overlay: entering at Vcount %d\n", CR1R(VCOUNT)));
|
||||
while (CR1R(VCOUNT) > (si->dm.timing.v_total - 100));
|
||||
LOG(3,("Overlay: starting at Vcount %d\n", CR1R(VCOUNT)));
|
||||
|
||||
/****************************************
|
||||
*** setup all edges of output window ***
|
||||
****************************************/
|
||||
|
||||
/* setup left and right edges of output window */
|
||||
temp32 = 0;
|
||||
hcoordv = 0;
|
||||
/* left edge coordinate of output window, must be inside desktop */
|
||||
/* clipping on the left side */
|
||||
if (ow->h_start < 0)
|
||||
@@ -96,7 +111,7 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
temp1 = (uint16)ow->h_start & 0x7ff;
|
||||
}
|
||||
}
|
||||
temp32 |= temp1 << 16;
|
||||
hcoordv |= temp1 << 16;
|
||||
/* right edge coordinate of output window, must be inside desktop */
|
||||
/* width < 2 is not allowed */
|
||||
if (ow->width < 2)
|
||||
@@ -125,12 +140,11 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
}
|
||||
}
|
||||
}
|
||||
temp32 |= temp2 << 0;
|
||||
BESW(HCOORD, temp32);
|
||||
hcoordv |= temp2 << 0;
|
||||
LOG(4,("Overlay: left-edge output %d, right-edge output %d\n",temp1, temp2));
|
||||
|
||||
/* setup top and bottom edges of output window */
|
||||
temp32 = 0;
|
||||
vcoordv = 0;
|
||||
/* top edge coordinate of output window, must be inside desktop */
|
||||
/* clipping on the top side */
|
||||
if (ow->v_start < 0)
|
||||
@@ -151,7 +165,7 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
temp1 = (uint16)ow->v_start & 0x7ff;
|
||||
}
|
||||
}
|
||||
temp32 |= temp1 << 16;
|
||||
vcoordv |= temp1 << 16;
|
||||
/* bottom edge coordinate of output window, must be inside desktop */
|
||||
/* height < 2 is not allowed */
|
||||
if (ow->height < 2)
|
||||
@@ -180,8 +194,7 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
}
|
||||
}
|
||||
}
|
||||
temp32 |= temp2 << 0;
|
||||
BESW(VCOORD, temp32);
|
||||
vcoordv |= temp2 << 0;
|
||||
LOG(4,("Overlay: top-edge output %d, bottom-edge output %d\n",temp1, temp2));
|
||||
|
||||
|
||||
@@ -189,16 +202,16 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
*** setup horizontal scaling and clipping ***
|
||||
*********************************************/
|
||||
|
||||
LOG(4,("Overlay: input picture width = %d, height = %d\n",
|
||||
LOG(6,("Overlay: total input picture width = %d, height = %d\n",
|
||||
(ob->width - si->overlay.myBufInfo[offset].slopspace), ob->height));
|
||||
LOG(4,("Overlay: output picture width = %d, height = %d\n", ow->width, ow->height));
|
||||
LOG(6,("Overlay: output picture width = %d, height = %d\n", ow->width, ow->height));
|
||||
|
||||
/* do horizontal scaling... */
|
||||
/* determine interval representation value */
|
||||
/* determine interval representation value, taking zoom into account */
|
||||
if (ow->flags & B_OVERLAY_HORIZONTAL_FILTERING)
|
||||
{
|
||||
/* horizontal filtering is ON */
|
||||
if (((ob->width - si->overlay.myBufInfo[offset].slopspace) == ow->width) | (ow->width < 2))
|
||||
if ((my_ov.width == ow->width) | (ow->width < 2))
|
||||
{
|
||||
/* no horizontal scaling used, OR destination width < 2 */
|
||||
intrep = 0;
|
||||
@@ -211,7 +224,7 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
else
|
||||
{
|
||||
/* horizontal filtering is OFF */
|
||||
if ((ow->width < (ob->width - si->overlay.myBufInfo[offset].slopspace)) & (ow->width >= 2))
|
||||
if ((ow->width < my_ov.width) & (ow->width >= 2))
|
||||
{
|
||||
/* horizontal downscaling used AND destination width >= 2 */
|
||||
intrep = 1;
|
||||
@@ -223,32 +236,33 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
}
|
||||
LOG(4,("Overlay: horizontal interval representation value is %d\n",intrep));
|
||||
|
||||
/* calculate inverse horizontal scaling factor */
|
||||
/* (using standard scaling formula: neglecting round-off var as extra error is very small..) */
|
||||
ifactor = ((ob->width - si->overlay.myBufInfo[offset].slopspace - intrep) << 16) /
|
||||
(ow->width - intrep);
|
||||
/* calculate inverse horizontal scaling factor, taking zoom into account */
|
||||
/* standard scaling formula: */
|
||||
ifactor = (((uint32)(my_ov.width - intrep)) << 16) / (ow->width - intrep);
|
||||
|
||||
/* correct factor to prevent most-right visible 'line' from distorting */
|
||||
ifactor -= (1 << 2);
|
||||
LOG(4,("Overlay: horizontal scaling factor is %f\n", (float)65536 / ifactor));
|
||||
|
||||
/* compensate for accelerated 2x zoom (slowdown BES if pixelclock is too high) */
|
||||
temp32 = ifactor * acczoom;
|
||||
LOG(4,("Overlay: horizontal speed compensated factor is %f\n", (float)65536 / temp32));
|
||||
hiscalv = ifactor * acczoom;
|
||||
LOG(4,("Overlay: horizontal speed compensated factor is %f\n", (float)65536 / hiscalv));
|
||||
|
||||
/* check scaling factor (and modify if needed) to be within scaling limits */
|
||||
if ((((ob->width - si->overlay.myBufInfo[offset].slopspace) << 16) / 16384) > temp32)
|
||||
if (((((uint32)my_ov.width) << 16) / 16384) > hiscalv)
|
||||
{
|
||||
/* (non-inverse) factor too large, set factor to max. valid value */
|
||||
temp32 = (((ob->width - si->overlay.myBufInfo[offset].slopspace) << 16) / 16384);
|
||||
LOG(4,("Overlay: horizontal scaling factor too large, clamping at %f\n", (float)65536 / temp32));
|
||||
hiscalv = ((((uint32)my_ov.width) << 16) / 16384);
|
||||
LOG(4,("Overlay: horizontal scaling factor too large, clamping at %f\n", (float)65536 / hiscalv));
|
||||
}
|
||||
if (temp32 >= (32 << 16))
|
||||
if (hiscalv >= (32 << 16))
|
||||
{
|
||||
/* (non-inverse) factor too small, set factor to min. valid value */
|
||||
temp32 = 0x1ffffc;
|
||||
LOG(4,("Overlay: horizontal scaling factor too small, clamping at %f\n", (float)65536 / temp32));
|
||||
hiscalv = 0x1ffffc;
|
||||
LOG(4,("Overlay: horizontal scaling factor too small, clamping at %f\n", (float)65536 / hiscalv));
|
||||
}
|
||||
/* AND below is required by hardware */
|
||||
temp32 &= 0x001ffffc;
|
||||
BESW(HISCAL, temp32);
|
||||
hiscalv &= 0x001ffffc;
|
||||
|
||||
|
||||
/* do horizontal clipping... */
|
||||
@@ -256,11 +270,12 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
/* Note:
|
||||
* The method is to calculate, based on 1:1 scaling, based on the output window.
|
||||
* After this is done, include the scaling factor so you get a value based on the input bitmap.
|
||||
* The input bitmaps slopspace is automatically excluded from the calculations this way! */
|
||||
* Then add the left starting position of the bitmap's view (zoom function) to get the final value needed.
|
||||
* Note: The input bitmaps slopspace is automatically excluded from the calculations this way! */
|
||||
/* Note also:
|
||||
* Even if the scaling factor is clamping we instruct the BES to use the correct source start pos.! */
|
||||
|
||||
temp32 = 0;
|
||||
hsrcstv = 0;
|
||||
/* check for destination horizontal clipping at left side */
|
||||
if (ow->h_start < 0)
|
||||
{
|
||||
@@ -269,33 +284,35 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
if ((ow->h_start + ow->width - 1) < 1)
|
||||
{
|
||||
/* increase 'first contributing pixel' with 'fixed value': (total dest. width - 2) */
|
||||
temp32 += (ow->width - 2);
|
||||
hsrcstv += (ow->width - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* increase 'first contributing pixel' with actual number of dest. clipping pixels */
|
||||
temp32 += (0 - ow->h_start);
|
||||
hsrcstv += (0 - ow->h_start);
|
||||
}
|
||||
LOG(4,("Overlay: clipping left...\n"));
|
||||
|
||||
/* The calculated value is based on scaling = 1x. So we now compensate for scaling.
|
||||
* Note that this also already takes care of aligning the value to the BES register! */
|
||||
temp32 *= ifactor;
|
||||
hsrcstv *= ifactor;
|
||||
}
|
||||
/* take zoom into account */
|
||||
hsrcstv += ((uint32)my_ov.h_start) << 16;
|
||||
/* AND below required by hardware */
|
||||
temp32 &= 0x03fffffc;
|
||||
BESW(HSRCST, temp32);
|
||||
LOG(4,("Overlay: first hor. (sub)pixel of input bitmap contributing %f\n", temp32 / (float)65536));
|
||||
hsrcstv &= 0x03fffffc;
|
||||
LOG(4,("Overlay: first hor. (sub)pixel of input bitmap contributing %f\n", hsrcstv / (float)65536));
|
||||
|
||||
|
||||
/* Setup horizontal source end: last (sub)pixel contributing to output picture */
|
||||
/* Note:
|
||||
* The method is to calculate, based on 1:1 scaling, based on the output window.
|
||||
* After this is done, include the scaling factor so you get a value based on the input bitmap. */
|
||||
* After this is done, include the scaling factor so you get a value based on the input bitmap.
|
||||
* Then add the right ending position of the bitmap's view (zoom function) to get the final value needed. */
|
||||
/* Note also:
|
||||
* Even if the scaling factor is clamping we instruct the BES to use the correct source end pos.! */
|
||||
|
||||
temp32 = 0;
|
||||
hsrcendv = 0;
|
||||
/* check for destination horizontal clipping at right side */
|
||||
if ((ow->h_start + ow->width - 1) > (si->dm.virtual_width - 1))
|
||||
{
|
||||
@@ -304,38 +321,36 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
if (ow->h_start > (si->dm.virtual_width - 2))
|
||||
{
|
||||
/* increase 'number of clipping pixels' with 'fixed value': (total dest. width - 2) */
|
||||
temp32 += (ow->width - 2);
|
||||
hsrcendv += (ow->width - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* increase 'number of clipping pixels' with actual number of dest. clipping pixels */
|
||||
temp32 += ((ow->h_start + ow->width - 1) - (si->dm.virtual_width - 1));
|
||||
hsrcendv += ((ow->h_start + ow->width - 1) - (si->dm.virtual_width - 1));
|
||||
}
|
||||
LOG(4,("Overlay: clipping right...\n"));
|
||||
|
||||
/* The calculated value is based on scaling = 1x. So we now compensate for scaling.
|
||||
* Note that this also already takes care of aligning the value to the BES register! */
|
||||
temp32 *= ifactor;
|
||||
|
||||
/* now subtract this value from the last used pixel in inputbuffer, aligned to BES */
|
||||
temp32 = (((ob->width - 1) - si->overlay.myBufInfo[offset].slopspace) << 16) - temp32;
|
||||
hsrcendv *= ifactor;
|
||||
/* now subtract this value from the last used pixel in (zoomed) inputbuffer, aligned to BES */
|
||||
hsrcendv = (((uint32)((my_ov.h_start + my_ov.width) - 1)) << 16) - hsrcendv;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set last contributing pixel to last used pixel in inputbuffer, aligned to BES */
|
||||
temp32 = ((ob->width - 1) - si->overlay.myBufInfo[offset].slopspace) << 16;
|
||||
/* set last contributing pixel to last used pixel in (zoomed) inputbuffer, aligned to BES */
|
||||
hsrcendv = (((uint32)((my_ov.h_start + my_ov.width) - 1)) << 16);
|
||||
}
|
||||
/* AND below required by hardware */
|
||||
temp32 &= 0x03fffffc;
|
||||
BESW(HSRCEND, temp32);
|
||||
LOG(4,("Overlay: last horizontal (sub)pixel of input bitmap contributing %f\n", temp32 / (float)65536));
|
||||
hsrcendv &= 0x03fffffc;
|
||||
LOG(4,("Overlay: last horizontal (sub)pixel of input bitmap contributing %f\n", hsrcendv / (float)65536));
|
||||
|
||||
|
||||
/* setup horizontal source last position excluding slopspace */
|
||||
temp32 = ((ob->width - 1) - si->overlay.myBufInfo[offset].slopspace) << 16;
|
||||
/* setup horizontal source last position excluding slopspace:
|
||||
* this is the last pixel that will be used for calculating interpolated pixels */
|
||||
hsrclstv = ((ob->width - 1) - si->overlay.myBufInfo[offset].slopspace) << 16;
|
||||
/* AND below required by hardware */
|
||||
temp32 &= 0x03ff0000;
|
||||
BESW(HSRCLST, temp32);
|
||||
hsrclstv &= 0x03ff0000;
|
||||
|
||||
|
||||
/*******************************************
|
||||
@@ -343,11 +358,11 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
*******************************************/
|
||||
|
||||
/* do vertical scaling... */
|
||||
/* determine interval representation value */
|
||||
/* determine interval representation value, taking zoom into account */
|
||||
if (ow->flags & B_OVERLAY_VERTICAL_FILTERING)
|
||||
{
|
||||
/* vertical filtering is ON */
|
||||
if ((ob->height == ow->height) | (ow->height < 2))
|
||||
if ((my_ov.height == ow->height) | (ow->height < 2))
|
||||
{
|
||||
/* no vertical scaling used, OR destination height < 2 */
|
||||
intrep = 0;
|
||||
@@ -360,7 +375,7 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
else
|
||||
{
|
||||
/* vertical filtering is OFF */
|
||||
if ((ow->height < ob->height) & (ow->height >= 2))
|
||||
if ((ow->height < my_ov.height) & (ow->height >= 2))
|
||||
{
|
||||
/* vertical downscaling used AND destination height >= 2 */
|
||||
intrep = 1;
|
||||
@@ -372,50 +387,53 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
}
|
||||
LOG(4,("Overlay: vertical interval representation value is %d\n",intrep));
|
||||
|
||||
/* calculate inverse vertical scaling factor */
|
||||
/* (using standard scaling formula: neglecting round-off var as extra error is very small..) */
|
||||
ifactor = ((ob->height - intrep) << 16) / (ow->height - intrep);
|
||||
/* calculate inverse vertical scaling factor, taking zoom into account */
|
||||
/* standard scaling formula: */
|
||||
ifactor = (((uint32)(my_ov.height - intrep)) << 16) / (ow->height - intrep);
|
||||
|
||||
/* correct factor to prevent lowest visible line from distorting */
|
||||
ifactor -= (1 << 2);
|
||||
LOG(4,("Overlay: vertical scaling factor is %f\n", (float)65536 / ifactor));
|
||||
|
||||
/* preserve ifactor for source positioning calculations later on */
|
||||
temp32 = ifactor;
|
||||
viscalv = ifactor;
|
||||
|
||||
/* check scaling factor (and modify if needed) to be within scaling limits */
|
||||
if (((ob->height << 16) / 16384) > temp32)
|
||||
if (((((uint32)my_ov.height) << 16) / 16384) > viscalv)
|
||||
{
|
||||
/* (non-inverse) factor too large, set factor to max. valid value */
|
||||
temp32 = ((ob->height << 16) / 16384);
|
||||
LOG(4,("Overlay: vertical scaling factor too large, clamping at %f\n", (float)65536 / temp32));
|
||||
viscalv = ((((uint32)my_ov.height) << 16) / 16384);
|
||||
LOG(4,("Overlay: vertical scaling factor too large, clamping at %f\n", (float)65536 / viscalv));
|
||||
}
|
||||
if (temp32 >= (32 << 16))
|
||||
if (viscalv >= (32 << 16))
|
||||
{
|
||||
/* (non-inverse) factor too small, set factor to min. valid value */
|
||||
temp32 = 0x1ffffc;
|
||||
LOG(4,("Overlay: vertical scaling factor too small, clamping at %f\n", (float)65536 / temp32));
|
||||
viscalv = 0x1ffffc;
|
||||
LOG(4,("Overlay: vertical scaling factor too small, clamping at %f\n", (float)65536 / viscalv));
|
||||
}
|
||||
/* AND below is required by hardware */
|
||||
temp32 &= 0x001ffffc;
|
||||
BESW(VISCAL, temp32);
|
||||
viscalv &= 0x001ffffc;
|
||||
|
||||
|
||||
/* do vertical clipping... */
|
||||
/* Setup vertical source start: first (sub)pixel contributing to output picture.
|
||||
* Note: this exists of two parts:
|
||||
* 1. setup fractional part (sign is always 'positive');
|
||||
* 2. setup relative base_adress, taking clipping on top into account.
|
||||
* 2. setup relative base_adress, taking clipping on top (and zoom) into account.
|
||||
* Both parts are done intertwined below. */
|
||||
/* Note:
|
||||
* The method is to calculate, based on 1:1 scaling, based on the output window.
|
||||
* 'After' this is done, include the scaling factor so you get a value based on the input bitmap. */
|
||||
* 'After' this is done, include the scaling factor so you get a value based on the input bitmap.
|
||||
* Then add the top starting position of the bitmap's view (zoom function) to get the final value needed. */
|
||||
/* Note also:
|
||||
* Even if the scaling factor is clamping we instruct the BES to use the correct source start pos.! */
|
||||
|
||||
/* calculate relative base_adress and 'vertical weight fractional part' */
|
||||
weight = 0;
|
||||
temp32 = (uint32)((vuint32 *)ob->buffer);
|
||||
temp32 -= (uint32)((vuint32 *)si->framebuffer);
|
||||
LOG(4,("Overlay: topleft corner of input bitmap (cardRAM offset) $%08x\n",temp32));
|
||||
a1orgv = (uint32)((vuint32 *)ob->buffer);
|
||||
a1orgv -= (uint32)((vuint32 *)si->framebuffer);
|
||||
/* calculate origin adress */
|
||||
LOG(4,("Overlay: topleft corner of input bitmap (cardRAM offset) $%08x\n",a1orgv));
|
||||
/* check for destination vertical clipping at top side */
|
||||
if (ow->v_start < 0)
|
||||
{
|
||||
@@ -426,7 +444,7 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
/* increase source buffer origin with 'fixed value':
|
||||
* (integer part of ('total height - 2' of dest. picture in pixels * inverse scaling factor)) *
|
||||
* bytes per row source picture */
|
||||
temp32 += ((((ow->height - 2) * ifactor) >> 16) * ob->bytes_per_row);
|
||||
a1orgv += ((((ow->height - 2) * ifactor) >> 16) * ob->bytes_per_row);
|
||||
weight = (ow->height - 2) * ifactor;
|
||||
}
|
||||
else
|
||||
@@ -434,52 +452,194 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
/* increase source buffer origin with:
|
||||
* (integer part of (number of destination picture clipping pixels * inverse scaling factor)) *
|
||||
* bytes per row source picture */
|
||||
temp32 += ((((0 - ow->v_start) * ifactor) >> 16) * ob->bytes_per_row);
|
||||
a1orgv += ((((0 - ow->v_start) * ifactor) >> 16) * ob->bytes_per_row);
|
||||
weight = (0 - ow->v_start) * ifactor;
|
||||
}
|
||||
LOG(4,("Overlay: clipping at top: buffer origin is (cardRAM offset) $%08x\n",temp32));
|
||||
LOG(4,("Overlay: clipping at top...\n"));
|
||||
}
|
||||
/* take zoom into account */
|
||||
a1orgv += (my_ov.v_start * ob->bytes_per_row);
|
||||
weight += (((uint32)my_ov.v_start) << 16);
|
||||
LOG(4,("Overlay: 'contributing part of buffer' origin is (cardRAM offset) $%08x\n",a1orgv));
|
||||
LOG(4,("Overlay: first vert. (sub)pixel of input bitmap contributing %f\n", weight / (float)65536));
|
||||
|
||||
/* Note:
|
||||
* Because later G200 and all > G200 overlay units will ignore b0-3 of the calculated adress,
|
||||
* Because all > G200 overlay units will ignore b0-3 of the calculated adress,
|
||||
* we do not use the above way for horizontal source positioning.
|
||||
* (Early G200 cards ignore b0-2.)
|
||||
* (G200 cards ignore b0-2.)
|
||||
* If we did, 8 source-image pixel jumps (in 4:2:2 colorspace) will occur if the picture
|
||||
* is shifted horizontally during left clipping on later G200 and all > G200 cards, while
|
||||
* early G200 cards will have 4 source-image pixel jumps occuring. */
|
||||
* is shifted horizontally during left clipping on all > G200 cards, while G200 cards
|
||||
* will have 4 source-image pixel jumps occuring. */
|
||||
|
||||
/* AND below is required by G200-G550 hardware. All cards can have max. 32Mb RAM on board
|
||||
* (incl. later G200 cards!). Compatible setting used (between early G200 and the rest),
|
||||
* this has no downside consequences here. */
|
||||
temp32 &= 0x01fffff0;
|
||||
/* buffer A topleft corner of field 1 (origin)(field 1 contains our full frames) */
|
||||
BESW(A1ORG, temp32);
|
||||
/* AND below is required by G200-G550 hardware. > G200 cards can have max. 32Mb RAM on board
|
||||
* (16Mb on G200 cards). Compatible setting used (between G200 and the rest), this has no
|
||||
* downside consequences here. */
|
||||
/* Buffer A topleft corner of field 1 (origin)(field 1 contains our full frames) */
|
||||
a1orgv &= 0x01fffff0;
|
||||
|
||||
/* field 1 weight: AND below required by hardware, also make sure 'sign' is always 'positive' */
|
||||
temp32 = weight & 0x0000fffc;
|
||||
BESW(V1WGHT, temp32);
|
||||
v1wghtv = weight & 0x0000fffc;
|
||||
|
||||
|
||||
/* setup field 1 (is our complete frame) vertical source contributing height - 1.
|
||||
* Note:
|
||||
* This value is bottom-unclipped! (as it should be according to the MGA specs...) */
|
||||
temp32 = (ob->height - 1) - (weight >> 16);
|
||||
/* setup field 1 (is our complete frame) vertical source last position.
|
||||
* this is the last pixel that will be used for calculating interpolated pixels */
|
||||
v1srclstv = (ob->height - 1);
|
||||
/* AND below required by hardware */
|
||||
temp32 &= 0x000003ff;
|
||||
BESW(V1SRCLST, temp32);
|
||||
LOG(4,("Overlay: input bitmap bottom-unclipped contributing height (integer part) %d\n", temp32 + 1));
|
||||
v1srclstv &= 0x000003ff;
|
||||
|
||||
|
||||
/*****************************
|
||||
*** log color keying info ***
|
||||
*****************************/
|
||||
|
||||
LOG(6,("Overlay: key_red %d, key_green %d, key_blue %d, key_alpha %d\n",
|
||||
ow->red.value, ow->green.value, ow->blue.value, ow->alpha.value));
|
||||
LOG(6,("Overlay: mask_red %d, mask_green %d, mask_blue %d, mask_alpha %d\n",
|
||||
ow->red.mask, ow->green.mask, ow->blue.mask, ow->alpha.mask));
|
||||
|
||||
|
||||
/*************************
|
||||
*** setup BES control ***
|
||||
*************************/
|
||||
|
||||
/* BES global control: setup functions */
|
||||
globctlv = 0;
|
||||
|
||||
/* slowdown BES if nessesary */
|
||||
if (acczoom == 1)
|
||||
{
|
||||
/* run at full speed and resolution */
|
||||
globctlv |= 0 << 0;
|
||||
/* disable filtering for half speed interpolation */
|
||||
globctlv |= 0 << 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* run at half speed and resolution */
|
||||
globctlv |= 1 << 0;
|
||||
/* enable filtering for half speed interpolation */
|
||||
globctlv |= 1 << 1;
|
||||
}
|
||||
|
||||
/* 4:2:0 specific setup: not needed here */
|
||||
globctlv |= 0 << 3;
|
||||
/* BES testregister: keep zero */
|
||||
globctlv |= 0 << 4;
|
||||
/* the following bits marked (> G200) *must* be zero on G200: */
|
||||
/* 4:2:0 specific setup: not needed here (> G200) */
|
||||
globctlv |= 0 << 5;
|
||||
/* select yuy2 byte-order to B_YCbCr422 (> G200) */
|
||||
globctlv |= 0 << 6;
|
||||
/* BES internal contrast and brighness controls are not used, disabled (> G200) */
|
||||
globctlv |= 0 << 7;
|
||||
/* RGB specific setup: not needed here, so disabled (> G200) */
|
||||
globctlv |= 0 << 8;
|
||||
globctlv |= 0 << 9;
|
||||
/* 4:2:0 specific setup: not needed here (> G200) */
|
||||
globctlv |= 0 << 10;
|
||||
/* Tell BES when to copy the new register values to the actual active registers.
|
||||
* bits 16-27 (12 bits) are the CRTC vert. count value at which copying takes
|
||||
* place.
|
||||
* (This is the double buffering feature: programming must be completed *before*
|
||||
* the CRTC vert count value set here!) */
|
||||
/* CRTC vert count for copying = $000, so during retrace, line 0. */
|
||||
globctlv |= 0x000 << 16;
|
||||
|
||||
/* BES control: enable scaler and setup functions */
|
||||
/* pre-reset all bits */
|
||||
ctlv = 0;
|
||||
/* enable BES */
|
||||
ctlv |= 1 << 0;
|
||||
/* we start displaying at an even startline (zero) in 'field 1' (no hardware de-interlacing is used) */
|
||||
ctlv |= 0 << 6;
|
||||
/* we don't use field 2, so its startline is not important */
|
||||
ctlv |= 0 << 7;
|
||||
|
||||
LOG(6,("Overlay: ow->flags is $%08x\n",ow->flags));
|
||||
/* enable horizontal filtering on scaling if asked for: if we *are* actually scaling */
|
||||
if ((ow->flags & B_OVERLAY_HORIZONTAL_FILTERING) && (hiscalv != (0x01 << 16)))
|
||||
{
|
||||
ctlv |= 1 << 10;
|
||||
LOG(6,("Overlay: using horizontal interpolation on scaling\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ctlv |= 0 << 10;
|
||||
LOG(6,("Overlay: using horizontal dropping or replication on scaling\n"));
|
||||
}
|
||||
/* enable vertical filtering on scaling if asked for: if we are *upscaling* only */
|
||||
if ((ow->flags & B_OVERLAY_VERTICAL_FILTERING) && (viscalv < (0x01 << 16)))
|
||||
{
|
||||
ctlv |= 1 << 11;
|
||||
LOG(6,("Overlay: using vertical interpolation on scaling\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ctlv |= 0 << 11;
|
||||
LOG(6,("Overlay: using vertical dropping or replication on scaling\n"));
|
||||
}
|
||||
|
||||
/* use actual calculated weight for horizontal interpolation */
|
||||
ctlv |= 0 << 12;
|
||||
/* use horizontal chroma interpolation upsampling on BES input picture */
|
||||
ctlv |= 1 << 16;
|
||||
/* select 4:2:2 BES input format */
|
||||
ctlv |= 0 << 17;
|
||||
/* dithering is enabled */
|
||||
ctlv |= 1 << 18;
|
||||
/* horizontal mirroring is not used */
|
||||
ctlv |= 0 << 19;
|
||||
/* BES output should be in color */
|
||||
ctlv |= 0 << 20;
|
||||
/* BES output blanking is disabled: we want a picture, no 'black box'! */
|
||||
ctlv |= 0 << 21;
|
||||
/* we do software field select (field select is not used) */
|
||||
ctlv |= 0 << 24;
|
||||
/* we always display field 1 in buffer A, this contains our full frames */
|
||||
/* select field 1 */
|
||||
ctlv |= 0 << 25;
|
||||
/* select buffer A */
|
||||
ctlv |= 0 << 26;
|
||||
|
||||
|
||||
/*************************************
|
||||
*** sync to BES (Back End Scaler) ***
|
||||
*************************************/
|
||||
|
||||
/* Make sure reprogramming the BES completes before the next retrace occurs,
|
||||
* to prevent register-update glitches (double buffer feature). */
|
||||
|
||||
LOG(3,("Overlay: starting register programming beyond Vcount %d\n", CR1R(VCOUNT)));
|
||||
/* Even at 1600x1200x90Hz, a single line still takes about 9uS to complete:
|
||||
* this resolution will generate about 180Mhz pixelclock while we can do
|
||||
* upto 360Mhz. So snooze about 4uS to prevent bus-congestion...
|
||||
* Appr. 200 lines time will provide enough room even on a 100Mhz CPU if it's
|
||||
* screen is set to the highest refreshrate/resolution possible. */
|
||||
while (CR1R(VCOUNT) > (si->dm.timing.v_total - 200)) snooze(4);
|
||||
|
||||
|
||||
/**************************************
|
||||
*** actually program the registers ***
|
||||
**************************************/
|
||||
|
||||
BESW(HCOORD, hcoordv);
|
||||
BESW(VCOORD, vcoordv);
|
||||
BESW(HISCAL, hiscalv);
|
||||
BESW(HSRCST, hsrcstv);
|
||||
BESW(HSRCEND, hsrcendv);
|
||||
BESW(HSRCLST, hsrclstv);
|
||||
BESW(VISCAL, viscalv);
|
||||
BESW(A1ORG, a1orgv);
|
||||
BESW(V1WGHT, v1wghtv);
|
||||
BESW(V1SRCLST, v1srclstv);
|
||||
BESW(GLOBCTL, globctlv);
|
||||
BESW(CTL, ctlv);
|
||||
|
||||
|
||||
/**************************
|
||||
*** setup color keying ***
|
||||
**************************/
|
||||
|
||||
LOG(4,("Overlay: key_red %d, key_green %d, key_blue %d, key_alpha %d\n",
|
||||
ow->red.value, ow->green.value, ow->blue.value, ow->alpha.value));
|
||||
LOG(4,("Overlay: mask_red %d, mask_green %d, mask_blue %d, mask_alpha %d\n",
|
||||
ow->red.mask, ow->green.mask, ow->blue.mask, ow->alpha.mask));
|
||||
|
||||
/* setup colorkeying */
|
||||
DXIW(COLKEY, (ow->alpha.value & ow->alpha.mask));
|
||||
|
||||
@@ -504,116 +664,11 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
|
||||
/* setup brightness and contrast to be 'neutral' (this is not implemented on G200) */
|
||||
BESW(LUMACTL, 0x00000080);
|
||||
|
||||
/* setup source pitch including slopspace (in pixels) */
|
||||
temp32 = ob->width;
|
||||
/* AND below required by hardware */
|
||||
temp32 &= 0x00000fff;
|
||||
BESW(PITCH, temp32);
|
||||
|
||||
|
||||
/*************************
|
||||
*** setup BES control ***
|
||||
*************************/
|
||||
|
||||
/* BES global control: setup functions */
|
||||
temp32 = 0;
|
||||
|
||||
/* slowdown BES if nessesary */
|
||||
if (acczoom == 1)
|
||||
{
|
||||
/* run at full speed and resolution */
|
||||
temp32 |= 0 << 0;
|
||||
/* disable filtering for half speed interpolation */
|
||||
temp32 |= 0 << 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* run at half speed and resolution */
|
||||
temp32 |= 1 << 0;
|
||||
/* enable filtering for half speed interpolation */
|
||||
temp32 |= 1 << 1;
|
||||
}
|
||||
|
||||
/* 4:2:0 specific setup: not needed here */
|
||||
temp32 |= 0 << 3;
|
||||
/* BES testregister: keep zero */
|
||||
temp32 |= 0 << 4;
|
||||
/* the following bits marked (> G200) *must* be zero on G200: */
|
||||
/* 4:2:0 specific setup: not needed here (> G200) */
|
||||
temp32 |= 0 << 5;
|
||||
/* select yuy2 byte-order to B_YCbCr422 (> G200) */
|
||||
temp32 |= 0 << 6;
|
||||
/* BES internal contrast and brighness controls are not used, disabled (> G200) */
|
||||
temp32 |= 0 << 7;
|
||||
/* RGB specific setup: not needed here, so disabled (> G200) */
|
||||
temp32 |= 0 << 8;
|
||||
temp32 |= 0 << 9;
|
||||
/* 4:2:0 specific setup: not needed here (> G200) */
|
||||
temp32 |= 0 << 10;
|
||||
/* Tell BES when to copy the new register values to the actual active registers.
|
||||
* bits 16-27 (12 bits) are the CRTC vert. count value at which copying takes
|
||||
* place.
|
||||
* (This is the double buffering feature: programming must be completed *before*
|
||||
* the CRTC vert count value set here!) */
|
||||
/* CRTC vert count for copying = $000, so during retrace, line 0. */
|
||||
temp32 |= 0x000 << 16;
|
||||
BESW(GLOBCTL, temp32);
|
||||
|
||||
/* BES control: enable scaler and setup functions */
|
||||
/* pre-reset all bits */
|
||||
temp32 = 0;
|
||||
/* enable BES */
|
||||
temp32 |= 1 << 0;
|
||||
/* we start displaying at an even startline (zero) in 'field 1' (no hardware de-interlacing is used) */
|
||||
temp32 |= 0 << 6;
|
||||
/* we don't use field 2, so its startline is not important */
|
||||
temp32 |= 0 << 7;
|
||||
|
||||
LOG(4,("Overlay: ow->flags is $%08x\n",ow->flags));
|
||||
/* enable horizontal filtering on scaling if asked for */
|
||||
if (ow->flags & B_OVERLAY_HORIZONTAL_FILTERING)
|
||||
{
|
||||
temp32 |= 1 << 10;
|
||||
LOG(4,("Overlay: using horizontal filtering\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
temp32 |= 0 << 10;
|
||||
}
|
||||
/* enable vertical filtering on scaling if asked for */
|
||||
if (ow->flags & B_OVERLAY_VERTICAL_FILTERING)
|
||||
{
|
||||
temp32 |= 1 << 11;
|
||||
LOG(4,("Overlay: using vertical filtering\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
temp32 |= 0 << 11;
|
||||
}
|
||||
|
||||
/* use actual calculated weight for horizontal interpolation if scaling */
|
||||
temp32 |= 0 << 12;
|
||||
/* use horizontal chroma interpolation upsampling on BES input picture */
|
||||
temp32 |= 1 << 16;
|
||||
/* select 4:2:2 BES input format */
|
||||
temp32 |= 0 << 17;
|
||||
/* dithering is not used */
|
||||
temp32 |= 0 << 18;
|
||||
/* horizontal mirroring is not used */
|
||||
temp32 |= 0 << 19;
|
||||
/* BES output should be in color */
|
||||
temp32 |= 0 << 20;
|
||||
/* BES output blanking is disabled: we want a picture, no 'black box'! */
|
||||
temp32 |= 0 << 21;
|
||||
/* we do software field select (field select is not used) */
|
||||
temp32 |= 0 << 24;
|
||||
/* we always display field 1 in buffer A, this contains our full frames */
|
||||
/* select field 1 */
|
||||
temp32 |= 0 << 25;
|
||||
/* select buffer A */
|
||||
temp32 |= 0 << 26;
|
||||
BESW(CTL, temp32);
|
||||
/* setup source pitch including slopspace (in pixels); AND is required by hardware */
|
||||
BESW(PITCH, (ob->width & 0x00000fff));
|
||||
|
||||
/* on a 500Mhz P3 CPU just logging a line costs 400uS (18-19 vcounts at 1024x768x60Hz)!
|
||||
* programming the registers above actually costs 180uS here */
|
||||
LOG(3,("Overlay: completed at Vcount %d\n", CR1R(VCOUNT)));
|
||||
|
||||
return B_OK;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/* Authors:
|
||||
Mark Watson 2/2000,
|
||||
Apsed,
|
||||
Rudolf Cornelissen 10/2002
|
||||
Rudolf Cornelissen 11-12/2002
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00040000
|
||||
@@ -109,14 +109,14 @@ status_t gx00_crtc_set_timing(
|
||||
|
||||
LOG(4,("CRTC: setting timing\n"));
|
||||
|
||||
/*Modify parameters as required by the G400/G200*/
|
||||
htotal=(ht>>3)-5;
|
||||
hdisp_e=(hd_e>>3)-1;
|
||||
hsync_s=(hs_s>>3);
|
||||
hsync_e=(hs_e>>3);
|
||||
hblnk_s=hdisp_e;
|
||||
hblnk_e=htotal+4;
|
||||
|
||||
/* Modify parameters as required by the G400/G200 */
|
||||
htotal = ((ht >> 3) - 5);
|
||||
hdisp_e = ((hd_e >> 3) -1); //so: timing - 8
|
||||
hblnk_s = hdisp_e; //so: timing - 8
|
||||
hblnk_e = (htotal + 4); //so: timing - 8
|
||||
hsync_s = (hs_s >> 3);
|
||||
hsync_e = (hs_e >> 3);
|
||||
|
||||
vtotal=vt-2;
|
||||
vdisp_e=vd_e-1;
|
||||
vsync_s=vs_s-1;
|
||||
@@ -149,6 +149,7 @@ status_t gx00_crtc_set_timing(
|
||||
((vsync_s&0x100)>>(8-2))|((vsync_s&0x200)>>(9-7))|
|
||||
((vblnk_s&0x100)>>(8-3))|((linecomp&0x100)>>(8-4))
|
||||
));
|
||||
VGAW_I(CRTC,0x8,0x00);
|
||||
VGAW_I(CRTC,0x9,((vblnk_s&0x200)>>(9-5))|((linecomp&0x200)>>(9-6)));
|
||||
VGAW_I(CRTC,0x10,vsync_s&0xFF);
|
||||
VGAW_I(CRTC,0x11,((VGAR_I(CRTC,0x11))&0xF0)|(vsync_e&0xF));
|
||||
@@ -157,7 +158,8 @@ status_t gx00_crtc_set_timing(
|
||||
VGAW_I(CRTC,0x16,vblnk_e&0xFF);
|
||||
VGAW_I(CRTC,0x18,linecomp&0xFF);
|
||||
|
||||
/*horizontal - extended regs*/
|
||||
/* horizontal - extended regs */
|
||||
/* do not touch external sync reset inputs: used for TVout */
|
||||
VGAW_I(CRTCEXT,1,
|
||||
(
|
||||
((htotal&0x100)>>8)|
|
||||
@@ -219,7 +221,8 @@ status_t gx00_crtc_dpms(uint8 display,uint8 h,uint8 v) // MIL2
|
||||
VGAW_I(SEQ,1,(!display)<<5);
|
||||
VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0xCF)|((!v)<<5))|((!h)<<4);
|
||||
|
||||
VGAW_I(CRTC,0x17,0xC3);/*do not force disable all syncs and other stuff*/
|
||||
/* set some required fixed values for proper MGA mode initialisation */
|
||||
VGAW_I(CRTC,0x17,0xC3);
|
||||
VGAW_I(CRTC,0x14,0x00);
|
||||
|
||||
return B_OK;
|
||||
@@ -258,18 +261,8 @@ status_t gx00_crtc_set_display_start(uint32 startadd,uint8 bpp)
|
||||
|
||||
LOG(4,("CRTC: setting card RAM to be displayed bpp %d\n", bpp));
|
||||
|
||||
/*figure out startadd value hardware needs*/
|
||||
/*switch(bpp)
|
||||
{
|
||||
case 8:case 24:
|
||||
startadd>>=1;
|
||||
case 16:
|
||||
startadd>>=1;
|
||||
case 32:
|
||||
startadd>>=1;
|
||||
break;
|
||||
}*/
|
||||
startadd>>=3; // apsed, TODO doc Matrox g200 g400 4.6.5 is false?
|
||||
/* Matrox docs are false/incomplete, always program qword adress. */
|
||||
startadd >>= 3;
|
||||
|
||||
LOG(2,("CRTC: startadd: %x\n",startadd));
|
||||
LOG(2,("CRTC: frameRAM: %x\n",si->framebuffer));
|
||||
@@ -297,28 +290,99 @@ status_t gx00_crtc_set_display_start(uint32 startadd,uint8 bpp)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t gx00_crtc_mem_priority(uint8 HIPRILVL)
|
||||
status_t gx00_crtc_mem_priority(uint8 colordepth)
|
||||
{
|
||||
if (si->ps.card_type<G100) return B_ERROR; // apsed TODO, not used, see after SetDisplayMode.c/interrupt_enable()
|
||||
float tpixclk, tmclk, refresh, temp;
|
||||
uint8 mp, vc, hiprilvl, maxhipri, prioctl;
|
||||
|
||||
LOG(4,("CRTC: Setting memory priority level: %x\n",HIPRILVL));
|
||||
|
||||
switch (HIPRILVL)
|
||||
/* we can only do this if card pins is read OK *and* card is coldstarted! */
|
||||
if (si->settings.usebios || (si->ps.pins_status != B_OK))
|
||||
{
|
||||
LOG(4,("CRTC: Card not coldstarted, skipping memory priority level setup\n"));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* only on G200 the mem_priority register should be programmed with this formula */
|
||||
if (si->ps.card_type != G200)
|
||||
{
|
||||
LOG(4,("CRTC: Memory priority level setup not needed, skipping\n"));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* make sure the G200 is running at peak performance, so for instance high-res
|
||||
* overlay distortions due to bandwidth limitations are minimal.
|
||||
* Note please that later cards have plenty of bandwidth to cope by default.
|
||||
* Note also that the formula needed is entirely cardtype-dependant! */
|
||||
LOG(4,("CRTC: Setting G200 memory priority level\n"));
|
||||
|
||||
/* set memory controller pipe depth, assuming no codec or Vin operating */
|
||||
switch ((si->ps.memrdbk_reg & 0x00c00000) >> 22)
|
||||
{
|
||||
case 0:
|
||||
VGAW_I(CRTCEXT,6,0x00);
|
||||
mp = 52;
|
||||
break;
|
||||
case 1:case 2:case 3:
|
||||
VGAW_I(CRTCEXT,6,0x10|HIPRILVL);
|
||||
case 1:
|
||||
mp = 41;
|
||||
break;
|
||||
case 4:case 5:case 6:case 7:
|
||||
VGAW_I(CRTCEXT,6,0x20|HIPRILVL);
|
||||
case 2:
|
||||
mp = 32;
|
||||
break;
|
||||
default:
|
||||
LOG(8,("CRTC: Memory priority level violation: %x\n",HIPRILVL));
|
||||
return B_ERROR;
|
||||
mp = 52;
|
||||
LOG(8,("CRTC: Streamer flowcontrol violation in PINS, defaulting to %%00\n"));
|
||||
break;
|
||||
}
|
||||
|
||||
/* calculate number of videoclocks needed per 8 pixels */
|
||||
vc = (8 * colordepth) / 64;
|
||||
|
||||
/* calculate pixelclock period (nS) */
|
||||
tpixclk = 1000000 / si->dm.timing.pixel_clock;
|
||||
|
||||
/* calculate memoryclock period (nS) */
|
||||
if (si->ps.v3_option2_reg & 0x08)
|
||||
{
|
||||
tmclk = 1000.0 / si->ps.std_engine_clock;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (si->ps.v3_clk_div & 0x02)
|
||||
tmclk = 3000.0 / si->ps.std_engine_clock;
|
||||
else
|
||||
tmclk = 2000.0 / si->ps.std_engine_clock;
|
||||
}
|
||||
|
||||
/* calculate refreshrate of current displaymode */
|
||||
refresh = ((si->dm.timing.pixel_clock * 1000) /
|
||||
((uint32)si->dm.timing.h_total * (uint32)si->dm.timing.v_total));
|
||||
|
||||
/* calculate high priority request level, but stay on the 'crtc-safe' side:
|
||||
* hence 'formula + 1.0' instead of 'formula + 0.5' */
|
||||
temp = (((((mp * tmclk) + (11 * vc * tpixclk)) / tpixclk) - (vc - 1)) / (8 * vc)) + 1.0;
|
||||
if (temp > 7.0) temp = 7.0;
|
||||
if (temp < 0.0) temp = 0.0;
|
||||
hiprilvl = 7 - ((uint8) temp);
|
||||
/* limit non-crtc priority so crtc always stays 'just' OK */
|
||||
if (hiprilvl > 4) hiprilvl = 4;
|
||||
if ((si->dm.timing.v_display > 768) && (hiprilvl > 3)) hiprilvl = 3;
|
||||
if ((si->dm.timing.v_display > 864) && (hiprilvl > 2) && (refresh >= 76.0)) hiprilvl = 2;
|
||||
if ((si->dm.timing.v_display > 1024) && (hiprilvl > 2)) hiprilvl = 2;
|
||||
|
||||
/* calculate maximum high priority requests */
|
||||
temp = (vc * (tmclk / tpixclk)) + 0.5;
|
||||
if (temp > (float)hiprilvl) temp = (float)hiprilvl;
|
||||
if (temp < 0.0) temp = 0.0;
|
||||
maxhipri = ((uint8) temp);
|
||||
|
||||
/* program the card */
|
||||
prioctl = ((hiprilvl & 0x07) | ((maxhipri & 0x07) << 4));
|
||||
VGAW_I(CRTCEXT, 6, prioctl);
|
||||
|
||||
/* log results */
|
||||
LOG(4,("CRTC: Vclks/char is %d, pixClk period %02.2fnS, memClk period %02.2fnS\n",
|
||||
vc, tpixclk, tmclk));
|
||||
LOG(4,("CRTC: memory priority control register is set to $%02x\n", prioctl));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -326,11 +390,17 @@ status_t gx00_crtc_cursor_init()
|
||||
{
|
||||
int i;
|
||||
uint32 * fb;
|
||||
const uint32 curadd = 0; // apsed, TODO with ramaddr -> taken care off.
|
||||
/* cursor bitmap will be stored at the start of the framebuffer */
|
||||
const uint32 curadd = 0;
|
||||
|
||||
/*store cursor at the start of the framebuffer*/
|
||||
DXIW(CURADDL,curadd >> 10); /*data at curadd in framebuffer*/
|
||||
/* set cursor bitmap adress ... */
|
||||
DXIW(CURADDL,curadd >> 10);
|
||||
DXIW(CURADDH,curadd >> 18);
|
||||
/* ... and repeat that: G100 requires other programming order than other cards!?! */
|
||||
DXIW(CURADDL,curadd >> 10);
|
||||
DXIW(CURADDH,curadd >> 18);
|
||||
|
||||
/* activate hardware cursor */
|
||||
DXIW(CURCTRL,1);
|
||||
|
||||
/*set cursor colour*/
|
||||
@@ -395,6 +465,13 @@ status_t gx00_crtc_cursor_position(uint16 x ,uint16 y)
|
||||
x+=i;
|
||||
y+=i;
|
||||
|
||||
/* make sure we are not in retrace, because the register(s) might get copied
|
||||
* during our reprogramming them (double buffering feature) */
|
||||
while (ACCR(STATUS) & 0x08)
|
||||
{
|
||||
snooze(4);
|
||||
}
|
||||
|
||||
DACW(CURSPOSXL,x&0xFF);
|
||||
DACW(CURSPOSXH,x>>8);
|
||||
DACW(CURSPOSYL,y&0xFF);
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
/* second CTRC functionality */
|
||||
/* Mark Watson 6/2000 */
|
||||
/* second CTRC functionality
|
||||
|
||||
Authors:
|
||||
Mark Watson 6/2000,
|
||||
Rudolf Cornelissen 12/2002
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00020000
|
||||
|
||||
@@ -22,12 +26,14 @@ status_t g400_crtc2_set_timing(
|
||||
}
|
||||
|
||||
/*program the second CRTC*/
|
||||
CR2W(HPARAM,(((hdisp_e-8)<<16) | (htotal-8)));
|
||||
CR2W(HSYNC,(((hsync_e-8)<<16) | (hsync_s-8)));
|
||||
CR2W(VPARAM,(((vdisp_e-1)<<16) | (vtotal-1)));
|
||||
CR2W(VSYNC,(((vsync_e-1)<<16) | (vsync_s-1)));
|
||||
CR2W(PRELOAD,(((vsync_s)<<16) | (hsync_s)));
|
||||
CR2W(MISC,((0xfff<<16) | ((!hsync_pos)<<8) | ((!vsync_pos)<<9)));
|
||||
CR2W(HPARAM, ((((hdisp_e - 8) & 0x0fff) << 16) | ((htotal - 8) & 0x0fff)));
|
||||
CR2W(HSYNC, ((((hsync_e - 8) & 0x0fff) << 16) | ((hsync_s - 8) & 0x0fff)));
|
||||
CR2W(VPARAM, ((((vdisp_e - 1) & 0x0fff) << 16) | ((vtotal - 1) & 0x0fff)));
|
||||
CR2W(VSYNC, ((((vsync_e - 1) & 0x0fff) << 16) | ((vsync_s - 1) & 0x0fff)));
|
||||
//Mark: (wrong AFAIK, warning: SETMODE MAVEN-CRTC delay is now tuned to new setup!!)
|
||||
//CR2W(PRELOAD, (((vsync_s & 0x0fff) << 16) | (hsync_s & 0x0fff)));
|
||||
CR2W(PRELOAD, ((((vsync_s - 1) & 0x0fff) << 16) | ((hsync_s - 8) & 0x0fff)));
|
||||
CR2W(MISC, ((0xfff << 16) | (((!hsync_pos) & 0x01) << 8) | (((!vsync_pos) & 0x01) << 9)));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -51,6 +57,7 @@ status_t g400_crtc2_depth(int mode)
|
||||
|
||||
status_t g400_crtc2_dpms(uint8 display,uint8 h,uint8 v)
|
||||
{
|
||||
//fixme: CTL b0=1 is CRTC2 enabled, 0 is disabled. This code is dangerous...
|
||||
CR2W(CTL,(CR2R(CTL)&0xFFF0077E)|(display&h&v)); /*enable second CRTC if required*/
|
||||
|
||||
/*ignore h,v because they are not supported*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/* Authors:
|
||||
Mark Watson 2/2000,
|
||||
Apsed 2002,
|
||||
Rudolf Cornelissen 9/2002
|
||||
Rudolf Cornelissen 9-12/2002
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00010000
|
||||
@@ -27,7 +27,7 @@ status_t gx00_dac_mode(int mode,float brightness)
|
||||
g=r+256;
|
||||
b=g+256;
|
||||
|
||||
LOG(4,("DAC:Setting screen mode %d brightness %f\n", mode, brightness));
|
||||
LOG(4,("DAC: Setting screen mode %d brightness %f\n", mode, brightness));
|
||||
/*init a basic palette for brightness specified*/
|
||||
for (i=0;i<256;i++)
|
||||
{
|
||||
@@ -73,7 +73,7 @@ status_t gx00_dac_mode(int mode,float brightness)
|
||||
case BPP32DIR:
|
||||
break;
|
||||
default:
|
||||
LOG(8,("DAC:Invalid bit depth requested\n"));
|
||||
LOG(8,("DAC: Invalid bit depth requested\n"));
|
||||
return B_ERROR;
|
||||
break;
|
||||
}
|
||||
@@ -96,8 +96,10 @@ status_t gx00_dac_palette(uint8 r[256],uint8 g[256],uint8 b[256])
|
||||
|
||||
LOG(4,("DAC: setting palette\n"));
|
||||
|
||||
/*clear palwtadd to start programming*/
|
||||
/* clear palwtadd to start programming (LUT index?) */
|
||||
DACW(PALWTADD,0);
|
||||
/* just for safety (specs are somewhat unclear) (LUT color?) */
|
||||
DACW(PALRDADD,0);
|
||||
|
||||
/*loop through all 256 to program DAC*/
|
||||
for (i=0;i<256;i++)
|
||||
@@ -111,17 +113,26 @@ status_t gx00_dac_palette(uint8 r[256],uint8 g[256],uint8 b[256])
|
||||
LOG(8,("DAC: PALWTADD is not 0 after programming\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
if (0) {// apsed: reread LUT
|
||||
if (0)
|
||||
{// apsed: reread LUT
|
||||
uint8 R, G, B;
|
||||
|
||||
/* clear LUT color (modulo 3 counter) */
|
||||
DACW(PALRDADD,0);
|
||||
for (i=0;i<256;i++) {
|
||||
for (i=0;i<256;i++)
|
||||
{
|
||||
R = DACR(PALDATA);
|
||||
G = DACR(PALDATA);
|
||||
B = DACR(PALDATA);
|
||||
if ((r[i] != R) || (g[i] != G) || (b[i] != B))
|
||||
LOG(1,("DAC palette %d: w %x %x %x, r %x %x %x\n", i, r[i], g[i], b[i], R, G, B)); // apsed
|
||||
}
|
||||
}
|
||||
}
|
||||
/* reset to LUT start just for safety (LUT index?) */
|
||||
DACW(PALWTADD,0);
|
||||
/* (specs are somewhat unclear) (LUT color?) */
|
||||
DACW(PALRDADD,0);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -650,7 +661,191 @@ static status_t g100_g400max_dac_sys_pll_find(
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*set up system pll - NB mclk is memory clock, */
|
||||
status_t gx50_dac_check_sys_pll(uint8 m, uint8 n, uint8 p)
|
||||
{
|
||||
uint time = 0, count = 0;
|
||||
|
||||
/* program the new clock */
|
||||
// DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0C)|0x01); /*select the PIXPLL*/
|
||||
DXIW(SYSPLLM, m);
|
||||
DXIW(SYSPLLN, n);
|
||||
DXIW(SYSPLLP, p);
|
||||
|
||||
/* Wait for the SYSPLL frequency to lock until timeout occurs */
|
||||
time = 0;
|
||||
while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 1000))
|
||||
{
|
||||
time++;
|
||||
snooze(1);
|
||||
}
|
||||
|
||||
/* no lock aquired, not useable */
|
||||
if (time > 1000) return B_ERROR;
|
||||
|
||||
/* check if lock holds for at least 90% of the time */
|
||||
for (time = 0, count = 0; time <= 1000; time++)
|
||||
{
|
||||
if(DXIR(SYSPLLSTAT)&0x40) count++;
|
||||
snooze(1);
|
||||
}
|
||||
/* we have a winner */
|
||||
if (count >= 900) return B_OK;
|
||||
|
||||
/* nogo, the PLL does not stabilize */
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t gx50_dac_check_sys_pll_range(uint8 m, uint8 n, uint8 *p, uint8 *q)
|
||||
{
|
||||
uint8 s=0, p_backup = *p;
|
||||
|
||||
/* preset no candidate, non working setting */
|
||||
*q = 0;
|
||||
/* preset lowest range filter */
|
||||
*p &= 0x47;
|
||||
|
||||
/* iterate through all possible filtersettings */
|
||||
// DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0F)|0x04); /*disable the PIXPLL*/
|
||||
for (s = 0; s < 8 ;s++)
|
||||
{
|
||||
if (gx50_dac_check_sys_pll(m, n, *p)== B_OK)
|
||||
{
|
||||
/* now check 3 closest lower and higher settings */
|
||||
if ((gx50_dac_check_sys_pll(m, n - 3, *p)== B_OK) &&
|
||||
(gx50_dac_check_sys_pll(m, n - 2, *p)== B_OK) &&
|
||||
(gx50_dac_check_sys_pll(m, n - 1, *p)== B_OK) &&
|
||||
(gx50_dac_check_sys_pll(m, n + 1, *p)== B_OK) &&
|
||||
(gx50_dac_check_sys_pll(m, n + 2, *p)== B_OK) &&
|
||||
(gx50_dac_check_sys_pll(m, n + 3, *p)== B_OK))
|
||||
{
|
||||
LOG(2,("DAC: found optimal working VCO filter: #%d\n",s));
|
||||
/* preset first choice setting found */
|
||||
*q = 1;
|
||||
/* we are done */
|
||||
// DXIW(PIXCLKCTRL,DXIR(PIXCLKCTRL)&0x0B); /*enable the PIXPLL*/
|
||||
return B_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(2,("DAC: found critical but working VCO filter: #%d\n",s));
|
||||
/* preset backup setting found */
|
||||
*q = 2;
|
||||
/* remember this setting */
|
||||
p_backup = *p;
|
||||
/* let's continue to see if a better filter exists */
|
||||
}
|
||||
}
|
||||
/* new filtersetting to try */
|
||||
*p += (1 << 3);
|
||||
}
|
||||
|
||||
/* return the (last found) backup result, or the original p value */
|
||||
*p = p_backup;
|
||||
// DXIW(PIXCLKCTRL,DXIR(PIXCLKCTRL)&0x0B); /*enable the PIXPLL*/
|
||||
/* we found only a non-optimal value */
|
||||
if (*q == 2) return B_OK;
|
||||
|
||||
/* nothing worked at all */
|
||||
LOG(2,("DAC: no working VCO filter found!\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/* find nearest valid system PLL setting */
|
||||
static status_t g450_g550_dac_sys_pll_find(
|
||||
float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result)
|
||||
{
|
||||
int m = 0, n = 0;
|
||||
uint8 p = 0, q = 0;
|
||||
float error, error_best = 999999999;
|
||||
int best[3];
|
||||
float f_vco;
|
||||
|
||||
LOG(4,("DAC: G450/G550 restrictions apply\n"));
|
||||
|
||||
/* Make sure the requested pixelclock is within the PLL's operational limits */
|
||||
/* lower limit is min_system_vco divided by highest postscaler-factor */
|
||||
if (req_sclk < (si->ps.min_system_vco / 16.0))
|
||||
req_sclk = (si->ps.min_system_vco / 16.0);
|
||||
/* upper limit is max_system_vco */
|
||||
if (req_sclk > si->ps.max_system_vco) req_sclk = si->ps.max_system_vco;
|
||||
|
||||
/* iterate through all valid PLL postscaler settings */
|
||||
for (p=0x01; p < 0x20; p = p<<1)
|
||||
{
|
||||
/* calculate the needed VCO frequency for this postscaler setting */
|
||||
f_vco = req_sclk * p;
|
||||
|
||||
/* check if this is within range of the VCO specs */
|
||||
if ((f_vco >= si->ps.min_system_vco) && (f_vco <= si->ps.max_system_vco))
|
||||
{
|
||||
/* iterate trough all valid reference-frequency postscaler settings */
|
||||
for (m = 2; m <= 32; m++)
|
||||
{
|
||||
/* calculate VCO postscaler setting for current setup.. */
|
||||
n = (int)(((f_vco * m) / (si->ps.f_ref * 2)) + 0.5);
|
||||
/* ..and check for validity, BUT:
|
||||
* Keep in mind that we need to be able to test n-3 ... n+3! */
|
||||
if ((n < (8 + 3)) || (n > (128 - 3))) continue;
|
||||
|
||||
/* find error in frequency this setting gives */
|
||||
error = fabs(req_sclk - ((((si->ps.f_ref * 2)/ m) * n) / p));
|
||||
|
||||
/* note the setting if best yet */
|
||||
if (error < error_best)
|
||||
{
|
||||
error_best = error;
|
||||
best[0]=m;
|
||||
best[1]=n;
|
||||
best[2]=p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* setup the scalers programming values for found optimum setting */
|
||||
m=best[0] - 1;
|
||||
n=best[1] - 1;
|
||||
switch(best[2])
|
||||
{
|
||||
case 1:
|
||||
p = 0x40;
|
||||
break;
|
||||
case 2:
|
||||
p = 0x00;
|
||||
break;
|
||||
case 4:
|
||||
p = 0x01;
|
||||
break;
|
||||
case 8:
|
||||
p = 0x02;
|
||||
break;
|
||||
case 16:
|
||||
p = 0x03;
|
||||
break;
|
||||
}
|
||||
|
||||
/* log the closest VCO speed found */
|
||||
f_vco = ((si->ps.f_ref * 2) / (m + 1)) * (n + 1);
|
||||
LOG(2,("DAC: sys VCO frequency found %fMhz\n", f_vco));
|
||||
|
||||
/* now find the filtersetting that matches best with this frequency by testing.
|
||||
* for now we assume this routine succeeds to get us a stable setting */
|
||||
gx50_dac_check_sys_pll_range(m, n, &p, &q);
|
||||
|
||||
/* return the results */
|
||||
*calc_sclk = f_vco / best[2];
|
||||
*m_result = m;
|
||||
*n_result = n;
|
||||
*p_result = p;
|
||||
|
||||
/* display the found pixelclock values */
|
||||
LOG(2,("DAC: sys PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
|
||||
req_sclk, *calc_sclk, *m_result, *n_result, *p_result));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*set up system pll - NB mclk is memory clock */
|
||||
status_t g100_dac_set_sys_pll()
|
||||
{
|
||||
/* values for DAC sys pll registers */
|
||||
@@ -660,8 +855,7 @@ status_t g100_dac_set_sys_pll()
|
||||
float calc_sclk;
|
||||
|
||||
LOG(1,("DAC: Setting up G100 system clock\n"));
|
||||
//zodra gclk, mclk en fmclk DIV ingesteld is via PINS en hieronder:
|
||||
g100_g400max_dac_sys_pll_find(si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
|
||||
g100_g400max_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
|
||||
|
||||
/* reprogram the clock - set PCI/AGP, program, set to programmed */
|
||||
/* disable the SYSPLL */
|
||||
@@ -707,30 +901,30 @@ status_t g100_dac_set_sys_pll()
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*set up system pll - NB mclk is memory clock, */
|
||||
/*set up system pll - NB mclk is memory clock */
|
||||
status_t g200_dac_set_sys_pll()
|
||||
{
|
||||
uint8 m, n, p;/*values for DAC sys pll registers*/
|
||||
/* values for DAC sys pll registers */
|
||||
uint8 m, n, p;
|
||||
uint time = 0;
|
||||
uint32 temp;
|
||||
float calc_sclk;
|
||||
|
||||
LOG(1,("DAC: Setting up G200 system clock\n"));
|
||||
//zodra gclk, mclk en fmclk DIV ingesteld is via PINS !EN OPTION2! en hieronder:
|
||||
//g100_g400max_dac_sys_pll_find(si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
|
||||
//voor nu:
|
||||
g100_g400max_dac_sys_pll_find(124.2, &calc_sclk, &m, &n, &p);
|
||||
g100_g400max_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
|
||||
|
||||
/*reprogram the clock - set PCI/AGP, program, set to programmed*/
|
||||
//fixme: PINS..
|
||||
CFGW(OPTION2,0x8000); /*no memory clock divider (pinced from win)*/
|
||||
/* reprogram the clock - set PCI/AGP, program, set to programmed */
|
||||
/* disable the SYSPLL */
|
||||
CFGW(OPTION, CFGR(OPTION) | 0x04);
|
||||
/* select the PCI/AGP clock */
|
||||
CFGW(OPTION, CFGR(OPTION) & 0xfffffffc);
|
||||
/* enable the SYSPLL */
|
||||
CFGW(OPTION, CFGR(OPTION) & 0xfffffffb);
|
||||
|
||||
CFGW(OPTION,CFGR(OPTION)|0x04); /*disable the SYSPLL*/
|
||||
CFGW(OPTION,CFGR(OPTION)&0xFFFFFFFC); /*select the PCI/AGP clock*/
|
||||
CFGW(OPTION,CFGR(OPTION)&0xFFFFFFFB); /*enable the SYSPLL*/
|
||||
|
||||
DXIW(SYSPLLM,m);
|
||||
DXIW(SYSPLLN,n);
|
||||
DXIW(SYSPLLP,p);
|
||||
/* program the new clock */
|
||||
DXIW(SYSPLLM, m);
|
||||
DXIW(SYSPLLN, n);
|
||||
DXIW(SYSPLLP, p);
|
||||
|
||||
/* Wait for the SYSPLL frequency to lock until timeout occurs */
|
||||
while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
|
||||
@@ -744,74 +938,57 @@ status_t g200_dac_set_sys_pll()
|
||||
else
|
||||
LOG(2,("DAC: sys PLL frequency locked\n"));
|
||||
|
||||
CFGW(OPTION,CFGR(OPTION)|0x04); /*disable the SYSPLL*/
|
||||
//fixme: PINS..
|
||||
CFGW(OPTION,(CFGR(OPTION)&0xFFFFFF27)|0x1); /*select the SYSPLLs chosen*/
|
||||
CFGW(OPTION,(CFGR(OPTION)&0xFFFFFFFB)|0x20); /*enable the SYSPLL*/
|
||||
/* disable the SYSPLL */
|
||||
CFGW(OPTION, CFGR(OPTION) | 0x04);
|
||||
/* setup Wclk divisor and enable/disable Wclk, Gclk and Mclk divisors
|
||||
* according to PINS */
|
||||
temp = (CFGR(OPTION2) & 0x00383000);
|
||||
if (si->ps.v3_option2_reg & 0x04) temp |= 0x00004000;
|
||||
if (si->ps.v3_option2_reg & 0x08) temp |= 0x00008000;
|
||||
if (si->ps.v3_option2_reg & 0x10) temp |= 0x00010000;
|
||||
if (si->ps.v3_option2_reg & 0x20) temp |= 0x00020000;
|
||||
CFGW(OPTION2, temp);
|
||||
/* setup Gclk and Mclk divisors according to PINS */
|
||||
temp = (CFGR(OPTION) & 0xffffff27);
|
||||
if (si->ps.v3_clk_div & 0x01) temp |= 0x08;
|
||||
if (si->ps.v3_clk_div & 0x02) temp |= 0x10;
|
||||
/* fixme: swapPLL can only be done when the rest of the driver respects this also! */
|
||||
//never used AFAIK:
|
||||
//if (si->ps.v3_clk_div & 0x08) temp |= 0x40;
|
||||
/* select the SYSPLL as system clock source */
|
||||
temp |= 0x01;
|
||||
CFGW(OPTION, temp);
|
||||
/* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */
|
||||
CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*set up system pll - NB mclk is memory clock, */
|
||||
/*set up system pll - NB mclk is memory clock */
|
||||
status_t g400_dac_set_sys_pll()
|
||||
|
||||
{
|
||||
uint32 scalers; /*value for option 3*/
|
||||
uint8 m, n, p;/*values for DAC sys pll registers*/
|
||||
uint8 mclk_duty,oclk_duty;
|
||||
|
||||
/* values for DAC sys pll registers */
|
||||
uint8 m, n, p;
|
||||
uint time = 0;
|
||||
float mclk,oclk;
|
||||
float temp_f;
|
||||
float calc_sclk;
|
||||
|
||||
/* fixme? get from PINS */
|
||||
int mclk_div = 4;
|
||||
int oclk_div = 3;
|
||||
|
||||
float div[8]={0.3333,0.4,0.4444,0.5,0.6666,0,0,0};
|
||||
|
||||
LOG(1,("DAC: Setting up G400/G400MAX system clock\n"));
|
||||
g100_g400max_dac_sys_pll_find(si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
|
||||
g100_g400max_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
|
||||
|
||||
/* calculate the real clock speeds derivated from SYSPLL */
|
||||
mclk = div[mclk_div] * calc_sclk;
|
||||
oclk = div[oclk_div] * calc_sclk;
|
||||
/* reprogram the clock - set PCI/AGP, program, set to programmed */
|
||||
/* clear, so don't o/clock addons */
|
||||
CFGW(OPTION2, 0);
|
||||
/* disable the SYSPLL */
|
||||
CFGW(OPTION, CFGR(OPTION) | 0x04);
|
||||
/* select the PCI/AGP clock */
|
||||
CFGW(OPTION3, 0);
|
||||
/* enable the SYSPLL */
|
||||
CFGW(OPTION, CFGR(OPTION) & 0xfffffffb);
|
||||
|
||||
/*work out the duty cycle correction*/
|
||||
temp_f=1/(float)oclk;
|
||||
temp_f*=1000;
|
||||
LOG(2,("DAC:oclk correction ns: %f\n",temp_f));
|
||||
temp_f-=2.25;
|
||||
temp_f/=0.5;
|
||||
oclk_duty=(uint8)temp_f;
|
||||
|
||||
temp_f=1/(float)mclk;
|
||||
temp_f*=1000;
|
||||
LOG(2,("DAC:mclk correction ns: %f\n",temp_f));
|
||||
temp_f-=2.25;
|
||||
temp_f/=0.5;
|
||||
mclk_duty=(uint8)temp_f;
|
||||
|
||||
/*calculate OPTION3*/
|
||||
scalers=(0x1<<0)|(0x1<<10)|(0x1<<20);
|
||||
scalers|=(oclk_div<<3)|(mclk_div<<13)|(oclk_div<<23);
|
||||
scalers|=(oclk_duty<<6)|(mclk_duty<<16)|(oclk_duty<<26);
|
||||
|
||||
/*print out the results*/
|
||||
LOG(2,("DAC: MCLK:%f\tOCLK:%f\n",mclk,oclk));
|
||||
LOG(2,("DAC: mclk_div:0x%x mclk_duty:0x%x\noclk_div:0x%x oclk_duty:0x%x\nOPTION3: 0x%x\n",
|
||||
mclk_div,mclk_duty,oclk_div,oclk_duty,scalers));
|
||||
|
||||
/*reprogram the clock - set PCI/AGP, program, set to programmed*/
|
||||
CFGW(OPTION2,0); /*clear so don't o/clock add ons*/
|
||||
CFGW(OPTION,CFGR(OPTION)|0x04); /*disable the SYSPLL*/
|
||||
CFGW(OPTION3,0); /*select the PCI/AGP clock*/
|
||||
CFGW(OPTION,CFGR(OPTION)&0xFFFFFFFB); /*enable the SYSPLL*/
|
||||
|
||||
DXIW(SYSPLLM,m);
|
||||
DXIW(SYSPLLN,n);
|
||||
DXIW(SYSPLLP,p);
|
||||
/* program the new clock */
|
||||
DXIW(SYSPLLM, m);
|
||||
DXIW(SYSPLLN, n);
|
||||
DXIW(SYSPLLP, p);
|
||||
|
||||
/* Wait for the SYSPLL frequency to lock until timeout occurs */
|
||||
while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
|
||||
@@ -825,13 +1002,71 @@ status_t g400_dac_set_sys_pll()
|
||||
else
|
||||
LOG(2,("DAC: sys PLL frequency locked\n"));
|
||||
|
||||
CFGW(OPTION,CFGR(OPTION)|0x04); /*disable the SYSPLL*/
|
||||
CFGW(OPTION3,scalers); /*select the SYSPLLs chosen*/
|
||||
CFGW(OPTION,CFGR(OPTION)&0xFFFFFFFB); /*enable the SYSPLL*/
|
||||
/* disable the SYSPLL */
|
||||
CFGW(OPTION, CFGR(OPTION) | 0x04);
|
||||
/* setup Gclk, Mclk and Wclk divs via PINS and select SYSPLL as system clock source */
|
||||
CFGW(OPTION3, si->ps.option3_reg);
|
||||
/* make sure the PLLs are not swapped (set default config) */
|
||||
CFGW(OPTION, CFGR(OPTION) & 0xffffffbf);
|
||||
/* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */
|
||||
CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*set up system pll - NB mclk is memory clock, */
|
||||
//fixme: implement this routine for coldstart:
|
||||
//status_t g450_dac_set_sys_pll(int m,int n,int mclk_div,int oclk_div)
|
||||
/*set up system pll - NB mclk is memory clock */
|
||||
status_t g450_dac_set_sys_pll()
|
||||
{
|
||||
/* values for DAC sys pll registers */
|
||||
uint8 m, n, p;
|
||||
uint time = 0;
|
||||
float calc_sclk;
|
||||
|
||||
LOG(1,("DAC: Setting up G450/G550 system clock\n"));
|
||||
/* reprogram the clock - set PCI/AGP, program, set to programmed */
|
||||
/* clear, so don't o/clock addons */
|
||||
CFGW(OPTION2, 0);
|
||||
/* setup OPTION via pins */
|
||||
CFGW(OPTION, si->ps.option_reg);
|
||||
/* disable the SYSPLL */
|
||||
CFGW(OPTION, CFGR(OPTION) | 0x04);
|
||||
/* select the PCI/AGP clock */
|
||||
CFGW(OPTION3, 0);
|
||||
/* enable the SYSPLL */
|
||||
CFGW(OPTION, CFGR(OPTION) & 0xfffffffb);
|
||||
|
||||
/* this routine also tests the filters, so it actually programs the clock already */
|
||||
g450_g550_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
|
||||
|
||||
/* program the new clock */
|
||||
DXIW(SYSPLLM, m);
|
||||
DXIW(SYSPLLN, n);
|
||||
DXIW(SYSPLLP, p);
|
||||
|
||||
/* Wait for the SYSPLL frequency to lock until timeout occurs */
|
||||
while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
|
||||
{
|
||||
time++;
|
||||
snooze(1);
|
||||
}
|
||||
|
||||
if (time > 2000)
|
||||
LOG(2,("DAC: sys PLL frequency not locked!\n"));
|
||||
else
|
||||
LOG(2,("DAC: sys PLL frequency locked\n"));
|
||||
|
||||
/* disable the SYSPLL */
|
||||
CFGW(OPTION, CFGR(OPTION) | 0x04);
|
||||
/* setup Gclk, Mclk and Wclk divs via PINS and select SYSPLL as system clock source */
|
||||
CFGW(OPTION3, si->ps.option3_reg);
|
||||
/* setup option2 via pins */
|
||||
CFGW(OPTION2, si->ps.option2_reg);
|
||||
/* make sure the PLLs are not swapped (set default config) */
|
||||
/* fixme: swapPLL can only be done when the rest of the driver respects this also!
|
||||
* (never used AFAIK) */
|
||||
CFGW(OPTION, CFGR(OPTION) & 0xffffffbf);
|
||||
/* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */
|
||||
CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Authors:
|
||||
Mark Watson 12/1999,
|
||||
Apsed,
|
||||
Rudolf Cornelissen 10/2002
|
||||
Rudolf Cornelissen 10-12/2002
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00008000
|
||||
@@ -54,60 +54,62 @@ static void mga_dump_configuration_space (void)
|
||||
status_t gx00_general_powerup()
|
||||
{
|
||||
status_t status;
|
||||
uint32 class;
|
||||
uint32 card_class;
|
||||
|
||||
//detect card type and powerup
|
||||
/* detect card type and power it up */
|
||||
switch(CFGR(DEVID))
|
||||
{
|
||||
case 0x0519102b: //MGA-2064 Millenium PCI
|
||||
case 0x051a102b: //MGA-1064 Mystic PCI
|
||||
LOG(8,("POWERUP: unimplemented Matrox device %08x\n",CFGR(DEVID)));
|
||||
LOG(8,("POWERUP: Unimplemented Matrox device %08x\n",CFGR(DEVID)));
|
||||
return B_ERROR;
|
||||
case 0x051b102b:case 0x051f102b: //MGA-2164 Millenium 2 PCI/AGP
|
||||
si->ps.card_type=MIL2;
|
||||
LOG(4,("POWERUP:Detected MGA-2164 Millennium 2\n"));
|
||||
si->ps.card_type = MIL2;
|
||||
LOG(4,("POWERUP: Detected MGA-2164 Millennium 2\n"));
|
||||
status = mil2_general_powerup();
|
||||
break;
|
||||
case 0x1000102b:case 0x1001102b: //G100
|
||||
si->ps.card_type=G100;
|
||||
LOG(4,("POWERUP:Detected G100\n"));
|
||||
si->ps.card_type = G100;
|
||||
LOG(4,("POWERUP: Detected G100\n"));
|
||||
status = g100_general_powerup();
|
||||
break;
|
||||
case 0x0520102b:case 0x0521102b: //G200
|
||||
si->ps.card_type=G200;
|
||||
LOG(4,("POWERUP:Detected G200\n"));
|
||||
si->ps.card_type = G200;
|
||||
LOG(4,("POWERUP: Detected G200\n"));
|
||||
status = g200_general_powerup();
|
||||
break;
|
||||
case 0x0525102b: //G400
|
||||
LOG(4,("POWERUP:Detected G4"));
|
||||
//Check if it is a G450...
|
||||
class = 0xff&CFGR(CLASS);
|
||||
if (class & 0x80) //G450
|
||||
case 0x0525102b: //G400, G400MAX or G450
|
||||
LOG(4,("POWERUP: Detected G4"));
|
||||
/* get classinfo to distinguish different types */
|
||||
card_class = CFGR(CLASS) & 0xff;
|
||||
if (card_class & 0x80)
|
||||
{
|
||||
si->ps.card_type=G450;
|
||||
LOG(4, ("50 revision %x\n", class&0x7f));
|
||||
/* G450 */
|
||||
si->ps.card_type = G450;
|
||||
LOG(4, ("50 revision %x\n", card_class & 0x7f));
|
||||
status = g450_general_powerup();
|
||||
}
|
||||
else //G400
|
||||
else
|
||||
{
|
||||
si->ps.card_type=G400;
|
||||
LOG(4, ("00 revision %x\n", class&0x7f));
|
||||
/* standard G400, G400MAX */
|
||||
/* the only difference is the max RAMDAC speed, accounted for via pins. */
|
||||
si->ps.card_type = G400;
|
||||
LOG(4, ("00 revision %x\n", card_class & 0x7f));
|
||||
status = g400_general_powerup();
|
||||
}
|
||||
break;
|
||||
case 0x2527102b://G550 patch from Jean-Michel Batto
|
||||
si->ps.card_type=G450;
|
||||
LOG(4,("POWERUP:Detected G550\n"));
|
||||
si->ps.card_type = G450;
|
||||
LOG(4,("POWERUP: Detected G550\n"));
|
||||
status = g450_general_powerup();
|
||||
break;
|
||||
default:
|
||||
LOG(8,("POWERUP:Failed to detect valid card 0x%08x\n",CFGR(DEVID)));
|
||||
LOG(8,("POWERUP: Failed to detect valid card 0x%08x\n",CFGR(DEVID)));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/*override memory if requested by user*/
|
||||
// even if detection works on the G400
|
||||
if (si->settings.memory != 0) // apsed
|
||||
/* override memory detection if requested by user */
|
||||
if (si->settings.memory != 0)
|
||||
si->ps.memory_size = si->settings.memory;
|
||||
|
||||
return status;
|
||||
@@ -252,61 +254,20 @@ status_t mil2_general_powerup()
|
||||
LOG(2, ("INIT: Skipping card coldstart!\n"));
|
||||
mil2_dac_init();
|
||||
|
||||
//rudolf: sync on green test:
|
||||
/* disable 15bit mode CLUT-overlay function */
|
||||
//enable 'sync on green' option
|
||||
// DXIW(GENCTRL, DXIR(GENCTRL | 0x20));
|
||||
/* enable composite sync instead of Hsync only */
|
||||
// VGAW_I(CRTCEXT,3,(VGAR_I(CRTCEXT,3) | 0x40));
|
||||
//end sync on green test.
|
||||
|
||||
VGAW_I(SEQ,1,0x00);
|
||||
/*enable screen*/
|
||||
return B_OK;
|
||||
|
||||
return B_ERROR; // apsed TODO MIL2 taken from G100, avoid DXIR/W DACR/W
|
||||
|
||||
/*power up the PLLs,LUT,DAC*/
|
||||
/*this bit should not be needed if BIOS has initialised it*/
|
||||
LOG(2,("INIT:PLL/LUT/DAC powerup\n"));
|
||||
DXIW(VREFCTRL,0x3F); /*set voltage reference - using DAC reference block*/
|
||||
delay(100000); /*wait for 100ms for voltage reference to stabalise*/
|
||||
CFGW(OPTION,CFGR(OPTION)|0x20); /*power up the SYSPLL - sets syspllpdN to 1*/
|
||||
while(!(DXIR(SYSPLLSTAT)&0x40)); /*wait for the SYSPLL frequency to lock*/
|
||||
LOG(2,("INIT: SYS PLL locked\n"));
|
||||
DXIW(PIXCLKCTRL,0x08); /*power up the PIXPLL - sets pixpllpdN to 1*/
|
||||
while(!(DXIR(PIXPLLSTAT)&0x40)); /*wait for the PIXPLL frequency to lock*/
|
||||
LOG(2,("INIT: PIX PLL locked\n"));
|
||||
DXIW(MISCCTRL,0x1b); /*CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC*/
|
||||
|
||||
/* setup i2c bus */
|
||||
i2c_init();
|
||||
|
||||
/*make sure card is in powergraphics mode*/
|
||||
VGAW_I(CRTCEXT,3,0x80);
|
||||
|
||||
/*set the system clocks to powergraphics speed*/
|
||||
LOG(2,("INIT:Setting SYS/PIX plls to powergraphics speeds\n"));
|
||||
g100_dac_set_sys_pll();
|
||||
|
||||
/*RAM initialisation*/
|
||||
LOG(2,("INIT:RAM init\n"));
|
||||
gx00_crtc_dpms(0,0,0); /*turn off both displays*/
|
||||
ACCW(MCTLWTST,si->ps.mem_ctl); /*set memory wait states*/
|
||||
CFGW(OPTION,(CFGR(OPTION)&0xFFFF83FF)|si->ps.mem_type); /*set RAM type and config*/
|
||||
CFGW(OPTION2,(CFGR(OPTION2)&0xC100)|(si->ps.mem_rd)); /*set MEMRDCLK*/
|
||||
CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|(si->ps.membuf<<12)); /*set the memory buffer type*/
|
||||
delay(250); /*wait for 250microseconds*/
|
||||
ACCW(MACCESS,ACCR(MACCESS)&0xFFFF7FFF); /*reset memory*/
|
||||
delay(250);
|
||||
ACCW(MACCESS,ACCR(MACCESS)|0xC000); /*sets JEDEC as well*/
|
||||
delay(250); /*wait for 250microseconds*/
|
||||
ACCW(MACCESS,ACCR(MACCESS)&0xFFFF3FFF);
|
||||
delay(250);
|
||||
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF0000)|(si->ps.mem_rd&0xFFFF));/*set tap delays*/
|
||||
CFGW(OPTION,(CFGR(OPTION)&0xffe07fff)|(si->ps.mem_rfhcnt<<15)); /*start memory refresh*/
|
||||
|
||||
/*Bus parameters*/
|
||||
CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29))); /*enable retries, use advanced read*/
|
||||
|
||||
/*enable writing to crtc registers*/
|
||||
VGAW_I(CRTC,0x11,0);
|
||||
|
||||
/*turn on display one*/
|
||||
gx00_crtc_dpms(1,1,1);
|
||||
|
||||
// apsed TODO MIL2 taken from G100, avoid DXIR/W DACR/W
|
||||
//rudolf: G100 version that was here nolonger exists, look at new implementation...
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -329,20 +290,32 @@ status_t g100_general_powerup()
|
||||
if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
|
||||
|
||||
/*power up the PLLs,LUT,DAC*/
|
||||
/*this bit should not be needed if BIOS has initialised it*/
|
||||
LOG(2,("INIT: PLL/LUT/DAC powerup\n"));
|
||||
/* turn off both displays and the hardcursor (also disables transfers) */
|
||||
gx00_crtc_dpms(0,0,0);
|
||||
gx00_crtc_cursor_hide();
|
||||
/* 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 */
|
||||
DXIW(VREFCTRL,0x03); /*set voltage reference - using DAC reference block partly */
|
||||
delay(100000); /*wait for 100ms for voltage reference to stabalise*/
|
||||
CFGW(OPTION,CFGR(OPTION)|0x20); /*power up the SYSPLL - sets syspllpdN to 1*/
|
||||
while(!(DXIR(SYSPLLSTAT)&0x40)); /*wait for the SYSPLL frequency to lock*/
|
||||
LOG(2,("INIT: SYS PLL locked\n"));
|
||||
DXIW(PIXCLKCTRL,0x08); /*power up the PIXPLL - sets pixpllpdN to 1*/
|
||||
while(!(DXIR(PIXPLLSTAT)&0x40)); /*wait for the PIXPLL frequency to lock*/
|
||||
LOG(2,("INIT: PIX PLL locked\n"));
|
||||
DXIW(MISCCTRL,0x1b); /*CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC*/
|
||||
/* 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 */
|
||||
//fixme: setup b5 later for 'sync on green' option
|
||||
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));
|
||||
|
||||
/* setup i2c bus */
|
||||
i2c_init();
|
||||
@@ -356,14 +329,13 @@ status_t g100_general_powerup()
|
||||
|
||||
/* 'official' RAM initialisation */
|
||||
LOG(2,("INIT: RAM init\n"));
|
||||
/* turn off both displays (also disables transfers) */
|
||||
gx00_crtc_dpms(0,0,0);
|
||||
/* disable plane write mask (needed for SDRAM) */
|
||||
/* 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:
|
||||
* - no split framebuffer,
|
||||
/* 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));
|
||||
@@ -372,16 +344,13 @@ status_t g100_general_powerup()
|
||||
* 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 mode register opcode to $0 */
|
||||
// ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xE1FFFFFF)); /* G200 only */
|
||||
/* set RAM read tap delay G100 */
|
||||
/* set RAM read tap delay */
|
||||
CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFFFF0) | ((si->ps.v3_mem_type & 0xf0) >> 4));
|
||||
// ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF0000)|the_setting); /* G200 version */
|
||||
/* wait 200uS minimum */
|
||||
snooze(250);
|
||||
|
||||
/* reset memory */
|
||||
ACCW(MACCESS,ACCR(MACCESS)&0xFFFF7FFF);
|
||||
ACCW(MACCESS, 0x00000000);
|
||||
/* select JEDEC reset method */
|
||||
ACCW(MACCESS,ACCR(MACCESS)|0x4000);
|
||||
/* perform actual RAM reset */
|
||||
@@ -424,52 +393,78 @@ status_t g200_general_powerup()
|
||||
if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
|
||||
|
||||
/*power up the PLLs,LUT,DAC*/
|
||||
/*this bit should not be needed if BIOS has initialised it*/
|
||||
LOG(2,("INIT: PLL/LUT/DAC powerup\n"));
|
||||
//rudolf: check from here on:
|
||||
DXIW(VREFCTRL,0x3f); /*set voltage reference - using DAC reference block*/
|
||||
delay(100000); /*wait for 100ms for voltage reference to stabalise*/
|
||||
CFGW(OPTION,CFGR(OPTION)|0x20); /*power up the SYSPLL - sets syspllpdN to 1*/
|
||||
while(!(DXIR(SYSPLLSTAT)&0x40)); /*wait for the SYSPLL frequency to lock*/
|
||||
LOG(2,("INIT: SYS PLL locked\n"));
|
||||
DXIW(PIXCLKCTRL,0x08); /*power up the PIXPLL - sets pixpllpdN to 1*/
|
||||
while(!(DXIR(PIXPLLSTAT)&0x40)); /*wait for the PIXPLL frequency to lock*/
|
||||
LOG(2,("INIT: PIX PLL locked\n"));
|
||||
DXIW(MISCCTRL,0x1b); /*CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC*/
|
||||
//until here
|
||||
/* turn off both displays and the hardcursor (also disables transfers) */
|
||||
gx00_crtc_dpms(0,0,0);
|
||||
gx00_crtc_cursor_hide();
|
||||
/* G200 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 */
|
||||
//fixme: setup b5 later for 'sync on green' option
|
||||
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));
|
||||
|
||||
/* setup i2c bus */
|
||||
i2c_init();
|
||||
|
||||
//rudolf: remove:
|
||||
/*read the PINS and other stuff*/
|
||||
if (g200_card_info()==B_ERROR)
|
||||
return B_ERROR;
|
||||
//until here
|
||||
|
||||
/*make sure card is in powergraphics mode*/
|
||||
VGAW_I(CRTCEXT,3,0x80);
|
||||
|
||||
/*set the system clocks to powergraphics speed*/
|
||||
LOG(2,("INIT: Setting SYS/PIX plls to powergraphics speeds\n"));
|
||||
LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
|
||||
g200_dac_set_sys_pll();
|
||||
|
||||
/*RAM initialisation*/
|
||||
LOG(2,("INIT:RAM init\n"));
|
||||
gx00_crtc_dpms(0,0,0); /*turn off both displays*/
|
||||
ACCW(MCTLWTST,si->ps.mem_ctl); /*set memory wait states*/
|
||||
CFGW(OPTION,(CFGR(OPTION)&0xFFFF83FF)|si->ps.mem_type); /*set RAM type and config*/
|
||||
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF)|(si->ps.mem_rd&0xFFFF0000));/*set MEMRDBK - mrsopcode*/
|
||||
CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|(si->ps.membuf<<12)); /*set the memory buffer type*/
|
||||
delay(250); /*wait for 250microseconds*/
|
||||
ACCW(MACCESS,ACCR(MACCESS)&0xFFFF7FFF); /*reset memory*/
|
||||
ACCW(MACCESS,ACCR(MACCESS)|0x8000);
|
||||
delay(250); /*wait for 250microseconds*/
|
||||
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF0000)|(si->ps.mem_rd&0xFFFF));/*set tap delays*/
|
||||
CFGW(OPTION,(CFGR(OPTION)&0xffe07fff)|(si->ps.mem_rfhcnt<<15)); /*start memory refresh*/
|
||||
/* 'official' RAM initialisation */
|
||||
LOG(2,("INIT: RAM init\n"));
|
||||
/* disable hardware plane write mask if SDRAM card */
|
||||
if (si->ps.sdram) CFGW(OPTION,(CFGR(OPTION) & 0xffffbfff));
|
||||
/* 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:
|
||||
* - 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)));
|
||||
/* set memory buffer type */
|
||||
CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|((si->ps.v3_option2_reg & 0x03) << 12));
|
||||
/* set mode register opcode and streamer flow control */
|
||||
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0x0000FFFF)|(si->ps.memrdbk_reg & 0xffff0000));
|
||||
/* set RAM read tap delays */
|
||||
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF0000)|(si->ps.memrdbk_reg & 0x0000ffff));
|
||||
/* wait 200uS minimum */
|
||||
snooze(250);
|
||||
|
||||
/*Bus parameters*/
|
||||
CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29))); /*enable retries, use advanced read*/
|
||||
/* reset memory */
|
||||
ACCW(MACCESS, 0x00000000);
|
||||
/* perform actual RAM reset */
|
||||
ACCW(MACCESS,ACCR(MACCESS)|0x8000);
|
||||
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);
|
||||
@@ -485,8 +480,7 @@ status_t g400_general_powerup()
|
||||
{
|
||||
status_t result;
|
||||
|
||||
//fully functional G400 powerup -> uses settings from my card if no PINS
|
||||
LOG(4, ("INIT: G400 powerup\n"));
|
||||
LOG(4, ("INIT: G400/G400MAX powerup\n"));
|
||||
if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
|
||||
|
||||
/* initialize the shared_info PINS struct */
|
||||
@@ -500,52 +494,78 @@ status_t g400_general_powerup()
|
||||
if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
|
||||
|
||||
/*power up the PLLs,LUT,DAC*/
|
||||
/*this bit should not be needed if BIOS has initialised it*/
|
||||
LOG(4,("INIT: G400 PLL/LUT/DAC powerup\n"));
|
||||
DXIW(VREFCTRL,0x30); /*set voltage reference - using DAC reference block*/
|
||||
delay(100000); /*wait for 100ms for voltage reference to stabalise*/
|
||||
CFGW(OPTION,CFGR(OPTION)|0x20); /*power up the SYSPLL - sets syspllpdN to 1*/
|
||||
while(!(DXIR(SYSPLLSTAT)&0x40)); /*wait for the SYSPLL frequency to lock*/
|
||||
LOG(2,("INIT: SYS PLL locked\n"));
|
||||
DXIW(PIXCLKCTRL,0x08); /*power up the PIXPLL - sets pixpllpdN to 1*/
|
||||
while(!(DXIR(PIXPLLSTAT)&0x40)); /*wait for the PIXPLL frequency to lock*/
|
||||
LOG(2,("INIT: PIX PLL locked\n"));
|
||||
DXIW(MISCCTRL,0x9b); /*CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC*/
|
||||
DXIW(MAFCDEL,0x2); /*makes CRTC2 stable! Matrox specify 8, but use 4 - grrrr!*/
|
||||
LOG(4,("INIT: PLL/LUT/DAC powerup\n"));
|
||||
/* turn off both displays and the hardcursor (also disables transfers) */
|
||||
gx00_crtc_dpms(0,0,0);
|
||||
g400_crtc2_dpms(0,0,0);
|
||||
gx00_crtc_cursor_hide();
|
||||
|
||||
/* set voltage reference - not using DAC reference block */
|
||||
DXIW(VREFCTRL,0x00);
|
||||
/* 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 */
|
||||
//fixme: setup b5 later for 'sync on green' option
|
||||
DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
|
||||
/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
|
||||
DXIW(MISCCTRL,0x9b);
|
||||
snooze(250);
|
||||
/* re-enable pixelclock oscillations */
|
||||
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
|
||||
|
||||
DXIW(MAFCDEL,0x02); /*makes CRTC2 stable! Matrox specify 8, but use 4 - grrrr!*/
|
||||
DXIW(PANELMODE,0x00); /*eclipse panellink*/
|
||||
|
||||
/* setup i2c bus */
|
||||
i2c_init();
|
||||
|
||||
//rudolf: remove
|
||||
/*read the PINS and other stuff*/
|
||||
if (g400_card_info()==B_ERROR)
|
||||
return B_ERROR;
|
||||
//end remove
|
||||
|
||||
/*make sure card is in powergraphics mode*/
|
||||
/* make sure card is in powergraphics mode */
|
||||
VGAW_I(CRTCEXT,3,0x80);
|
||||
|
||||
/*set the system clocks to powergraphics speed*/
|
||||
LOG(2,("INIT: Setting SYS/PIX plls to powergraphics speeds\n"));
|
||||
/* set the system clocks to powergraphics speed */
|
||||
LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
|
||||
g400_dac_set_sys_pll();
|
||||
|
||||
/*RAM initialisation*/
|
||||
LOG(2,("INIT:RAM init\n"));
|
||||
gx00_crtc_dpms(0,0,0); /*turn off both displays*/
|
||||
g400_crtc2_dpms(0,0,0);
|
||||
ACCW(MCTLWTST,si->ps.mem_ctl); /*set memory wait states*/
|
||||
CFGW(OPTION,(CFGR(OPTION)&0xFFFF83FF)|si->ps.mem_type); /*set RAM type and config*/
|
||||
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF)|(si->ps.mem_rd&0xFFFF0000));/*set MEMRDBK - mrsopcode*/
|
||||
delay(250); /*wait for 250microseconds*/
|
||||
ACCW(MACCESS,ACCR(MACCESS)&0xFFFF7FFF); /*reset memory*/
|
||||
ACCW(MACCESS,ACCR(MACCESS)|0x8000);
|
||||
delay(250); /*wait for 250microseconds*/
|
||||
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF0000)|(si->ps.mem_rd&0xFFFF));/*set tap delays*/
|
||||
CFGW(OPTION,(CFGR(OPTION)&0xffe07fff)|(si->ps.mem_rfhcnt<<15)); /*start memory refresh*/
|
||||
/* 'official' RAM initialisation */
|
||||
LOG(2,("INIT: RAM init\n"));
|
||||
/* disable hardware plane write mask if SDRAM card */
|
||||
if (si->ps.sdram) CFGW(OPTION,(CFGR(OPTION) & 0xffffbfff));
|
||||
/* 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:
|
||||
* - 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)));
|
||||
/* set mode register opcode and streamer flow control */
|
||||
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0x0000FFFF)|(si->ps.memrdbk_reg & 0xffff0000));
|
||||
/* set RAM read tap delays */
|
||||
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF0000)|(si->ps.memrdbk_reg & 0x0000ffff));
|
||||
/* wait 200uS minimum */
|
||||
snooze(250);
|
||||
|
||||
/*Bus parameters*/
|
||||
CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29))); /*enable retries, use advanced read*/
|
||||
/* reset memory */
|
||||
ACCW(MACCESS, 0x00000000);
|
||||
/* perform actual RAM reset */
|
||||
ACCW(MACCESS,ACCR(MACCESS)|0x8000);
|
||||
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. */
|
||||
|
||||
/* 'advance read' busparameter and 'memory priority' enable/disable setup */
|
||||
CFGW(OPTION, ((CFGR(OPTION) & 0xefbfffff) | (si->ps.option_reg & 0x10400000)));
|
||||
|
||||
/*enable writing to crtc registers*/
|
||||
VGAW_I(CRTC,0x11,0);
|
||||
@@ -557,16 +577,18 @@ status_t g400_general_powerup()
|
||||
|
||||
/*turn on display one*/
|
||||
gx00_crtc_dpms(1,1,1);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
static
|
||||
status_t g450_general_powerup()
|
||||
{
|
||||
uint32 temp;
|
||||
//fixme: check if g450 and g550 powerup should be the same! (DAC outputconnector?)
|
||||
status_t result;
|
||||
uint32 pwr_cas[] = {0, 1, 5, 6, 7, 5, 2, 3};
|
||||
|
||||
LOG(4, ("INIT: G450 powerup\n"));
|
||||
LOG(4, ("INIT: G450/G550 powerup\n"));
|
||||
if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
|
||||
|
||||
/* initialize the shared_info PINS struct */
|
||||
@@ -576,82 +598,159 @@ status_t g450_general_powerup()
|
||||
/* log the PINS struct settings */
|
||||
dump_pins();
|
||||
|
||||
//rudolf: remove if impl in PINS above:
|
||||
// various sensible defaults for G450
|
||||
si->ps.sdram = true;
|
||||
//end remove
|
||||
|
||||
/* 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 gx00_general_bios_to_powergraphics();
|
||||
|
||||
/*power up the PLLs,LUT,DAC*/
|
||||
//rudolf: checkout coldstart from here:
|
||||
/* power up the PLLs,LUT,DAC */
|
||||
LOG(4,("INIT: PLL/LUT/DAC powerup\n"));
|
||||
/* disable outputs */
|
||||
DXIW(OUTPUTCONN,0x00);
|
||||
/* turn off both displays and the hardcursor (also disables transfers) */
|
||||
gx00_crtc_dpms(0,0,0);
|
||||
//fixme:
|
||||
//g400_crtc2_dpms(0,0,0);
|
||||
gx00_crtc_cursor_hide();
|
||||
|
||||
//In case you are interested here is some of the G450 powerup stuff -> nonfunction as yet
|
||||
|
||||
//These are the values of OPTION->OPTION4 used in Linux
|
||||
//rudolf: get from PINS...
|
||||
CFGW(OPTION, 0x400a1160);
|
||||
CFGW(OPTION2, 0x100ac00);
|
||||
CFGW(OPTION3, 0x90a409);
|
||||
CFGW(OPTION4, 0x80000004);
|
||||
/* power up everything except DVI electronics (for now) */
|
||||
DXIW(PWRCTRL,0x1b);
|
||||
/* set voltage reference - not using DAC reference block */
|
||||
DXIW(VREFCTRL,0x00);
|
||||
/* 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);
|
||||
|
||||
//rudolf: remove
|
||||
/*read the PINS and other stuff*/
|
||||
if (g450_card_info()==B_ERROR)
|
||||
return B_ERROR;
|
||||
//end remove
|
||||
/* disable pixelclock oscillations before switching on CLUT */
|
||||
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
|
||||
/* disable 15bit mode CLUT-overlay function */
|
||||
//fixme: setup b5 later for 'sync on green' option
|
||||
DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
|
||||
/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
|
||||
DXIW(MISCCTRL,0x9b);
|
||||
snooze(250);
|
||||
|
||||
//various init (as bios)
|
||||
CFGW(OPTION, ((CFGR(OPTION)&0xf8404164) | (si->ps.option&0x207e00)) );
|
||||
CFGW(OPTION2, (CFGR(OPTION2) | (0xfc00&si->ps.option2)));
|
||||
ACCW(MCTLWTST, si->ps.mem_ctl);
|
||||
CFGW(OPTION4, (si->ps.option4&0x6000000f));
|
||||
ACCW(MEMRDBK, si->ps.mem_rd);
|
||||
/* re-enable pixelclock oscillations */
|
||||
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
|
||||
|
||||
ACCW(MACCESS, ((si->ps.maccess&0x80)>>1) );
|
||||
//fixme:
|
||||
DXIW(MAFCDEL,0x02); /*makes CRTC2 stable! Matrox specify 8, but use 4 - grrrr!*/
|
||||
DXIW(PANELMODE,0x00); /*eclipse panellink*/
|
||||
|
||||
CFGW(OPTION4,((si->ps.option4&0x60000004)|0x80000000));
|
||||
/* setup i2c bus */
|
||||
i2c_init();
|
||||
|
||||
delay(250);
|
||||
/* make sure card is in powergraphics mode */
|
||||
VGAW_I(CRTCEXT,3,0x80);
|
||||
|
||||
if
|
||||
(
|
||||
((si->ps.option&0x200000) == 0) &&
|
||||
((si->ps.maccess&0x200) == 0)
|
||||
)
|
||||
/* set the system clocks to powergraphics speed */
|
||||
LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
|
||||
g450_dac_set_sys_pll();
|
||||
|
||||
/* 'official' RAM initialisation */
|
||||
LOG(2,("INIT: RAM init\n"));
|
||||
/* stop memory refresh, and setup b9, memconfig, b13, sgram planemask function, b21 fields,
|
||||
* and don't touch the rest */
|
||||
CFGW(OPTION, ((CFGR(OPTION) & 0xf8400164) | (si->ps.option_reg & 0x00207e00)));
|
||||
/* setup b10-b15 unknown field */
|
||||
CFGW(OPTION2, ((CFGR(OPTION2) & 0xffff0200) | (si->ps.option2_reg & 0x0000fc00)));
|
||||
|
||||
/* program memory control waitstates */
|
||||
ACCW(MCTLWTST, si->ps.mctlwtst_reg);
|
||||
/* program option4 b0-3 and b29-30 fields, reset the rest: stop memory clock */
|
||||
CFGW(OPTION4, (si->ps.option4_reg & 0x6000000f));
|
||||
/* set RAM read tap delays and mode register opcode / streamer flow control */
|
||||
ACCW(MEMRDBK, si->ps.memrdbk_reg);
|
||||
/* b7 v5_mem_type = done by Mark Watson. fixme: still confirm! (unknown bits) */
|
||||
ACCW(MACCESS, ((((uint32)si->ps.v5_mem_type) & 0x80) >> 1));
|
||||
/* clear b0-1 and 3, and set b31 in option4: re-enable memory clock */
|
||||
CFGW(OPTION4, ((si->ps.option4_reg & 0x60000004) | 0x80000000));
|
||||
snooze(250);
|
||||
|
||||
/* if DDR RAM */
|
||||
if ((si->ps.v5_mem_type & 0x0060) == 0x0020)
|
||||
{
|
||||
ACCW(MEMRDBK, ((si->ps.mem_rd)&0xffffefff));
|
||||
|
||||
if ((si->ps.maccess&0x100) == 0)
|
||||
/* if not 'EMRSW RAM-option' available */
|
||||
if (!(si->ps.v5_mem_type & 0x0100))
|
||||
{
|
||||
/* clear unknown bits */
|
||||
ACCW(MACCESS, 0x00000000);
|
||||
/* clear b12: unknown bit */
|
||||
ACCW(MEMRDBK, (si->ps.memrdbk_reg & 0xffffefff));
|
||||
}
|
||||
else
|
||||
/* if not 'DLL RAM-option' available */
|
||||
if (!(si->ps.v5_mem_type & 0x0200))
|
||||
{
|
||||
ACCW(MACCESS, ACCR(MACCESS)&0xffff00ff);
|
||||
/* clear b12: unknown bit */
|
||||
ACCW(MEMRDBK, (si->ps.memrdbk_reg & 0xffffefff));
|
||||
}
|
||||
}
|
||||
|
||||
temp = ACCR(MACCESS);
|
||||
temp &=0xffff80ff;
|
||||
temp = temp|((temp&0x8000)>>1)|0x8000;
|
||||
ACCW(MACCESS, temp);
|
||||
/* create positive flank to generate memory reset */
|
||||
ACCW(MACCESS,ACCR(MACCESS) & 0xffff7fff);
|
||||
ACCW(MACCESS,ACCR(MACCESS) | 0x00008000);
|
||||
snooze(250);
|
||||
|
||||
temp &= 0xffff7fff;
|
||||
ACCW(MACCESS, temp);
|
||||
/* start memory refresh */
|
||||
CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
|
||||
|
||||
delay(250);
|
||||
/* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
|
||||
ACCW(PLNWT,0x00000000);
|
||||
ACCW(PLNWT,0xffffffff);
|
||||
|
||||
if ((si->ps.maccess&0x400) == 0)
|
||||
/* if not 'MEMCASLT RAM-option' available */
|
||||
if (!(si->ps.v5_mem_type & 0x0400))
|
||||
{
|
||||
temp = si->ps.mem_ctl;
|
||||
temp = (temp &0x7) + 3;
|
||||
temp |= si->ps.mem_ctl &0xfffffff8;
|
||||
ACCW(MCTLWTST, temp);
|
||||
/* calculate powergraphics CAS-latency from pins CAS-latency, and update register setting */
|
||||
ACCW(MCTLWTST,
|
||||
((si->ps.mctlwtst_reg & 0xfffffff8) | pwr_cas[(si->ps.mctlwtst_reg & 0x07)]));
|
||||
|
||||
}
|
||||
|
||||
temp = CFGR(OPTION);
|
||||
temp &=0xffe07fff;
|
||||
temp |= si->ps.option&0x1f8000;
|
||||
CFGW(OPTION, temp);
|
||||
/*enable writing to crtc registers*/
|
||||
VGAW_I(CRTC,0x11,0);
|
||||
//fixme..
|
||||
if (si->ps.secondary_head)
|
||||
{
|
||||
//MAVW(LOCK,0x01);
|
||||
CR2W(DATACTL,0x00000000);
|
||||
}
|
||||
|
||||
/* enable primary analog output */
|
||||
gx50_general_output_select();
|
||||
|
||||
/*turn on display one*/
|
||||
gx00_crtc_dpms(1,1,1);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t gx50_general_output_select()
|
||||
{
|
||||
/* make sure this call is warranted */
|
||||
if ((si->ps.card_type != G450) && (si->ps.card_type != G550)) return B_ERROR;
|
||||
|
||||
/* choose primary analog outputconnector */
|
||||
if ((si->ps.primary_dvi) && (si->ps.secondary_head) && (si->ps.secondary_tvout))
|
||||
{
|
||||
if (i2c_sec_tv_adapter() == B_OK)
|
||||
{
|
||||
LOG(4,("INIT: secondary TV-adapter detected, using primary connector\n"));
|
||||
DXIW(OUTPUTCONN,0x01);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(4,("INIT: no secondary TV-adapter detected, using secondary connector\n"));
|
||||
DXIW(OUTPUTCONN,0x04);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(4,("INIT: using primary connector\n"));
|
||||
DXIW(OUTPUTCONN,0x01);
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -664,27 +763,27 @@ status_t gx00_general_dac_select(int dac)
|
||||
/*MISCCTRL, clock src,...*/
|
||||
switch(dac)
|
||||
{
|
||||
case DS_CRTCDAC_CRTC2MAVEN: /*CRTC->DAC,CRTC2->MAFC*/
|
||||
case DS_CRTC1DAC_CRTC2MAVEN:
|
||||
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); /*internal clk*/
|
||||
CR2W(CTL,(CR2R(CTL)&0xffe00779)|0xD0000002); /*external clk*/
|
||||
VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0x77));
|
||||
DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x82);
|
||||
break;
|
||||
case DS_CRTCMAVEN_CRTC2DAC: /*CRTC->MAVEN,CRTC2->DAC*/
|
||||
case DS_CRTC1MAVEN_CRTC2DAC:
|
||||
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x2); /*external clk*/
|
||||
CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x1<<20)); /*internal clk*/
|
||||
VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)|0x88));
|
||||
DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x02);
|
||||
break;
|
||||
case DS_CRTCDAC_CRTC2DAC2:
|
||||
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); /*internal clk*/
|
||||
CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x1<<20)); /*internal clk - gets DAC*/
|
||||
//FIXME VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0x77));
|
||||
//FIXME DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x82);
|
||||
break;
|
||||
case DS_CRTCDAC_CRTCDAC2:
|
||||
case DS_CRTC1CON1_CRTC2CON2:
|
||||
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); /*internal clk*/
|
||||
CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x0<<20)); /*internal clk - no DAC PTR*/
|
||||
DXIW(OUTPUTCONN,0x09);
|
||||
break;
|
||||
case DS_CRTC1CON2_CRTC2CON1:
|
||||
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); /*internal clk*/
|
||||
CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x1<<20)); /*internal clk - gets DAC*/
|
||||
DXIW(OUTPUTCONN,0x05);
|
||||
break;
|
||||
default:
|
||||
return B_ERROR;
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
/*
|
||||
* i2c interface for the G400 MAVEN under BeOS
|
||||
* Mark Watson 06/2000
|
||||
* i2c interface for the G400 MAVEN under BeOS
|
||||
*
|
||||
* Provides I2CR,I2CW - functions to parallel DACW,DACR
|
||||
* Bus is run slowly because I do not know how fast the MAVEN is!
|
||||
* Provides I2CR,I2CW - functions to parallel DACW,DACR
|
||||
* Bus should be run at max. 100kHz: see original Philips I2C specification
|
||||
*
|
||||
* Much help was provided by observing the Linux i2c code,
|
||||
* so thanks go to: Gerd Knorr
|
||||
* Much help was provided by observing the Linux i2c code,
|
||||
* so thanks go to: Gerd Knorr
|
||||
*
|
||||
* Other authors:
|
||||
* Mark Watson 6/2000,
|
||||
* Rudolf Cornelissen 12/2002
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00004000
|
||||
|
||||
#include "mga_std.h"
|
||||
@@ -19,6 +23,48 @@
|
||||
#define I2C_CLOCK 0x20
|
||||
#define I2C_DATA 0x10
|
||||
|
||||
/* MGA-TVO I2C for G200, G400 */
|
||||
#define I2C_CLOCK 0x20
|
||||
#define I2C_DATA 0x10
|
||||
/* primary head DDC for Mystique(?), G100, G200, G400 */
|
||||
#define DDC1_CLK 0x08
|
||||
#define DDC1_DATA 0x02
|
||||
/* primary head DDC for Millennium, Millennium II */
|
||||
#define DDC1B_CLK 0x10
|
||||
#define DDC1B_DATA 0x04
|
||||
/* secondary head DDC for G400, G450 and G550 */
|
||||
#define DDC2_CLK 0x04
|
||||
#define DDC2_DATA 0x01
|
||||
|
||||
status_t i2c_sec_tv_adapter()
|
||||
{
|
||||
status_t result = B_ERROR;
|
||||
|
||||
/* The secondary DDC channel only exist on dualhead cards */
|
||||
if (!si->ps.secondary_head) return result;
|
||||
|
||||
/* make sure the output lines will be active-low when enabled
|
||||
* (they will be pulled 'passive-high' when disabled) */
|
||||
DXIW(GENIODATA,0x00);
|
||||
/* send out B_STOP condition on secondary head DDC channel and use it to
|
||||
* check for 'shortcut', indicating the Matrox VGA->TV adapter is connected */
|
||||
|
||||
/* make sure SDA is low */
|
||||
DXIW(GENIOCTRL, (DXIR(GENIOCTRL) | DDC2_DATA));
|
||||
snooze(2);
|
||||
/* make sure SCL should be high */
|
||||
DXIW(GENIOCTRL, (DXIR(GENIOCTRL) & ~DDC2_CLK));
|
||||
snooze(2);
|
||||
/* if SCL is low then the bus is blocked by a TV adapter */
|
||||
if (!(DXIR(GENIODATA) & DDC2_CLK)) result = B_OK;
|
||||
snooze(5);
|
||||
/* set SDA while SCL should be set (generates actual bus-stop condition) */
|
||||
DXIW(GENIOCTRL, (DXIR(GENIOCTRL) & ~DDC2_DATA));
|
||||
snooze(5);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*-----------------------------
|
||||
*low level hardware access
|
||||
*/
|
||||
|
||||
@@ -2,254 +2,13 @@
|
||||
/* some bits are hacks, where PINS is not known */
|
||||
/* Authors:
|
||||
Mark Watson 2/2000,
|
||||
Rudolf Cornelissen 10/2002
|
||||
Rudolf Cornelissen 10-11/2002
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00002000
|
||||
|
||||
#include "mga_std.h"
|
||||
|
||||
//general pins stuff!
|
||||
enum {
|
||||
id=0x00,
|
||||
length=0x02,
|
||||
version=0x04,
|
||||
location=0x7FFC
|
||||
};
|
||||
|
||||
//pins v5(!) (as used by G450)
|
||||
enum {
|
||||
p5_option=0x30,
|
||||
p5_option2=0x34,
|
||||
p5_memctl=0x3e,
|
||||
p5_option4=0x42,
|
||||
p5_memrd=0x46,
|
||||
p5_maccess=0x72
|
||||
};
|
||||
|
||||
//pins v4 (as used by G400)
|
||||
enum {
|
||||
p4_memtype=0x35,
|
||||
p4_memctl=0x3d,
|
||||
p4_memrd=0x56,
|
||||
p4_sdram=0x5c,
|
||||
};
|
||||
|
||||
//pins v3 (as used by G200/G100?)
|
||||
enum {
|
||||
p3_memtype=0x36,
|
||||
p3_memctl=0x30,
|
||||
p3_memrd=0x38,
|
||||
p3_sdram=0x34,
|
||||
p3_membuf=0x3a //G200 extra?
|
||||
};
|
||||
|
||||
static void dump_card_infos (void)
|
||||
{
|
||||
MSG(("g200_card_info:Memory control word: 0x%08x\n",si->ps.mem_ctl));
|
||||
if (si->ps.sdram) MSG(("g200_card_info:is SDRAM card: 1\n"));
|
||||
else MSG(("g200_card_info:is SDRAM card: 0\n"));
|
||||
MSG(("g200_card_info:Memory config: 0x%08x\n",si->ps.mem_type));
|
||||
MSG(("g200_card_info:MEMRDBK setting: 0x%08x\n",si->ps.mem_rd));
|
||||
MSG(("g200_card_info:Membuftype: 0x%08x\n",si->ps.membuf));
|
||||
MSG(("g200_card_info:mem_rfhcnt: %d\n", si->ps.mem_rfhcnt));
|
||||
}
|
||||
|
||||
/*word out card specific information - using PINS where possible (if not substitute sensible defaults)*/
|
||||
status_t g200_card_info()
|
||||
{
|
||||
uint8 * rom;
|
||||
uint8 * pins;
|
||||
int i;
|
||||
int chksum = 0;
|
||||
|
||||
/*check the validity of PINS*/
|
||||
LOG(4,("g200_card_info: Reading PINS info\n"));
|
||||
rom = (uint8 *) si->rom_mirror;
|
||||
|
||||
//check sig
|
||||
if (rom[0]!=0x55 || rom[1]!=0xaa)
|
||||
{
|
||||
LOG(8,("g200_card_info:BIOS bad signiture: 0x%02x%02x, expected 0x55aa\n",rom[0],rom[1]));
|
||||
}
|
||||
LOG(2,("g200_card_info: BIOS signiture $AA55 found OK\n"));
|
||||
pins = rom + (rom[location]|(rom[location+1]<<8));
|
||||
LOG(2,("g200_card_info: Using PINS v%d.%d structure at 0x%04x\n",pins[version+1],pins[version],pins-rom));
|
||||
//check valid
|
||||
for (i=0;i<pins[length];i++)
|
||||
{
|
||||
chksum+=pins[i];
|
||||
}
|
||||
if(chksum%256)
|
||||
{
|
||||
si->ps.mem_ctl=0x4244ca1;
|
||||
si->ps.mem_type=(4<<10)|(0<<14); //SDRAM memory config 4
|
||||
si->ps.mem_rd=0x108;
|
||||
si->ps.membuf=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(2,("INFO:PINS checksum is correct - grabbing PINS values\n"));
|
||||
|
||||
/*read memory control word*/
|
||||
si->ps.mem_ctl=*((uint32 *)(pins + p3_memctl));
|
||||
|
||||
/*read memory config*/
|
||||
si->ps.mem_type=(pins[p3_memtype]&0x7)<<10;
|
||||
if (!si->ps.sdram) si->ps.mem_type|= (0x01<<14);
|
||||
|
||||
/*figure out memrdbk settings*/
|
||||
si->ps.mem_rd=((pins[p3_memrd+1]&0xf0)>>3)<<24|((pins[p3_memrd+1]&0x03)>>2)<<16; //FIXME - ROR
|
||||
si->ps.mem_rd|=((pins[p3_memrd]&0xf0)<<1)|(pins[p3_memrd]&0x0f);
|
||||
|
||||
//memory buffer type setting
|
||||
si->ps.membuf=pins[p3_membuf]&0x3;
|
||||
}
|
||||
|
||||
/*FIXME hardcode a few required values, i.e. ones not found in PINS*/
|
||||
/*memory refresh settings (values pinched from windows)*/
|
||||
si->ps.mem_rfhcnt=0x78000>>15;
|
||||
|
||||
if (si->settings.logmask & 0x80000000) dump_card_infos();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*word out card specific information - using PINS where possible (if not substitute sensible defaults)*/
|
||||
status_t g400_card_info()
|
||||
{
|
||||
uint8 * rom;
|
||||
uint8 * pins;
|
||||
int i;
|
||||
int chksum = 0;
|
||||
|
||||
LOG(4,("INFO:Getting G400 card info\n"));
|
||||
/*check the validity of PINS*/
|
||||
LOG(2,("INFO:Reading PINS info\n"));
|
||||
rom = (uint8 *) si->rom_mirror;
|
||||
//check sig
|
||||
if (rom[0]!=0x55 || rom[1]!=0xaa)
|
||||
{
|
||||
LOG(8,("INFO:BIOS signiture not found\n"));
|
||||
}
|
||||
LOG(2,("INFO:BIOS signiture $AA55 found OK\n"));
|
||||
pins = rom + (rom[location]|(rom[location+1]<<8));
|
||||
LOG(2,("INFO:Using PINS v%d.%d structure at: %x\n",pins[version+1],pins[version],pins-rom));
|
||||
//check valid
|
||||
for (i=0;i<pins[length];i++)
|
||||
{
|
||||
chksum+=pins[i];
|
||||
}
|
||||
|
||||
if((chksum%256)) //if pins is invalid make up some stuff
|
||||
{
|
||||
LOG(8,("INFO:PINS checksum is incorrect - using default values\n"));
|
||||
LOG(8,("INFO:AFAIK these should work with most G400s, but they are untested\n"));
|
||||
si->ps.mem_ctl=0x24045491;
|
||||
si->ps.mem_type=1<<14; //SDRAM memory config 0
|
||||
si->ps.mem_rd=0x108;
|
||||
si->ps.sdram=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(2,("INFO:PINS checksum is correct - grabbing PINS values\n"));
|
||||
|
||||
/*read memory control word*/
|
||||
si->ps.mem_ctl=*((uint32 *)(pins + p4_memctl));
|
||||
LOG(2,("INFO:Memory control word: %x\n",si->ps.mem_ctl));
|
||||
|
||||
/*read memory config*/
|
||||
si->ps.sdram = (pins[p4_sdram]&0x10);
|
||||
si->ps.mem_type=(pins[p4_memtype]&0x38)<<7;
|
||||
if (!si->ps.sdram) si->ps.mem_type |= (0x01 << 14);
|
||||
LOG(2,("INFO:Memory config: %x\n",si->ps.mem_type));
|
||||
|
||||
/*figure out memrdbk settings*/
|
||||
si->ps.mem_rd=((pins[p4_memrd+1]&0xf0)>>3)<<24|((pins[p4_memrd+1]&0x03)>>2)<<16; //FIXME - ROR
|
||||
si->ps.mem_rd|=((pins[p4_memrd]&0xf0)<<1)|(pins[p4_memrd]&0x0f);
|
||||
LOG(2,("INFO:MEMRDBK setting: %x\n",si->ps.mem_rd));
|
||||
|
||||
/*figure out if it is a G400MAX*/
|
||||
/*FIXME, use the correct ID method!*/
|
||||
if (si->ps.mem_ctl==0x20049911)
|
||||
{
|
||||
LOG(2,("INFO:MAX\n"));
|
||||
si->ps.card_type=G400MAX;
|
||||
}
|
||||
}
|
||||
|
||||
/*FIXME hardcode a few required values, i.e. ones not found in PINS*/
|
||||
/*memory refresh settings (values pinched from windows)*/
|
||||
if (si->ps.card_type==G400)
|
||||
{
|
||||
si->ps.mem_rfhcnt=0x27;
|
||||
}
|
||||
else if (si->ps.card_type==G400MAX)
|
||||
{
|
||||
si->ps.mem_rfhcnt=0x2e;
|
||||
}
|
||||
if (si->settings.logmask & 0x80000000) dump_card_infos();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*word out card specific information - using PINS where possible (if not substitute sensible defaults)*/
|
||||
status_t g450_card_info()
|
||||
{
|
||||
uint8 * rom;
|
||||
uint8 * pins;
|
||||
int i;
|
||||
int chksum = 0;
|
||||
|
||||
LOG(4,("INFO:Getting G450 card info\n"));
|
||||
/*check the validity of PINS*/
|
||||
LOG(2,("INFO:Reading PINS info\n"));
|
||||
rom = (uint8 *) si->rom_mirror;
|
||||
//check sig
|
||||
if (rom[0]!=0x55 || rom[1]!=0xaa)
|
||||
{
|
||||
LOG(8,("INFO:BIOS signiture not found\n"));
|
||||
}
|
||||
LOG(2,("INFO:BIOS signiture $AA55 found OK\n"));
|
||||
pins = rom + (rom[location]|(rom[location+1]<<8));
|
||||
LOG(2,("INFO:Using PINS v%d.%d structure at: %x\n",pins[version+1],pins[version],pins-rom));
|
||||
//check valid
|
||||
for (i=0;i<pins[length];i++)
|
||||
{
|
||||
chksum+=pins[i];
|
||||
}
|
||||
|
||||
if((chksum%256)) //if pins is invalid make up some stuff
|
||||
{
|
||||
LOG(8,("INFO:PINS checksum is incorrect - using default values\n"));
|
||||
LOG(8,("INFO:AFAIK these should work with most G450s, but they are untested\n"));
|
||||
//FIXME
|
||||
si->ps.mem_ctl=0x24045491;
|
||||
si->ps.mem_type=1<<14; //SDRAM memory config 0
|
||||
si->ps.mem_rd=0x108;
|
||||
si->ps.sdram=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(2,("INFO:PINS checksum is correct - grabbing PINS values\n"));
|
||||
|
||||
/*read memory control word*/
|
||||
si->ps.mem_ctl=*((uint32 *)(pins + p5_memctl));
|
||||
LOG(2,("INFO:Memory control word: %x\n",si->ps.mem_ctl));
|
||||
|
||||
/*read useful registers*/
|
||||
si->ps.option=*((uint32 *)(pins + p5_option));
|
||||
si->ps.option2=*((uint32 *)(pins + p5_option2));
|
||||
si->ps.option4=*((uint32 *)(pins + p5_option4));
|
||||
si->ps.maccess=*((uint32 *)(pins + p5_maccess));
|
||||
|
||||
/*figure out memrdbk settings*/
|
||||
si->ps.mem_rd=*((uint32 *)(pins + p5_memrd));
|
||||
}
|
||||
|
||||
if (si->settings.logmask & 0x80000000) dump_card_infos();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* Parse the BIOS PINS structure if there */
|
||||
status_t parse_pins ()
|
||||
{
|
||||
@@ -380,9 +139,15 @@ status_t pins1_read(uint8 *pins, uint8 length)
|
||||
// bool secondary_dvi;
|
||||
// uint32 memory_size; /* memory in Mb */
|
||||
// uint32 mctlwtst_reg; /* memory control waitstate register */
|
||||
// uint32 memrdbk_reg; /* memory readback register */
|
||||
// uint32 option_reg; /* option register */
|
||||
// uint32 option2_reg; /* option2 register */
|
||||
// uint32 option3_reg; /* option3 register */
|
||||
// uint32 option4_reg; /* option4 register */
|
||||
// uint8 v3_option2_reg;
|
||||
// uint8 v3_clk_div; /* pins v3 memory and system clock division factors */
|
||||
// uint8 v3_mem_type; /* pins v3 memory type info */
|
||||
// uint16 v5_mem_type; /* pins v5 memory type info */
|
||||
// bool sdram;
|
||||
//end remove later on here.
|
||||
|
||||
@@ -421,10 +186,18 @@ status_t pins3_read(uint8 *pins, uint8 length)
|
||||
if (pins [45] < si->ps.std_engine_clock) si->ps.std_engine_clock = pins[45];
|
||||
if (pins [46] < si->ps.std_engine_clock) si->ps.std_engine_clock = pins[46];
|
||||
if (pins [47] < si->ps.std_engine_clock) si->ps.std_engine_clock = pins[47];
|
||||
if (pins[52] & 0x01)
|
||||
si->ps.std_engine_clock *= 3;
|
||||
if ((si->ps.card_type == G200) && (pins[58] & 0x04))
|
||||
{
|
||||
/* G200 can work without divisor */
|
||||
si->ps.std_engine_clock *= 1;
|
||||
}
|
||||
else
|
||||
si->ps.std_engine_clock *= 2;
|
||||
{
|
||||
if (pins[52] & 0x01)
|
||||
si->ps.std_engine_clock *= 3;
|
||||
else
|
||||
si->ps.std_engine_clock *= 2;
|
||||
}
|
||||
|
||||
if (pins[52] & 0x20) si->ps.f_ref = 14.31818;
|
||||
else si->ps.f_ref = 27.00000;
|
||||
@@ -433,29 +206,43 @@ status_t pins3_read(uint8 *pins, uint8 length)
|
||||
si->ps.memory_size = 2 << ((pins[55] & 0xc0) >> 6);
|
||||
/* more memory specifics */
|
||||
si->ps.mctlwtst_reg = (pins[51] << 24) | (pins[50] << 16) | (pins[49] << 8) | pins [48];
|
||||
si->ps.memrdbk_reg =
|
||||
(pins[56] & 0x0f) | ((pins[56] & 0xf0) << 1) | ((pins[57] & 0x03) << 22) | ((pins[57] & 0xf0) << 21);
|
||||
/* Mark did this as one step in the above stuff, which must be wrong:
|
||||
((pins[p3_memrd+1]&0x03)>>2)<<16; //FIXME - ROR */
|
||||
|
||||
si->ps.v3_clk_div = pins[52];
|
||||
si->ps.v3_mem_type = pins[54];
|
||||
si->ps.v3_option2_reg = pins[58];
|
||||
|
||||
/* for cards using this version of PINS both functions are in maven */
|
||||
si->ps.secondary_head = !(pins[59] & 0x01);
|
||||
si->ps.secondary_tvout = !(pins[59] & 0x01);
|
||||
|
||||
/* setup via gathered info from pins with some fixed values added which are not in pins */
|
||||
/* setup via gathered info from pins */
|
||||
si->ps.option_reg = 0;
|
||||
/* calculate refresh timer info-bits for 15uS interval (or shorter). See G100/G200 specs */
|
||||
/* calculate std memory clock period (nS) */
|
||||
if (pins[52] & 0x02)
|
||||
/* only used on G200, not on G100 */
|
||||
mclk_period = 3000.0 / si->ps.std_engine_clock;
|
||||
if ((si->ps.card_type == G200) && (pins[58] & 0x08))
|
||||
{
|
||||
/* G200 can work without Mclk divisor */
|
||||
mclk_period = 1000.0 / si->ps.std_engine_clock;
|
||||
}
|
||||
else
|
||||
mclk_period = 2000.0 / si->ps.std_engine_clock;
|
||||
{
|
||||
if (pins[52] & 0x02)
|
||||
/* this factor is only used on G200, not on G100 */
|
||||
mclk_period = 3000.0 / si->ps.std_engine_clock;
|
||||
else
|
||||
mclk_period = 2000.0 / si->ps.std_engine_clock;
|
||||
}
|
||||
/* calculate needed setting, 'round-down' result! */
|
||||
rfhcnt = (uint32)(((15000 / mclk_period) - 1) / 64);
|
||||
/* check for register limit */
|
||||
if (rfhcnt > 0x3f) rfhcnt = 0x3f;
|
||||
/* add to option register */
|
||||
si->ps.option_reg |= (rfhcnt << 15);
|
||||
/* the rest of the OPTION info currently comes via 'v3_clk_div' and 'v3_mem_type'. */
|
||||
/* the rest of the OPTION info for pins v3 comes via 'v3_clk_div' and 'v3_mem_type'. */
|
||||
|
||||
/* assuming the only possible panellink will be on the first head */
|
||||
si->ps.primary_dvi = !(pins[59] & 0x40);
|
||||
@@ -482,12 +269,22 @@ status_t pins3_read(uint8 *pins, uint8 length)
|
||||
si->ps.max_dac2_clock_16 = 136;
|
||||
si->ps.max_dac2_clock_32dh = 136;
|
||||
si->ps.max_dac2_clock_32 = 136;
|
||||
|
||||
/* not used here: */
|
||||
si->ps.option2_reg = 0;
|
||||
si->ps.option3_reg = 0;
|
||||
si->ps.option4_reg = 0;
|
||||
si->ps.v5_mem_type = 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* pins v4 is used by G400 */
|
||||
/* pins v4 is used by G400 and G400MAX */
|
||||
status_t pins4_read(uint8 *pins, uint8 length)
|
||||
{
|
||||
/* used to calculate RAM refreshrate */
|
||||
float mclk_period;
|
||||
uint32 rfhcnt;
|
||||
|
||||
if (length != 128)
|
||||
{
|
||||
LOG(8,("INFO: wrong PINS length, expected 128, got %d\n", length));
|
||||
@@ -526,6 +323,51 @@ status_t pins4_read(uint8 *pins, uint8 length)
|
||||
else si->ps.f_ref = 27.00000;
|
||||
|
||||
si->ps.memory_size = 4 << ((pins[92] >> 2) & 0x03);
|
||||
/* more memory specifics */
|
||||
si->ps.mctlwtst_reg = (pins[74] << 24) | (pins[73] << 16) | (pins[72] << 8) | pins [71];
|
||||
si->ps.option3_reg = (pins[70] << 24) | (pins[69] << 16) | (pins[68] << 8) | pins [67];
|
||||
/* mrsopcod field, msb is always zero.. */
|
||||
si->ps.memrdbk_reg =
|
||||
(pins[86] & 0x0f) | ((pins[86] & 0xf0) << 1) | ((pins[87] & 0x03) << 22) | ((pins[87] & 0xf0) << 21);
|
||||
si->ps.sdram = (pins[92] & 0x10);
|
||||
|
||||
/* setup via gathered info from pins */
|
||||
si->ps.option_reg = ((pins[53] & 0x38) << 7) | ((pins[53] & 0x40) << 22) | ((pins[53] & 0x80) << 15);
|
||||
/* calculate refresh timer info-bits for 15uS interval (or shorter). See G400 specs;
|
||||
* the 15uS value was confirmed by Mark Watson for both G400 and G400MAX */
|
||||
/* calculate std memory clock period (nS) */
|
||||
switch ((si->ps.option3_reg & 0x0000e000) >> 13)
|
||||
{
|
||||
case 0:
|
||||
mclk_period = 3000.0 / (si->ps.std_engine_clock * 1);
|
||||
break;
|
||||
case 1:
|
||||
mclk_period = 5000.0 / (si->ps.std_engine_clock * 2);
|
||||
break;
|
||||
case 2:
|
||||
mclk_period = 9000.0 / (si->ps.std_engine_clock * 4);
|
||||
break;
|
||||
case 3:
|
||||
mclk_period = 2000.0 / (si->ps.std_engine_clock * 1);
|
||||
break;
|
||||
case 4:
|
||||
mclk_period = 3000.0 / (si->ps.std_engine_clock * 2);
|
||||
break;
|
||||
case 5:
|
||||
mclk_period = 1000.0 / (si->ps.std_engine_clock * 1);
|
||||
break;
|
||||
default:
|
||||
/* we choose the lowest refreshcount that could be needed (so assuming slowest clocked memory) */
|
||||
mclk_period = 3000.0 / (si->ps.std_engine_clock * 1);
|
||||
LOG(8,("INFO: undefined/unknown memory clock divider select, using failsafe for refresh\n"));
|
||||
break;
|
||||
}
|
||||
/* calculate needed setting, 'round-down' result! */
|
||||
rfhcnt = (uint32)(((15000 / mclk_period) - 1) / 64);
|
||||
/* check for register limit */
|
||||
if (rfhcnt > 0x3f) rfhcnt = 0x3f;
|
||||
/* add to option register */
|
||||
si->ps.option_reg |= (rfhcnt << 15);
|
||||
|
||||
/* for cards using this version of PINS both functions are in maven */
|
||||
si->ps.secondary_head = !(pins[91] & 0x01);
|
||||
@@ -552,14 +394,21 @@ status_t pins4_read(uint8 *pins, uint8 length)
|
||||
si->ps.max_video_vco = si->ps.max_pixel_vco;
|
||||
si->ps.min_video_vco = 50;
|
||||
|
||||
//todo:
|
||||
// uint32 mctlwtst_reg;
|
||||
// uint32 option_reg;
|
||||
// bool sdram;
|
||||
|
||||
/* not used here: */
|
||||
si->ps.option2_reg = 0;
|
||||
si->ps.option4_reg = 0;
|
||||
si->ps.v3_option2_reg = 0;
|
||||
si->ps.v3_clk_div = 0;
|
||||
si->ps.v3_mem_type = 0;
|
||||
si->ps.v5_mem_type = 0;
|
||||
|
||||
/* check for a G400MAX card */
|
||||
/* fixme: use the PCI configspace ID method if it exists... */
|
||||
if (si->ps.max_dac1_clock > 300)
|
||||
{
|
||||
si->ps.card_type = G400MAX;
|
||||
LOG(2,("INFO: G400MAX detected\n"));
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -624,13 +473,27 @@ status_t pins5_read(uint8 *pins, uint8 length)
|
||||
si->ps.memory_size = ((pins[114] & 0x03) + 1) * 8;
|
||||
if ((pins[114] & 0x07) > 3)
|
||||
{
|
||||
LOG(2,("INFO: unknown RAM size, defaulting to 8Mb\n"));
|
||||
LOG(8,("INFO: unknown RAM size, defaulting to 8Mb\n"));
|
||||
si->ps.memory_size = 8;
|
||||
}
|
||||
|
||||
if (pins[110] & 0x01) si->ps.f_ref = 14.31818;
|
||||
else si->ps.f_ref = 27.00000;
|
||||
|
||||
/* make sure SGRAM functions only get enabled if SGRAM mounted */
|
||||
if ((pins[114] & 0x18) == 0x08) si->ps.sdram = false;
|
||||
else si->ps.sdram = true;
|
||||
/* more memory specifics */
|
||||
si->ps.v5_mem_type = (pins[115] << 8) | pins [114];
|
||||
|
||||
/* various registers */
|
||||
si->ps.option_reg = (pins[51] << 24) | (pins[50] << 16) | (pins[49] << 8) | pins [48];
|
||||
si->ps.option2_reg = (pins[55] << 24) | (pins[54] << 16) | (pins[53] << 8) | pins [52];
|
||||
si->ps.option3_reg = (pins[79] << 24) | (pins[78] << 16) | (pins[77] << 8) | pins [76];
|
||||
si->ps.option4_reg = (pins[87] << 24) | (pins[86] << 16) | (pins[85] << 8) | pins [84];
|
||||
si->ps.mctlwtst_reg = (pins[83] << 24) | (pins[82] << 16) | (pins[81] << 8) | pins [80];
|
||||
si->ps.memrdbk_reg = (pins[91] << 24) | (pins[90] << 16) | (pins[89] << 8) | pins [88];
|
||||
|
||||
si->ps.secondary_head = (pins[117] & 0x70);
|
||||
si->ps.secondary_tvout = (pins[117] & 0x40);
|
||||
si->ps.primary_dvi = (pins[117] & 0x02);
|
||||
@@ -640,12 +503,8 @@ status_t pins5_read(uint8 *pins, uint8 length)
|
||||
si->ps.max_dac2_clock_8 = 0;
|
||||
si->ps.max_dac2_clock_24 = 0;
|
||||
|
||||
//todo:
|
||||
// uint32 mctlwtst_reg;
|
||||
// uint32 option_reg;
|
||||
// bool sdram;
|
||||
|
||||
/* not used here: */
|
||||
si->ps.v3_option2_reg = 0;
|
||||
si->ps.v3_clk_div = 0;
|
||||
si->ps.v3_mem_type = 0;
|
||||
return B_OK;
|
||||
@@ -697,9 +556,15 @@ void fake_pins(void)
|
||||
si->ps.std_engine_clock = 0;
|
||||
si->ps.std_engine_clock_dh = 0;
|
||||
si->ps.mctlwtst_reg = 0;
|
||||
si->ps.memrdbk_reg = 0;
|
||||
si->ps.option_reg = 0;
|
||||
si->ps.option2_reg = 0;
|
||||
si->ps.option3_reg = 0;
|
||||
si->ps.option4_reg = 0;
|
||||
si->ps.v3_option2_reg = 0;
|
||||
si->ps.v3_clk_div = 0;
|
||||
si->ps.v3_mem_type = 0;
|
||||
si->ps.v5_mem_type = 0;
|
||||
}
|
||||
|
||||
void pinsmil2_fake(void)
|
||||
@@ -743,6 +608,7 @@ void pinsg100_fake(void)
|
||||
/* presume 2Mb RAM mounted */
|
||||
si->ps.memory_size = 2;
|
||||
//fixme: should be overrule-able via mga.settings for G100.
|
||||
//fail-safe mode for now:
|
||||
si->ps.sdram = true;
|
||||
}
|
||||
|
||||
@@ -823,11 +689,10 @@ void pinsg400_fake(void)
|
||||
/* presume 4Mb RAM mounted */
|
||||
si->ps.memory_size = 4;
|
||||
/* ask the G400 what type of RAM it has been set to by it's BIOS */
|
||||
//todo:
|
||||
// si->ps.sdram = !(CFGR(OPTION) & 0x00004000);
|
||||
//end todo.
|
||||
si->ps.sdram = !(CFGR(OPTION) & 0x00004000);
|
||||
}
|
||||
|
||||
/* this routine is currently unused, because G400MAX is detected via pins! */
|
||||
void pinsg400max_fake(void)
|
||||
{
|
||||
/* 'worst case' scenario defaults, overrule-able via mga.settings if needed */
|
||||
@@ -865,8 +730,7 @@ void pinsg400max_fake(void)
|
||||
/* presume 4Mb RAM mounted */
|
||||
si->ps.memory_size = 4;
|
||||
/* ask the G400MAX what type of RAM it has been set to by it's BIOS */
|
||||
//todo:
|
||||
// si->ps.sdram = !(CFGR(OPTION) & 0x00004000);
|
||||
si->ps.sdram = !(CFGR(OPTION) & 0x00004000);
|
||||
}
|
||||
|
||||
void pinsg450_fake(void)
|
||||
@@ -906,6 +770,8 @@ void pinsg450_fake(void)
|
||||
/* ask the G450 what type of RAM it has been set to by it's BIOS */
|
||||
//todo:
|
||||
// si->ps.sdram = !(CFGR(OPTION) & 0x00004000);
|
||||
//fail-safe mode for now:
|
||||
si->ps.sdram = true;
|
||||
}
|
||||
|
||||
void pinsg550_fake(void)
|
||||
@@ -945,6 +811,8 @@ void pinsg550_fake(void)
|
||||
/* ask the G550 what type of RAM it has been set to by it's BIOS */
|
||||
//todo:
|
||||
// si->ps.sdram = !(CFGR(OPTION) & 0x00004000);
|
||||
//fail-safe mode for now:
|
||||
si->ps.sdram = true;
|
||||
}
|
||||
|
||||
void dump_pins(void)
|
||||
@@ -981,9 +849,15 @@ void dump_pins(void)
|
||||
if (si->ps.secondary_dvi) LOG(2,("present\n")); else LOG(2,("absent\n"));
|
||||
LOG(2,("card memory_size: %dMb\n", si->ps.memory_size));
|
||||
LOG(2,("mctlwtst register: $%08x\n", si->ps.mctlwtst_reg));
|
||||
LOG(2,("memrdbk register: $%08x\n", si->ps.memrdbk_reg));
|
||||
LOG(2,("option register: $%08x\n", si->ps.option_reg));
|
||||
LOG(2,("option2 register: $%08x\n", si->ps.option2_reg));
|
||||
LOG(2,("option3 register: $%08x\n", si->ps.option3_reg));
|
||||
LOG(2,("option4 register: $%08x\n", si->ps.option4_reg));
|
||||
LOG(2,("v3_option2_reg: $%02x\n", si->ps.v3_option2_reg));
|
||||
LOG(2,("v3_clock_div: $%02x\n", si->ps.v3_clk_div));
|
||||
LOG(2,("v3_mem_type: $%02x\n", si->ps.v3_mem_type));
|
||||
LOG(2,("v5_mem_type: $%04x\n", si->ps.v5_mem_type));
|
||||
LOG(2,("sdram: "));
|
||||
if (si->ps.sdram) LOG(2,("SDRAM card\n")); else LOG(2,("SGRAM card\n"));
|
||||
LOG(2,("INFO: end pinsdump.\n"));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*general card functions*/
|
||||
status_t gx00_general_powerup();
|
||||
status_t mga_set_cas_latency();
|
||||
status_t gx50_general_output_select();
|
||||
status_t gx00_general_dac_select(int);
|
||||
status_t gx00_general_wait_retrace();
|
||||
//status_t gx00_general_bios_to_powergraphics();
|
||||
@@ -27,9 +28,6 @@ status_t i2c_maven_probe(void);
|
||||
|
||||
|
||||
/*card info functions*/
|
||||
status_t g450_card_info();
|
||||
status_t g400_card_info();
|
||||
status_t g200_card_info();
|
||||
status_t parse_pins(void);
|
||||
status_t pins1_read(uint8 *pins, uint8 length);
|
||||
status_t pins2_read(uint8 *pins, uint8 length);
|
||||
@@ -53,6 +51,7 @@ status_t gx00_dac_palette(uint8*,uint8*,uint8*);
|
||||
status_t gx00_dac_pix_pll_find(display_mode target,float * result,uint8 *,uint8 *,uint8 *, uint8);
|
||||
status_t gx00_dac_set_pix_pll(display_mode target);
|
||||
|
||||
status_t g450_dac_set_sys_pll();
|
||||
status_t g400_dac_set_sys_pll();
|
||||
status_t g200_dac_set_sys_pll();
|
||||
status_t g100_dac_set_sys_pll();
|
||||
@@ -123,9 +122,13 @@ status_t gx00_acc_wait_idle();
|
||||
|
||||
/*backend scaler functions*/
|
||||
status_t check_overlay_capability(uint32 feature);
|
||||
status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow, int offset);
|
||||
status_t gx00_configure_bes
|
||||
(const overlay_buffer *ob, const overlay_window *ow,const overlay_view *ov, int offset);
|
||||
status_t gx00_release_bes();
|
||||
|
||||
/* I2C functions */
|
||||
status_t i2c_sec_tv_adapter();
|
||||
|
||||
/*driver structures and enums*/
|
||||
enum{BPP8=0,BPP15=1,BPP16=2,BPP24=3,BPP32DIR=4,BPP32=7};
|
||||
enum{DS_CRTCDAC_CRTC2MAVEN, DS_CRTCMAVEN_CRTC2DAC, DS_CRTCDAC_CRTC2DAC2, DS_CRTCDAC_CRTCDAC2};
|
||||
enum{DS_CRTC1DAC_CRTC2MAVEN, DS_CRTC1MAVEN_CRTC2DAC, DS_CRTC1CON1_CRTC2CON2, DS_CRTC1CON2_CRTC2CON1};
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
#accelerant "mga.accelerant"
|
||||
|
||||
# mga.accelerant parameters
|
||||
usebios true # if true rely on bios to coldstart the card instead of by the driver
|
||||
# currently also: if false use BIOS PINS config info, otherwise just guess...
|
||||
usebios false # if true rely on bios to coldstart the card instead of driver
|
||||
#memory 2 # in MB, override builtin memory size detection
|
||||
hardcursor true # if true use on-chip cursor capabilities
|
||||
hardcursor false # if true use on-chip cursor capabilities
|
||||
#logmask 0x00000000 # nothing logged, except errors, is default
|
||||
#logmask 0x80000000 # log card physical features
|
||||
#logmask 0x80000000 # log following mask
|
||||
|
||||
Reference in New Issue
Block a user