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:
shatty
2003-12-02 21:54:44 +00:00
parent 81843775eb
commit f36d53a4a0
14 changed files with 1460 additions and 956 deletions
@@ -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 */
+10 -2
View File
@@ -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;
}
+2 -21
View File
@@ -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;
}
+158 -38
View File
@@ -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();
+19 -19
View File
@@ -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;
}
+279 -224
View File
@@ -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;
+115 -38
View File
@@ -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*/
+323 -88
View File
@@ -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
*/
+142 -268
View File
@@ -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