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) switch(si->ps.card_type)
{ {
case G200: case G200:
case G400: /* is also G400MAX in accelerant for now? */ case G400:
case G400MAX: /* not used in accelerant yet? */ case G400MAX:
case G450: /* is also G550 in accelerant for now */ case G450: /* is also G550 in accelerant for now */
case G550: /* not used in accelerant yet */ case G550: /* not used in accelerant yet */
/* export video overlay functions */ /* export video overlay functions */
+10 -2
View File
@@ -4,7 +4,7 @@
Other authors: Other authors:
Mark Watson Mark Watson
Rudolf Cornelissen 9/2002 Rudolf Cornelissen 9-11/2002
*/ */
#define MODULE_BIT 0x02000000 #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) status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high)
{ {
uint32 max_pclk = 0; uint32 max_pclk = 0;
uint32 min_pclk = 0;
/* check for NULL pointers */ /* check for NULL pointers */
if ((dm == NULL) || (low == NULL) || (high == NULL)) return B_ERROR; 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 */ /* return values in kHz */
*high = max_pclk * 1000; *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; 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: /* 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' * 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 #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" #include "acc_std.h"
/* define the supported overlay input colorspaces */ /* define the supported overlay input colorspaces */
@@ -591,11 +577,6 @@ status_t CONFIGURE_OVERLAY
{ {
int offset = 0; /* used for buffer index */ 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: ")); LOG(4,("Overlay: Configure_overlay called: "));
/* Note: /* Note:
@@ -649,7 +630,7 @@ status_t CONFIGURE_OVERLAY
{ {
LOG(4,("succesfull, switching to buffer %d\n", offset)); 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; return B_OK;
} }
+158 -38
View File
@@ -5,7 +5,7 @@
Other authors: Other authors:
Mark Watson, Mark Watson,
Apsed, Apsed,
Rudolf Cornelissen 10/2002 Rudolf Cornelissen 11-12/2002
*/ */
#define MODULE_BIT 0x00200000 #define MODULE_BIT 0x00200000
@@ -29,16 +29,6 @@ static void interrupt_enable(bool flag) {
result = ioctl(fd, GX00_RUN_INTERRUPTS, &sbs, sizeof(sbs)); 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)! */ /* 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) 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; uint8 colour_depth=32;
status_t result; status_t result;
uint32 startadd,startadd_right; uint32 startadd,startadd_right;
// double HIPRILVL;
// double Tmclk,Tpix,temp;
// apsed TODO startadd is 19 bits if < g200 // apsed TODO startadd is 19 bits if < g200
uint8 display,h,v; 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)); LOG(1,("DUALHEAD: %d\n",target.flags&DUALHEAD_BITS));
if ((target.flags&DUALHEAD_BITS)) /*if some dualhead mode*/ if ((target.flags&DUALHEAD_BITS)) /*if some dualhead mode*/
{ {
uint16 crtc1_vdisplay, crtc2_vdisplay;
/*set the pixel clock PLL(s)*/ /*set the pixel clock PLL(s)*/
if (gx00_dac_set_pix_pll(target)==B_ERROR) if (gx00_dac_set_pix_pll(target)==B_ERROR)
LOG(8,("SET: error setting pixel clock (internal DAC)\n")); 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")); 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) switch(target.space)
{ {
case B_RGB16_LITTLE: case B_RGB16_LITTLE:
colour_depth=16; 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); gx00_crtc_depth(BPP16);
g400_crtc2_depth(BPP16); g400_crtc2_depth(BPP16);
break; break;
case B_RGB32_LITTLE: case B_RGB32_LITTLE:
colour_depth=32; 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); gx00_crtc_depth(BPP32);
g400_crtc2_depth(BPP32DIR); g400_crtc2_depth(BPP32DIR);
break; break;
@@ -140,16 +131,130 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
/*work out where the "right" screen starts*/ /*work out where the "right" screen starts*/
startadd_right=startadd+(target.timing.h_display*(colour_depth>>3)); 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) switch (si->ps.card_type)
{ {
case G450: case G400:
gx00_general_dac_select(DS_CRTCDAC_CRTC2DAC2); case G400MAX:
switched_crtcs = false; 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; break;
case G400:case G400MAX: //fixme:
gx00_general_dac_select(DS_CRTCMAVEN_CRTC2DAC); //use current SETMODE MAVEN programming only on G400/G400MAX;
switched_crtcs = false; //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; break;
default: default:
break; break;
@@ -163,21 +268,17 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
} }
/*Tell card what memory to display*/ /*Tell card what memory to display*/
si->crtc_delay=17+4*(colour_depth==16);
switch (target.flags&DUALHEAD_BITS) switch (target.flags&DUALHEAD_BITS)
{ {
case DUALHEAD_ON: case DUALHEAD_ON:
gx00_crtc_set_display_start(startadd_right,colour_depth); case DUALHEAD_SWITCH:
g400_crtc2_set_display_start(startadd,colour_depth); gx00_crtc_set_display_start(startadd,colour_depth);
g400_crtc2_set_display_start(startadd_right,colour_depth);
break; break;
case DUALHEAD_CLONE: case DUALHEAD_CLONE:
gx00_crtc_set_display_start(startadd,colour_depth); gx00_crtc_set_display_start(startadd,colour_depth);
g400_crtc2_set_display_start(startadd,colour_depth); g400_crtc2_set_display_start(startadd,colour_depth);
break; 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*/ /*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_start,
target.timing.h_sync_end, target.timing.h_sync_end,
target.timing.h_total, 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_start,
target.timing.v_sync_end, target.timing.v_sync_end,
target.timing.v_total, 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_start,
target.timing.h_sync_end, target.timing.h_sync_end,
target.timing.h_total, target.timing.h_total,
(target.timing.v_display), crtc2_vdisplay,
target.timing.v_sync_start, target.timing.v_sync_start,
target.timing.v_sync_end, target.timing.v_sync_end,
target.timing.v_total, 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_start,
target.timing.h_sync_end, target.timing.h_sync_end,
target.timing.h_total, 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_start,
target.timing.v_sync_end, target.timing.v_sync_end,
target.timing.v_total, target.timing.v_total,
@@ -234,6 +335,7 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
/*TVout support*/ /*TVout support*/
if (si->ps.secondary_tvout && (target.flags&TV_BITS)) 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; si->crtc_delay+=5;
/*create a my tim(m)ing structure... for tvout*/ /*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) if (target.flags&TV_PAL)
{ {
LOG(2, ("OUTMODE: PAL\n")); LOG(2, ("OUTMODE: PAL\n"));
maven_set_mode(2); maven_set_mode(1);
} }
else else
{ {
LOG(2, ("OUTMODE: NTSC\n")); LOG(2, ("OUTMODE: NTSC\n"));
maven_set_mode(1); maven_set_mode(2);
} }
maven_out_compute(&tv_timing, &tv_regs); 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*/ /*tell the card what memory to display*/
gx00_crtc_set_display_start(startadd,colour_depth); gx00_crtc_set_display_start(startadd,colour_depth);
if (si->ps.card_type >= G100) /* enable primary analog output */
gx00_general_dac_select(DS_CRTCDAC_CRTC2MAVEN); 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*/ /*set the timing*/
result = gx00_crtc_set_timing /*crtc1*/ 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 */ /* enable interrupts using the kernel driver */
interrupt_enable(true); interrupt_enable(true);
/* optimize memory-access if needed */
gx00_crtc_mem_priority(colour_depth);
/* Tune RAM CAS-latency if needed. Must be done *here*! */ /* Tune RAM CAS-latency if needed. Must be done *here*! */
mga_set_cas_latency(); mga_set_cas_latency();
+19 -19
View File
@@ -1,7 +1,7 @@
/* MGA Acceleration functions */ /* MGA Acceleration functions */
/* Authors: /* Authors:
Mark Watson 2/2000, Mark Watson 2/2000,
Rudolf Cornelissen 10/2002 Rudolf Cornelissen 10-12/2002
*/ */
#define MODULE_BIT 0x00080000 #define MODULE_BIT 0x00080000
@@ -44,21 +44,20 @@ status_t gx00_acc_init()
{ {
ACCW(OPMODE,0); // cleanup bitblt ACCW(OPMODE,0); // cleanup bitblt
/*Set the Z origin to the start of FB (otherwise lockup on blits)*/ /* Set the Z origin to the start of FB (otherwise lockup on blits) */
if (si->ps.card_type>=G100) if (si->ps.card_type>=G100) ACCW(ZORG,0);
ACCW(ZORG,0);
/*MACCESS - for 2D, only pixel width is important > all others can be 0*/ /* Set pixel width */
switch(si->dm.space) switch(si->dm.space)
{ {
case B_CMAP8: case B_CMAP8:
ACCW(MACCESS,0); ACCW(MACCESS, ((ACCR(MACCESS) & 0xfffffffc) | 0x00));
break; break;
case B_RGB15_LITTLE:case B_RGB16_LITTLE: case B_RGB15_LITTLE:case B_RGB16_LITTLE:
ACCW(MACCESS,1); ACCW(MACCESS, ((ACCR(MACCESS) & 0xfffffffc) | 0x01));
break; break;
case B_RGB32_LITTLE:case B_RGBA32_LITTLE: case B_RGB32_LITTLE:case B_RGBA32_LITTLE:
ACCW(MACCESS,2); ACCW(MACCESS, ((ACCR(MACCESS) & 0xfffffffc) | 0x02));
break; break;
default: default:
LOG(8,("ACC: init, invalid bit depth\n")); 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 // ylin shall be 1 if 800x600
ACCW(PITCH, (1<<15) | (si->dm.virtual_width&0x0FFF)); ACCW(PITCH, (1<<15) | (si->dm.virtual_width&0x0FFF));
} }
/*PLNWT - plane write mask*/ /* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
// if (si->ps.card_type>=G200) // apsed: PLNWT exists also in MIL2, G100 ACCW(PLNWT,0x00000000);
ACCW(PLNWT,0xFFFFFFFF); /*all planes are written*/ ACCW(PLNWT,0xffffffff);
if (si->ps.card_type>=G200) { if (si->ps.card_type>=G200) {
/*DSTORG - location of active screen in framebuffer*/ /*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)); ACCW(SRCORG,(si->fbc.frame_buffer)-(si->framebuffer));
} }
/*YDSTORG - apsed, if not inited, BitBlts may fails on g200, see YTOP/BOT after */ /* init YDSTORG - apsed, if not inited, BitBlts may fails on g200 */
/* Used for G100, included in acceleration routines also: */
src_dst = 0; src_dst = 0;
ACCW(YDSTORG, src_dst); ACCW(YDSTORG, src_dst);
@@ -120,13 +118,15 @@ if ((si->ps.card_type==MIL2) && (si->dm.space==B_CMAP8)) {
} }
ACCW(YDSTORG,src_dst); ACCW(YDSTORG,src_dst);
/*clipping*/ /* clipping */
ACCW(CXBNDRY,((si->dm.virtual_width -1)<<16)|(0)); /*i.e. highest and lowest right pixel value*/ /* i.e. highest and lowest X pixel adresses */
ACCW(CXBNDRY,((si->dm.virtual_width - 1) << 16) | (0));
// apsed TODO g200 shall be YDSTORG + value /* Y pixel addresses must be linear */
// apsed TODO why -1, must be a multiple of 32 since MIl2 /* lowest adress */
ACCW(YTOP,0); ACCW(YTOP, 0 + src_dst);
ACCW(YBOT,(si->dm.virtual_height*si->dm.virtual_width)-1); /*y address must be linear*/ /* highest adress */
ACCW(YBOT,((si->dm.virtual_height - 1) * si->dm.virtual_width) + src_dst);
return B_OK; return B_OK;
} }
+279 -224
View File
@@ -1,26 +1,32 @@
/* G200-G550 Back End Scaler functions V0.13 beta1 */ /* G200-G550 Back End Scaler functions */
/* Written by Rudolf Cornelissen 05/08-2002 */ /* Written by Rudolf Cornelissen 05/11-2002 */
#define MODULE_BIT 0x00000200 #define MODULE_BIT 0x00000200
#include "mga_std.h" #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 */ /* yuy2 (4:2:2) colorspace calculations */
/* Note: Some calculations will have to be modified for other colorspaces if they are incorporated. */ /* Note: Some calculations will have to be modified for other colorspaces if they are incorporated. */
/* Note: /* 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->offset_xxx' is always 0, so not used;
* 'ow->width' and 'ow->height' are the output window size: does not change * 'ow->width' and 'ow->height' are the output window size: does not change
* if window is clipping; * if window is clipping;
* 'ow->h_start' and 'ow->v_start' are the left-top position of the output * '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 * window. These values can be negative: this means the window is clipping
* at the left or the top of the display, respectively. */ * 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 */ /* misc used variables */
uint32 temp32;
uint16 temp1, temp2; uint16 temp1, temp2;
/* interval representation, used for scaling calculations */ /* interval representation, used for scaling calculations */
uint16 intrep; uint16 intrep;
@@ -28,6 +34,8 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
uint32 ifactor; uint32 ifactor;
/* used for vertical weight starting value */ /* used for vertical weight starting value */
uint32 weight; 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. /* 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 * 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 LOG(6,("Overlay: inputbuffer view (zoom) left %d, top %d, width %d, height %d\n",
* register-update glitches (double buffer feature). my_ov.h_start, my_ov.v_start, my_ov.width, my_ov.height));
* Programming the BES needs about 50 lines with a 1600 x 1200 x 90Hz screen with
* logging mostly disabled on a P3-500. */
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 all edges of output window ***
****************************************/ ****************************************/
/* setup left and right 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 */ /* left edge coordinate of output window, must be inside desktop */
/* clipping on the left side */ /* clipping on the left side */
if (ow->h_start < 0) 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; temp1 = (uint16)ow->h_start & 0x7ff;
} }
} }
temp32 |= temp1 << 16; hcoordv |= temp1 << 16;
/* right edge coordinate of output window, must be inside desktop */ /* right edge coordinate of output window, must be inside desktop */
/* width < 2 is not allowed */ /* width < 2 is not allowed */
if (ow->width < 2) if (ow->width < 2)
@@ -125,12 +140,11 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
} }
} }
} }
temp32 |= temp2 << 0; hcoordv |= temp2 << 0;
BESW(HCOORD, temp32);
LOG(4,("Overlay: left-edge output %d, right-edge output %d\n",temp1, temp2)); LOG(4,("Overlay: left-edge output %d, right-edge output %d\n",temp1, temp2));
/* setup top and bottom edges of output window */ /* setup top and bottom edges of output window */
temp32 = 0; vcoordv = 0;
/* top edge coordinate of output window, must be inside desktop */ /* top edge coordinate of output window, must be inside desktop */
/* clipping on the top side */ /* clipping on the top side */
if (ow->v_start < 0) 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; temp1 = (uint16)ow->v_start & 0x7ff;
} }
} }
temp32 |= temp1 << 16; vcoordv |= temp1 << 16;
/* bottom edge coordinate of output window, must be inside desktop */ /* bottom edge coordinate of output window, must be inside desktop */
/* height < 2 is not allowed */ /* height < 2 is not allowed */
if (ow->height < 2) if (ow->height < 2)
@@ -180,8 +194,7 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
} }
} }
} }
temp32 |= temp2 << 0; vcoordv |= temp2 << 0;
BESW(VCOORD, temp32);
LOG(4,("Overlay: top-edge output %d, bottom-edge output %d\n",temp1, temp2)); 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 *** *** 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)); (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... */ /* do horizontal scaling... */
/* determine interval representation value */ /* determine interval representation value, taking zoom into account */
if (ow->flags & B_OVERLAY_HORIZONTAL_FILTERING) if (ow->flags & B_OVERLAY_HORIZONTAL_FILTERING)
{ {
/* horizontal filtering is ON */ /* 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 */ /* no horizontal scaling used, OR destination width < 2 */
intrep = 0; intrep = 0;
@@ -211,7 +224,7 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
else else
{ {
/* horizontal filtering is OFF */ /* 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 */ /* horizontal downscaling used AND destination width >= 2 */
intrep = 1; 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)); LOG(4,("Overlay: horizontal interval representation value is %d\n",intrep));
/* calculate inverse horizontal scaling factor */ /* calculate inverse horizontal scaling factor, taking zoom into account */
/* (using standard scaling formula: neglecting round-off var as extra error is very small..) */ /* standard scaling formula: */
ifactor = ((ob->width - si->overlay.myBufInfo[offset].slopspace - intrep) << 16) / ifactor = (((uint32)(my_ov.width - intrep)) << 16) / (ow->width - intrep);
(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)); LOG(4,("Overlay: horizontal scaling factor is %f\n", (float)65536 / ifactor));
/* compensate for accelerated 2x zoom (slowdown BES if pixelclock is too high) */ /* compensate for accelerated 2x zoom (slowdown BES if pixelclock is too high) */
temp32 = ifactor * acczoom; hiscalv = ifactor * acczoom;
LOG(4,("Overlay: horizontal speed compensated factor is %f\n", (float)65536 / temp32)); 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 */ /* 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 */ /* (non-inverse) factor too large, set factor to max. valid value */
temp32 = (((ob->width - si->overlay.myBufInfo[offset].slopspace) << 16) / 16384); hiscalv = ((((uint32)my_ov.width) << 16) / 16384);
LOG(4,("Overlay: horizontal scaling factor too large, clamping at %f\n", (float)65536 / temp32)); 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 */ /* (non-inverse) factor too small, set factor to min. valid value */
temp32 = 0x1ffffc; hiscalv = 0x1ffffc;
LOG(4,("Overlay: horizontal scaling factor too small, clamping at %f\n", (float)65536 / temp32)); LOG(4,("Overlay: horizontal scaling factor too small, clamping at %f\n", (float)65536 / hiscalv));
} }
/* AND below is required by hardware */ /* AND below is required by hardware */
temp32 &= 0x001ffffc; hiscalv &= 0x001ffffc;
BESW(HISCAL, temp32);
/* do horizontal clipping... */ /* do horizontal clipping... */
@@ -256,11 +270,12 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
/* Note: /* Note:
* The method is to calculate, based on 1:1 scaling, based on the output window. * 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.
* 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: /* Note also:
* Even if the scaling factor is clamping we instruct the BES to use the correct source start pos.! */ * 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 */ /* check for destination horizontal clipping at left side */
if (ow->h_start < 0) 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) if ((ow->h_start + ow->width - 1) < 1)
{ {
/* increase 'first contributing pixel' with 'fixed value': (total dest. width - 2) */ /* increase 'first contributing pixel' with 'fixed value': (total dest. width - 2) */
temp32 += (ow->width - 2); hsrcstv += (ow->width - 2);
} }
else else
{ {
/* increase 'first contributing pixel' with actual number of dest. clipping pixels */ /* 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")); LOG(4,("Overlay: clipping left...\n"));
/* The calculated value is based on scaling = 1x. So we now compensate for scaling. /* 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! */ * 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 */ /* AND below required by hardware */
temp32 &= 0x03fffffc; hsrcstv &= 0x03fffffc;
BESW(HSRCST, temp32); LOG(4,("Overlay: first hor. (sub)pixel of input bitmap contributing %f\n", hsrcstv / (float)65536));
LOG(4,("Overlay: first hor. (sub)pixel of input bitmap contributing %f\n", temp32 / (float)65536));
/* Setup horizontal source end: last (sub)pixel contributing to output picture */ /* Setup horizontal source end: last (sub)pixel contributing to output picture */
/* Note: /* Note:
* The method is to calculate, based on 1:1 scaling, based on the output window. * 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: /* Note also:
* Even if the scaling factor is clamping we instruct the BES to use the correct source end pos.! */ * 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 */ /* check for destination horizontal clipping at right side */
if ((ow->h_start + ow->width - 1) > (si->dm.virtual_width - 1)) 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)) if (ow->h_start > (si->dm.virtual_width - 2))
{ {
/* increase 'number of clipping pixels' with 'fixed value': (total dest. width - 2) */ /* increase 'number of clipping pixels' with 'fixed value': (total dest. width - 2) */
temp32 += (ow->width - 2); hsrcendv += (ow->width - 2);
} }
else else
{ {
/* increase 'number of clipping pixels' with actual number of dest. clipping pixels */ /* 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")); LOG(4,("Overlay: clipping right...\n"));
/* The calculated value is based on scaling = 1x. So we now compensate for scaling. /* 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! */ * Note that this also already takes care of aligning the value to the BES register! */
temp32 *= ifactor; hsrcendv *= ifactor;
/* now subtract this value from the last used pixel in (zoomed) inputbuffer, aligned to BES */
/* now subtract this value from the last used pixel in inputbuffer, aligned to BES */ hsrcendv = (((uint32)((my_ov.h_start + my_ov.width) - 1)) << 16) - hsrcendv;
temp32 = (((ob->width - 1) - si->overlay.myBufInfo[offset].slopspace) << 16) - temp32;
} }
else else
{ {
/* set last contributing pixel to last used pixel in inputbuffer, aligned to BES */ /* set last contributing pixel to last used pixel in (zoomed) inputbuffer, aligned to BES */
temp32 = ((ob->width - 1) - si->overlay.myBufInfo[offset].slopspace) << 16; hsrcendv = (((uint32)((my_ov.h_start + my_ov.width) - 1)) << 16);
} }
/* AND below required by hardware */ /* AND below required by hardware */
temp32 &= 0x03fffffc; hsrcendv &= 0x03fffffc;
BESW(HSRCEND, temp32); LOG(4,("Overlay: last horizontal (sub)pixel of input bitmap contributing %f\n", hsrcendv / (float)65536));
LOG(4,("Overlay: last horizontal (sub)pixel of input bitmap contributing %f\n", temp32 / (float)65536));
/* setup horizontal source last position excluding slopspace */ /* setup horizontal source last position excluding slopspace:
temp32 = ((ob->width - 1) - si->overlay.myBufInfo[offset].slopspace) << 16; * 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 */ /* AND below required by hardware */
temp32 &= 0x03ff0000; hsrclstv &= 0x03ff0000;
BESW(HSRCLST, temp32);
/******************************************* /*******************************************
@@ -343,11 +358,11 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
*******************************************/ *******************************************/
/* do vertical scaling... */ /* do vertical scaling... */
/* determine interval representation value */ /* determine interval representation value, taking zoom into account */
if (ow->flags & B_OVERLAY_VERTICAL_FILTERING) if (ow->flags & B_OVERLAY_VERTICAL_FILTERING)
{ {
/* vertical filtering is ON */ /* 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 */ /* no vertical scaling used, OR destination height < 2 */
intrep = 0; intrep = 0;
@@ -360,7 +375,7 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
else else
{ {
/* vertical filtering is OFF */ /* 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 */ /* vertical downscaling used AND destination height >= 2 */
intrep = 1; 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)); LOG(4,("Overlay: vertical interval representation value is %d\n",intrep));
/* calculate inverse vertical scaling factor */ /* calculate inverse vertical scaling factor, taking zoom into account */
/* (using standard scaling formula: neglecting round-off var as extra error is very small..) */ /* standard scaling formula: */
ifactor = ((ob->height - intrep) << 16) / (ow->height - intrep); 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)); LOG(4,("Overlay: vertical scaling factor is %f\n", (float)65536 / ifactor));
/* preserve ifactor for source positioning calculations later on */ /* preserve ifactor for source positioning calculations later on */
temp32 = ifactor; viscalv = ifactor;
/* check scaling factor (and modify if needed) to be within scaling limits */ /* 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 */ /* (non-inverse) factor too large, set factor to max. valid value */
temp32 = ((ob->height << 16) / 16384); viscalv = ((((uint32)my_ov.height) << 16) / 16384);
LOG(4,("Overlay: vertical scaling factor too large, clamping at %f\n", (float)65536 / temp32)); 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 */ /* (non-inverse) factor too small, set factor to min. valid value */
temp32 = 0x1ffffc; viscalv = 0x1ffffc;
LOG(4,("Overlay: vertical scaling factor too small, clamping at %f\n", (float)65536 / temp32)); LOG(4,("Overlay: vertical scaling factor too small, clamping at %f\n", (float)65536 / viscalv));
} }
/* AND below is required by hardware */ /* AND below is required by hardware */
temp32 &= 0x001ffffc; viscalv &= 0x001ffffc;
BESW(VISCAL, temp32);
/* do vertical clipping... */ /* do vertical clipping... */
/* Setup vertical source start: first (sub)pixel contributing to output picture. /* Setup vertical source start: first (sub)pixel contributing to output picture.
* Note: this exists of two parts: * Note: this exists of two parts:
* 1. setup fractional part (sign is always 'positive'); * 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. */ * Both parts are done intertwined below. */
/* Note: /* Note:
* The method is to calculate, based on 1:1 scaling, based on the output window. * 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: /* Note also:
* Even if the scaling factor is clamping we instruct the BES to use the correct source start pos.! */ * 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' */ /* calculate relative base_adress and 'vertical weight fractional part' */
weight = 0; weight = 0;
temp32 = (uint32)((vuint32 *)ob->buffer); a1orgv = (uint32)((vuint32 *)ob->buffer);
temp32 -= (uint32)((vuint32 *)si->framebuffer); a1orgv -= (uint32)((vuint32 *)si->framebuffer);
LOG(4,("Overlay: topleft corner of input bitmap (cardRAM offset) $%08x\n",temp32));
/* calculate origin adress */ /* calculate origin adress */
LOG(4,("Overlay: topleft corner of input bitmap (cardRAM offset) $%08x\n",a1orgv));
/* check for destination vertical clipping at top side */ /* check for destination vertical clipping at top side */
if (ow->v_start < 0) 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': /* increase source buffer origin with 'fixed value':
* (integer part of ('total height - 2' of dest. picture in pixels * inverse scaling factor)) * * (integer part of ('total height - 2' of dest. picture in pixels * inverse scaling factor)) *
* bytes per row source picture */ * 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; weight = (ow->height - 2) * ifactor;
} }
else else
@@ -434,52 +452,194 @@ status_t gx00_configure_bes(const overlay_buffer *ob, const overlay_window *ow,
/* increase source buffer origin with: /* increase source buffer origin with:
* (integer part of (number of destination picture clipping pixels * inverse scaling factor)) * * (integer part of (number of destination picture clipping pixels * inverse scaling factor)) *
* bytes per row source picture */ * 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; 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)); LOG(4,("Overlay: first vert. (sub)pixel of input bitmap contributing %f\n", weight / (float)65536));
/* Note: /* 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. * 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 * 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 * is shifted horizontally during left clipping on all > G200 cards, while G200 cards
* early G200 cards will have 4 source-image pixel jumps occuring. */ * 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 /* AND below is required by G200-G550 hardware. > G200 cards can have max. 32Mb RAM on board
* (incl. later G200 cards!). Compatible setting used (between early G200 and the rest), * (16Mb on G200 cards). Compatible setting used (between G200 and the rest), this has no
* this has no downside consequences here. */ * downside consequences here. */
temp32 &= 0x01fffff0; /* Buffer A topleft corner of field 1 (origin)(field 1 contains our full frames) */
/* buffer A topleft corner of field 1 (origin)(field 1 contains our full frames) */ a1orgv &= 0x01fffff0;
BESW(A1ORG, temp32);
/* field 1 weight: AND below required by hardware, also make sure 'sign' is always 'positive' */ /* field 1 weight: AND below required by hardware, also make sure 'sign' is always 'positive' */
temp32 = weight & 0x0000fffc; v1wghtv = weight & 0x0000fffc;
BESW(V1WGHT, temp32);
/* setup field 1 (is our complete frame) vertical source contributing height - 1. /* setup field 1 (is our complete frame) vertical source last position.
* Note: * this is the last pixel that will be used for calculating interpolated pixels */
* This value is bottom-unclipped! (as it should be according to the MGA specs...) */ v1srclstv = (ob->height - 1);
temp32 = (ob->height - 1) - (weight >> 16);
/* AND below required by hardware */ /* AND below required by hardware */
temp32 &= 0x000003ff; v1srclstv &= 0x000003ff;
BESW(V1SRCLST, temp32);
LOG(4,("Overlay: input bitmap bottom-unclipped contributing height (integer part) %d\n", temp32 + 1));
/*****************************
*** 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 *** *** 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 */ /* setup colorkeying */
DXIW(COLKEY, (ow->alpha.value & ow->alpha.mask)); 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) */ /* setup brightness and contrast to be 'neutral' (this is not implemented on G200) */
BESW(LUMACTL, 0x00000080); BESW(LUMACTL, 0x00000080);
/* setup source pitch including slopspace (in pixels) */ /* setup source pitch including slopspace (in pixels); AND is required by hardware */
temp32 = ob->width; BESW(PITCH, (ob->width & 0x00000fff));
/* 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);
/* 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))); LOG(3,("Overlay: completed at Vcount %d\n", CR1R(VCOUNT)));
return B_OK; return B_OK;
+115 -38
View File
@@ -2,7 +2,7 @@
/* Authors: /* Authors:
Mark Watson 2/2000, Mark Watson 2/2000,
Apsed, Apsed,
Rudolf Cornelissen 10/2002 Rudolf Cornelissen 11-12/2002
*/ */
#define MODULE_BIT 0x00040000 #define MODULE_BIT 0x00040000
@@ -109,14 +109,14 @@ status_t gx00_crtc_set_timing(
LOG(4,("CRTC: setting timing\n")); LOG(4,("CRTC: setting timing\n"));
/*Modify parameters as required by the G400/G200*/ /* Modify parameters as required by the G400/G200 */
htotal=(ht>>3)-5; htotal = ((ht >> 3) - 5);
hdisp_e=(hd_e>>3)-1; hdisp_e = ((hd_e >> 3) -1); //so: timing - 8
hsync_s=(hs_s>>3); hblnk_s = hdisp_e; //so: timing - 8
hsync_e=(hs_e>>3); hblnk_e = (htotal + 4); //so: timing - 8
hblnk_s=hdisp_e; hsync_s = (hs_s >> 3);
hblnk_e=htotal+4; hsync_e = (hs_e >> 3);
vtotal=vt-2; vtotal=vt-2;
vdisp_e=vd_e-1; vdisp_e=vd_e-1;
vsync_s=vs_s-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))| ((vsync_s&0x100)>>(8-2))|((vsync_s&0x200)>>(9-7))|
((vblnk_s&0x100)>>(8-3))|((linecomp&0x100)>>(8-4)) ((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,0x9,((vblnk_s&0x200)>>(9-5))|((linecomp&0x200)>>(9-6)));
VGAW_I(CRTC,0x10,vsync_s&0xFF); VGAW_I(CRTC,0x10,vsync_s&0xFF);
VGAW_I(CRTC,0x11,((VGAR_I(CRTC,0x11))&0xF0)|(vsync_e&0xF)); 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,0x16,vblnk_e&0xFF);
VGAW_I(CRTC,0x18,linecomp&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, VGAW_I(CRTCEXT,1,
( (
((htotal&0x100)>>8)| ((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(SEQ,1,(!display)<<5);
VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0xCF)|((!v)<<5))|((!h)<<4); 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); VGAW_I(CRTC,0x14,0x00);
return B_OK; 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)); LOG(4,("CRTC: setting card RAM to be displayed bpp %d\n", bpp));
/*figure out startadd value hardware needs*/ /* Matrox docs are false/incomplete, always program qword adress. */
/*switch(bpp) startadd >>= 3;
{
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?
LOG(2,("CRTC: startadd: %x\n",startadd)); LOG(2,("CRTC: startadd: %x\n",startadd));
LOG(2,("CRTC: frameRAM: %x\n",si->framebuffer)); 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; 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)); /* 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))
switch (HIPRILVL) {
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: case 0:
VGAW_I(CRTCEXT,6,0x00); mp = 52;
break; break;
case 1:case 2:case 3: case 1:
VGAW_I(CRTCEXT,6,0x10|HIPRILVL); mp = 41;
break; break;
case 4:case 5:case 6:case 7: case 2:
VGAW_I(CRTCEXT,6,0x20|HIPRILVL); mp = 32;
break; break;
default: default:
LOG(8,("CRTC: Memory priority level violation: %x\n",HIPRILVL)); mp = 52;
return B_ERROR; 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; return B_OK;
} }
@@ -326,11 +390,17 @@ status_t gx00_crtc_cursor_init()
{ {
int i; int i;
uint32 * fb; 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*/ /* set cursor bitmap adress ... */
DXIW(CURADDL,curadd >> 10); /*data at curadd in framebuffer*/ DXIW(CURADDL,curadd >> 10);
DXIW(CURADDH,curadd >> 18); 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); DXIW(CURCTRL,1);
/*set cursor colour*/ /*set cursor colour*/
@@ -395,6 +465,13 @@ status_t gx00_crtc_cursor_position(uint16 x ,uint16 y)
x+=i; x+=i;
y+=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(CURSPOSXL,x&0xFF);
DACW(CURSPOSXH,x>>8); DACW(CURSPOSXH,x>>8);
DACW(CURSPOSYL,y&0xFF); DACW(CURSPOSYL,y&0xFF);
@@ -1,5 +1,9 @@
/* second CTRC functionality */ /* second CTRC functionality
/* Mark Watson 6/2000 */
Authors:
Mark Watson 6/2000,
Rudolf Cornelissen 12/2002
*/
#define MODULE_BIT 0x00020000 #define MODULE_BIT 0x00020000
@@ -22,12 +26,14 @@ status_t g400_crtc2_set_timing(
} }
/*program the second CRTC*/ /*program the second CRTC*/
CR2W(HPARAM,(((hdisp_e-8)<<16) | (htotal-8))); CR2W(HPARAM, ((((hdisp_e - 8) & 0x0fff) << 16) | ((htotal - 8) & 0x0fff)));
CR2W(HSYNC,(((hsync_e-8)<<16) | (hsync_s-8))); CR2W(HSYNC, ((((hsync_e - 8) & 0x0fff) << 16) | ((hsync_s - 8) & 0x0fff)));
CR2W(VPARAM,(((vdisp_e-1)<<16) | (vtotal-1))); CR2W(VPARAM, ((((vdisp_e - 1) & 0x0fff) << 16) | ((vtotal - 1) & 0x0fff)));
CR2W(VSYNC,(((vsync_e-1)<<16) | (vsync_s-1))); CR2W(VSYNC, ((((vsync_e - 1) & 0x0fff) << 16) | ((vsync_s - 1) & 0x0fff)));
CR2W(PRELOAD,(((vsync_s)<<16) | (hsync_s))); //Mark: (wrong AFAIK, warning: SETMODE MAVEN-CRTC delay is now tuned to new setup!!)
CR2W(MISC,((0xfff<<16) | ((!hsync_pos)<<8) | ((!vsync_pos)<<9))); //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; 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) 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*/ CR2W(CTL,(CR2R(CTL)&0xFFF0077E)|(display&h&v)); /*enable second CRTC if required*/
/*ignore h,v because they are not supported*/ /*ignore h,v because they are not supported*/
+323 -88
View File
@@ -2,7 +2,7 @@
/* Authors: /* Authors:
Mark Watson 2/2000, Mark Watson 2/2000,
Apsed 2002, Apsed 2002,
Rudolf Cornelissen 9/2002 Rudolf Cornelissen 9-12/2002
*/ */
#define MODULE_BIT 0x00010000 #define MODULE_BIT 0x00010000
@@ -27,7 +27,7 @@ status_t gx00_dac_mode(int mode,float brightness)
g=r+256; g=r+256;
b=g+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*/ /*init a basic palette for brightness specified*/
for (i=0;i<256;i++) for (i=0;i<256;i++)
{ {
@@ -73,7 +73,7 @@ status_t gx00_dac_mode(int mode,float brightness)
case BPP32DIR: case BPP32DIR:
break; break;
default: default:
LOG(8,("DAC:Invalid bit depth requested\n")); LOG(8,("DAC: Invalid bit depth requested\n"));
return B_ERROR; return B_ERROR;
break; 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")); LOG(4,("DAC: setting palette\n"));
/*clear palwtadd to start programming*/ /* clear palwtadd to start programming (LUT index?) */
DACW(PALWTADD,0); DACW(PALWTADD,0);
/* just for safety (specs are somewhat unclear) (LUT color?) */
DACW(PALRDADD,0);
/*loop through all 256 to program DAC*/ /*loop through all 256 to program DAC*/
for (i=0;i<256;i++) 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")); LOG(8,("DAC: PALWTADD is not 0 after programming\n"));
return B_ERROR; return B_ERROR;
} }
if (0) {// apsed: reread LUT if (0)
{// apsed: reread LUT
uint8 R, G, B; uint8 R, G, B;
/* clear LUT color (modulo 3 counter) */
DACW(PALRDADD,0); DACW(PALRDADD,0);
for (i=0;i<256;i++) { for (i=0;i<256;i++)
{
R = DACR(PALDATA); R = DACR(PALDATA);
G = DACR(PALDATA); G = DACR(PALDATA);
B = DACR(PALDATA); B = DACR(PALDATA);
if ((r[i] != R) || (g[i] != G) || (b[i] != B)) 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 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; return B_OK;
} }
@@ -650,7 +661,191 @@ static status_t g100_g400max_dac_sys_pll_find(
return B_OK; 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() status_t g100_dac_set_sys_pll()
{ {
/* values for DAC sys pll registers */ /* values for DAC sys pll registers */
@@ -660,8 +855,7 @@ status_t g100_dac_set_sys_pll()
float calc_sclk; float calc_sclk;
LOG(1,("DAC: Setting up G100 system clock\n")); 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((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
g100_g400max_dac_sys_pll_find(si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
/* reprogram the clock - set PCI/AGP, program, set to programmed */ /* reprogram the clock - set PCI/AGP, program, set to programmed */
/* disable the SYSPLL */ /* disable the SYSPLL */
@@ -707,30 +901,30 @@ status_t g100_dac_set_sys_pll()
return B_OK; 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() 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; uint time = 0;
uint32 temp;
float calc_sclk; float calc_sclk;
LOG(1,("DAC: Setting up G200 system clock\n")); 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((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
//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);
/*reprogram the clock - set PCI/AGP, program, set to programmed*/ /* reprogram the clock - set PCI/AGP, program, set to programmed */
//fixme: PINS.. /* disable the SYSPLL */
CFGW(OPTION2,0x8000); /*no memory clock divider (pinced from win)*/ 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*/ /* program the new clock */
CFGW(OPTION,CFGR(OPTION)&0xFFFFFFFC); /*select the PCI/AGP clock*/ DXIW(SYSPLLM, m);
CFGW(OPTION,CFGR(OPTION)&0xFFFFFFFB); /*enable the SYSPLL*/ DXIW(SYSPLLN, n);
DXIW(SYSPLLP, p);
DXIW(SYSPLLM,m);
DXIW(SYSPLLN,n);
DXIW(SYSPLLP,p);
/* Wait for the SYSPLL frequency to lock until timeout occurs */ /* Wait for the SYSPLL frequency to lock until timeout occurs */
while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000)) while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
@@ -744,74 +938,57 @@ status_t g200_dac_set_sys_pll()
else else
LOG(2,("DAC: sys PLL frequency locked\n")); LOG(2,("DAC: sys PLL frequency locked\n"));
CFGW(OPTION,CFGR(OPTION)|0x04); /*disable the SYSPLL*/ /* disable the SYSPLL */
//fixme: PINS.. CFGW(OPTION, CFGR(OPTION) | 0x04);
CFGW(OPTION,(CFGR(OPTION)&0xFFFFFF27)|0x1); /*select the SYSPLLs chosen*/ /* setup Wclk divisor and enable/disable Wclk, Gclk and Mclk divisors
CFGW(OPTION,(CFGR(OPTION)&0xFFFFFFFB)|0x20); /*enable the SYSPLL*/ * 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; 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() status_t g400_dac_set_sys_pll()
{ {
uint32 scalers; /*value for option 3*/ /* values for DAC sys pll registers */
uint8 m, n, p;/*values for DAC sys pll registers*/ uint8 m, n, p;
uint8 mclk_duty,oclk_duty;
uint time = 0; uint time = 0;
float mclk,oclk;
float temp_f;
float calc_sclk; 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")); 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 */ /* reprogram the clock - set PCI/AGP, program, set to programmed */
mclk = div[mclk_div] * calc_sclk; /* clear, so don't o/clock addons */
oclk = div[oclk_div] * calc_sclk; 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*/ /* program the new clock */
temp_f=1/(float)oclk; DXIW(SYSPLLM, m);
temp_f*=1000; DXIW(SYSPLLN, n);
LOG(2,("DAC:oclk correction ns: %f\n",temp_f)); DXIW(SYSPLLP, p);
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);
/* Wait for the SYSPLL frequency to lock until timeout occurs */ /* Wait for the SYSPLL frequency to lock until timeout occurs */
while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000)) while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
@@ -825,13 +1002,71 @@ status_t g400_dac_set_sys_pll()
else else
LOG(2,("DAC: sys PLL frequency locked\n")); LOG(2,("DAC: sys PLL frequency locked\n"));
CFGW(OPTION,CFGR(OPTION)|0x04); /*disable the SYSPLL*/ /* disable the SYSPLL */
CFGW(OPTION3,scalers); /*select the SYSPLLs chosen*/ CFGW(OPTION, CFGR(OPTION) | 0x04);
CFGW(OPTION,CFGR(OPTION)&0xFFFFFFFB); /*enable the SYSPLL*/ /* 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; return B_OK;
} }
/*set up system pll - NB mclk is memory clock, */ /*set up system pll - NB mclk is memory clock */
//fixme: implement this routine for coldstart: status_t g450_dac_set_sys_pll()
//status_t g450_dac_set_sys_pll(int m,int n,int mclk_div,int oclk_div) {
/* 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: /* Authors:
Mark Watson 12/1999, Mark Watson 12/1999,
Apsed, Apsed,
Rudolf Cornelissen 10/2002 Rudolf Cornelissen 10-12/2002
*/ */
#define MODULE_BIT 0x00008000 #define MODULE_BIT 0x00008000
@@ -54,60 +54,62 @@ static void mga_dump_configuration_space (void)
status_t gx00_general_powerup() status_t gx00_general_powerup()
{ {
status_t status; status_t status;
uint32 class; uint32 card_class;
//detect card type and powerup /* detect card type and power it up */
switch(CFGR(DEVID)) switch(CFGR(DEVID))
{ {
case 0x0519102b: //MGA-2064 Millenium PCI case 0x0519102b: //MGA-2064 Millenium PCI
case 0x051a102b: //MGA-1064 Mystic 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; return B_ERROR;
case 0x051b102b:case 0x051f102b: //MGA-2164 Millenium 2 PCI/AGP case 0x051b102b:case 0x051f102b: //MGA-2164 Millenium 2 PCI/AGP
si->ps.card_type=MIL2; si->ps.card_type = MIL2;
LOG(4,("POWERUP:Detected MGA-2164 Millennium 2\n")); LOG(4,("POWERUP: Detected MGA-2164 Millennium 2\n"));
status = mil2_general_powerup(); status = mil2_general_powerup();
break; break;
case 0x1000102b:case 0x1001102b: //G100 case 0x1000102b:case 0x1001102b: //G100
si->ps.card_type=G100; si->ps.card_type = G100;
LOG(4,("POWERUP:Detected G100\n")); LOG(4,("POWERUP: Detected G100\n"));
status = g100_general_powerup(); status = g100_general_powerup();
break; break;
case 0x0520102b:case 0x0521102b: //G200 case 0x0520102b:case 0x0521102b: //G200
si->ps.card_type=G200; si->ps.card_type = G200;
LOG(4,("POWERUP:Detected G200\n")); LOG(4,("POWERUP: Detected G200\n"));
status = g200_general_powerup(); status = g200_general_powerup();
break; break;
case 0x0525102b: //G400 case 0x0525102b: //G400, G400MAX or G450
LOG(4,("POWERUP:Detected G4")); LOG(4,("POWERUP: Detected G4"));
//Check if it is a G450... /* get classinfo to distinguish different types */
class = 0xff&CFGR(CLASS); card_class = CFGR(CLASS) & 0xff;
if (class & 0x80) //G450 if (card_class & 0x80)
{ {
si->ps.card_type=G450; /* G450 */
LOG(4, ("50 revision %x\n", class&0x7f)); si->ps.card_type = G450;
LOG(4, ("50 revision %x\n", card_class & 0x7f));
status = g450_general_powerup(); status = g450_general_powerup();
} }
else //G400 else
{ {
si->ps.card_type=G400; /* standard G400, G400MAX */
LOG(4, ("00 revision %x\n", class&0x7f)); /* 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(); status = g400_general_powerup();
} }
break; break;
case 0x2527102b://G550 patch from Jean-Michel Batto case 0x2527102b://G550 patch from Jean-Michel Batto
si->ps.card_type=G450; si->ps.card_type = G450;
LOG(4,("POWERUP:Detected G550\n")); LOG(4,("POWERUP: Detected G550\n"));
status = g450_general_powerup(); status = g450_general_powerup();
break; break;
default: 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; return B_ERROR;
} }
/*override memory if requested by user*/ /* override memory detection if requested by user */
// even if detection works on the G400 if (si->settings.memory != 0)
if (si->settings.memory != 0) // apsed
si->ps.memory_size = si->settings.memory; si->ps.memory_size = si->settings.memory;
return status; return status;
@@ -252,61 +254,20 @@ status_t mil2_general_powerup()
LOG(2, ("INIT: Skipping card coldstart!\n")); LOG(2, ("INIT: Skipping card coldstart!\n"));
mil2_dac_init(); 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); VGAW_I(SEQ,1,0x00);
/*enable screen*/ /*enable screen*/
return B_OK; return B_OK;
return B_ERROR; // apsed TODO MIL2 taken from G100, avoid DXIR/W DACR/W // apsed TODO MIL2 taken from G100, avoid DXIR/W DACR/W
//rudolf: G100 version that was here nolonger exists, look at new implementation...
/*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);
return B_OK; 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(); if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
/*power up the PLLs,LUT,DAC*/ /*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")); 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! /* G100 SGRAM and SDRAM use external pix and dac refs, do *not* activate internals!
* (this would create electrical shortcuts, * (this would create electrical shortcuts,
* resulting in extra chip heat and distortions visible on screen */ * resulting in extra chip heat and distortions visible on screen */
DXIW(VREFCTRL,0x03); /*set voltage reference - using DAC reference block partly */ /* set voltage reference - using DAC reference block partly */
delay(100000); /*wait for 100ms for voltage reference to stabalise*/ DXIW(VREFCTRL,0x03);
CFGW(OPTION,CFGR(OPTION)|0x20); /*power up the SYSPLL - sets syspllpdN to 1*/ /* wait for 100ms for voltage reference to stabilize */
while(!(DXIR(SYSPLLSTAT)&0x40)); /*wait for the SYSPLL frequency to lock*/ delay(100000);
LOG(2,("INIT: SYS PLL locked\n")); /* power up the SYSPLL */
DXIW(PIXCLKCTRL,0x08); /*power up the PIXPLL - sets pixpllpdN to 1*/ CFGW(OPTION,CFGR(OPTION)|0x20);
while(!(DXIR(PIXPLLSTAT)&0x40)); /*wait for the PIXPLL frequency to lock*/ /* power up the PIXPLL */
LOG(2,("INIT: PIX PLL locked\n")); DXIW(PIXCLKCTRL,0x08);
DXIW(MISCCTRL,0x1b); /*CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC*/
/* 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 */ /* setup i2c bus */
i2c_init(); i2c_init();
@@ -356,14 +329,13 @@ status_t g100_general_powerup()
/* 'official' RAM initialisation */ /* 'official' RAM initialisation */
LOG(2,("INIT: RAM init\n")); LOG(2,("INIT: RAM init\n"));
/* turn off both displays (also disables transfers) */ /* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
gx00_crtc_dpms(0,0,0); ACCW(PLNWT,0x00000000);
/* disable plane write mask (needed for SDRAM) */
ACCW(PLNWT,0xffffffff); ACCW(PLNWT,0xffffffff);
/* program memory control waitstates */ /* program memory control waitstates */
ACCW(MCTLWTST,si->ps.mctlwtst_reg); ACCW(MCTLWTST,si->ps.mctlwtst_reg);
/* set memory configuration: /* set memory configuration including:
* - no split framebuffer, * - no split framebuffer.
* - Mark says b14 (G200) should be done also though not defined for G100 in spec, * - 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 */ * - 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)); 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, * 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. */ * - Mark also says: place v3_mem_type b1 in option2 bit13 (if not 0x03) but b13 = reserved. */
CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|((si->ps.v3_mem_type & 0x01) << 12)); CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|((si->ps.v3_mem_type & 0x01) << 12));
/* set mode register opcode to $0 */ /* set RAM read tap delay */
// ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xE1FFFFFF)); /* G200 only */
/* set RAM read tap delay G100 */
CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFFFF0) | ((si->ps.v3_mem_type & 0xf0) >> 4)); CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFFFF0) | ((si->ps.v3_mem_type & 0xf0) >> 4));
// ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF0000)|the_setting); /* G200 version */
/* wait 200uS minimum */ /* wait 200uS minimum */
snooze(250); snooze(250);
/* reset memory */ /* reset memory */
ACCW(MACCESS,ACCR(MACCESS)&0xFFFF7FFF); ACCW(MACCESS, 0x00000000);
/* select JEDEC reset method */ /* select JEDEC reset method */
ACCW(MACCESS,ACCR(MACCESS)|0x4000); ACCW(MACCESS,ACCR(MACCESS)|0x4000);
/* perform actual RAM reset */ /* 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(); if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
/*power up the PLLs,LUT,DAC*/ /*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")); LOG(2,("INIT: PLL/LUT/DAC powerup\n"));
//rudolf: check from here on: /* turn off both displays and the hardcursor (also disables transfers) */
DXIW(VREFCTRL,0x3f); /*set voltage reference - using DAC reference block*/ gx00_crtc_dpms(0,0,0);
delay(100000); /*wait for 100ms for voltage reference to stabalise*/ gx00_crtc_cursor_hide();
CFGW(OPTION,CFGR(OPTION)|0x20); /*power up the SYSPLL - sets syspllpdN to 1*/ /* G200 SGRAM and SDRAM use external pix and dac refs, do *not* activate internals!
while(!(DXIR(SYSPLLSTAT)&0x40)); /*wait for the SYSPLL frequency to lock*/ * (this would create electrical shortcuts,
LOG(2,("INIT: SYS PLL locked\n")); * resulting in extra chip heat and distortions visible on screen */
DXIW(PIXCLKCTRL,0x08); /*power up the PIXPLL - sets pixpllpdN to 1*/ /* set voltage reference - using DAC reference block partly */
while(!(DXIR(PIXPLLSTAT)&0x40)); /*wait for the PIXPLL frequency to lock*/ DXIW(VREFCTRL,0x03);
LOG(2,("INIT: PIX PLL locked\n")); /* wait for 100ms for voltage reference to stabilize */
DXIW(MISCCTRL,0x1b); /*CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC*/ delay(100000);
//until here /* 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 */ /* setup i2c bus */
i2c_init(); 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*/ /*make sure card is in powergraphics mode*/
VGAW_I(CRTCEXT,3,0x80); VGAW_I(CRTCEXT,3,0x80);
/*set the system clocks to powergraphics speed*/ /*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(); g200_dac_set_sys_pll();
/*RAM initialisation*/ /* 'official' RAM initialisation */
LOG(2,("INIT:RAM init\n")); LOG(2,("INIT: RAM init\n"));
gx00_crtc_dpms(0,0,0); /*turn off both displays*/ /* disable hardware plane write mask if SDRAM card */
ACCW(MCTLWTST,si->ps.mem_ctl); /*set memory wait states*/ if (si->ps.sdram) CFGW(OPTION,(CFGR(OPTION) & 0xffffbfff));
CFGW(OPTION,(CFGR(OPTION)&0xFFFF83FF)|si->ps.mem_type); /*set RAM type and config*/ /* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF)|(si->ps.mem_rd&0xFFFF0000));/*set MEMRDBK - mrsopcode*/ ACCW(PLNWT,0x00000000);
CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|(si->ps.membuf<<12)); /*set the memory buffer type*/ ACCW(PLNWT,0xffffffff);
delay(250); /*wait for 250microseconds*/ /* program memory control waitstates */
ACCW(MACCESS,ACCR(MACCESS)&0xFFFF7FFF); /*reset memory*/ ACCW(MCTLWTST,si->ps.mctlwtst_reg);
ACCW(MACCESS,ACCR(MACCESS)|0x8000); /* set memory configuration including:
delay(250); /*wait for 250microseconds*/ * - SDRAM / SGRAM special functions select. */
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF0000)|(si->ps.mem_rd&0xFFFF));/*set tap delays*/ CFGW(OPTION,(CFGR(OPTION)&0xFFFF83FF) | ((si->ps.v3_mem_type & 0x07) << 10));
CFGW(OPTION,(CFGR(OPTION)&0xffe07fff)|(si->ps.mem_rfhcnt<<15)); /*start memory refresh*/ 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*/ /* reset memory */
CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29))); /*enable retries, use advanced read*/ 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*/ /*enable writing to crtc registers*/
VGAW_I(CRTC,0x11,0); VGAW_I(CRTC,0x11,0);
@@ -485,8 +480,7 @@ status_t g400_general_powerup()
{ {
status_t result; status_t result;
//fully functional G400 powerup -> uses settings from my card if no PINS LOG(4, ("INIT: G400/G400MAX powerup\n"));
LOG(4, ("INIT: G400 powerup\n"));
if (si->settings.logmask & 0x80000000) mga_dump_configuration_space(); if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
/* initialize the shared_info PINS struct */ /* 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(); if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
/*power up the PLLs,LUT,DAC*/ /*power up the PLLs,LUT,DAC*/
/*this bit should not be needed if BIOS has initialised it*/ LOG(4,("INIT: PLL/LUT/DAC powerup\n"));
LOG(4,("INIT: G400 PLL/LUT/DAC powerup\n")); /* turn off both displays and the hardcursor (also disables transfers) */
DXIW(VREFCTRL,0x30); /*set voltage reference - using DAC reference block*/ gx00_crtc_dpms(0,0,0);
delay(100000); /*wait for 100ms for voltage reference to stabalise*/ g400_crtc2_dpms(0,0,0);
CFGW(OPTION,CFGR(OPTION)|0x20); /*power up the SYSPLL - sets syspllpdN to 1*/ gx00_crtc_cursor_hide();
while(!(DXIR(SYSPLLSTAT)&0x40)); /*wait for the SYSPLL frequency to lock*/
LOG(2,("INIT: SYS PLL locked\n")); /* set voltage reference - not using DAC reference block */
DXIW(PIXCLKCTRL,0x08); /*power up the PIXPLL - sets pixpllpdN to 1*/ DXIW(VREFCTRL,0x00);
while(!(DXIR(PIXPLLSTAT)&0x40)); /*wait for the PIXPLL frequency to lock*/ /* wait for 100ms for voltage reference to stabilize */
LOG(2,("INIT: PIX PLL locked\n")); delay(100000);
DXIW(MISCCTRL,0x9b); /*CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC*/ /* power up the SYSPLL */
DXIW(MAFCDEL,0x2); /*makes CRTC2 stable! Matrox specify 8, but use 4 - grrrr!*/ 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*/ DXIW(PANELMODE,0x00); /*eclipse panellink*/
/* setup i2c bus */ /* setup i2c bus */
i2c_init(); i2c_init();
//rudolf: remove /* make sure card is in powergraphics mode */
/*read the PINS and other stuff*/
if (g400_card_info()==B_ERROR)
return B_ERROR;
//end remove
/*make sure card is in powergraphics mode*/
VGAW_I(CRTCEXT,3,0x80); VGAW_I(CRTCEXT,3,0x80);
/*set the system clocks to powergraphics speed*/ /* 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"));
g400_dac_set_sys_pll(); g400_dac_set_sys_pll();
/*RAM initialisation*/ /* 'official' RAM initialisation */
LOG(2,("INIT:RAM init\n")); LOG(2,("INIT: RAM init\n"));
gx00_crtc_dpms(0,0,0); /*turn off both displays*/ /* disable hardware plane write mask if SDRAM card */
g400_crtc2_dpms(0,0,0); if (si->ps.sdram) CFGW(OPTION,(CFGR(OPTION) & 0xffffbfff));
ACCW(MCTLWTST,si->ps.mem_ctl); /*set memory wait states*/ /* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
CFGW(OPTION,(CFGR(OPTION)&0xFFFF83FF)|si->ps.mem_type); /*set RAM type and config*/ ACCW(PLNWT,0x00000000);
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF)|(si->ps.mem_rd&0xFFFF0000));/*set MEMRDBK - mrsopcode*/ ACCW(PLNWT,0xffffffff);
delay(250); /*wait for 250microseconds*/ /* program memory control waitstates */
ACCW(MACCESS,ACCR(MACCESS)&0xFFFF7FFF); /*reset memory*/ ACCW(MCTLWTST, si->ps.mctlwtst_reg);
ACCW(MACCESS,ACCR(MACCESS)|0x8000); /* set memory configuration including:
delay(250); /*wait for 250microseconds*/ * - SDRAM / SGRAM special functions select. */
ACCW(MEMRDBK,(ACCR(MEMRDBK)&0xFFFF0000)|(si->ps.mem_rd&0xFFFF));/*set tap delays*/ CFGW(OPTION,(CFGR(OPTION)&0xFFFF83FF) | (si->ps.option_reg & 0x00001c00));
CFGW(OPTION,(CFGR(OPTION)&0xffe07fff)|(si->ps.mem_rfhcnt<<15)); /*start memory refresh*/ 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*/ /* reset memory */
CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29))); /*enable retries, use advanced read*/ 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*/ /*enable writing to crtc registers*/
VGAW_I(CRTC,0x11,0); VGAW_I(CRTC,0x11,0);
@@ -557,16 +577,18 @@ status_t g400_general_powerup()
/*turn on display one*/ /*turn on display one*/
gx00_crtc_dpms(1,1,1); gx00_crtc_dpms(1,1,1);
return B_OK; return B_OK;
} }
static static
status_t g450_general_powerup() status_t g450_general_powerup()
{ {
uint32 temp; //fixme: check if g450 and g550 powerup should be the same! (DAC outputconnector?)
status_t result; 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(); if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
/* initialize the shared_info PINS struct */ /* initialize the shared_info PINS struct */
@@ -576,82 +598,159 @@ status_t g450_general_powerup()
/* log the PINS struct settings */ /* log the PINS struct settings */
dump_pins(); 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 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(); if (si->settings.usebios || (result != B_OK)) return gx00_general_bios_to_powergraphics();
/*power up the PLLs,LUT,DAC*/ /* power up the PLLs,LUT,DAC */
//rudolf: checkout coldstart from here: 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 /* power up everything except DVI electronics (for now) */
DXIW(PWRCTRL,0x1b);
//These are the values of OPTION->OPTION4 used in Linux /* set voltage reference - not using DAC reference block */
//rudolf: get from PINS... DXIW(VREFCTRL,0x00);
CFGW(OPTION, 0x400a1160); /* wait for 100ms for voltage reference to stabilize */
CFGW(OPTION2, 0x100ac00); delay(100000);
CFGW(OPTION3, 0x90a409); /* power up the SYSPLL */
CFGW(OPTION4, 0x80000004); CFGW(OPTION,CFGR(OPTION)|0x20);
/* power up the PIXPLL */
DXIW(PIXCLKCTRL,0x08);
//rudolf: remove /* disable pixelclock oscillations before switching on CLUT */
/*read the PINS and other stuff*/ DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
if (g450_card_info()==B_ERROR) /* disable 15bit mode CLUT-overlay function */
return B_ERROR; //fixme: setup b5 later for 'sync on green' option
//end remove DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
DXIW(MISCCTRL,0x9b);
snooze(250);
//various init (as bios) /* re-enable pixelclock oscillations */
CFGW(OPTION, ((CFGR(OPTION)&0xf8404164) | (si->ps.option&0x207e00)) ); DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
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);
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 /* set the system clocks to powergraphics speed */
( LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
((si->ps.option&0x200000) == 0) && g450_dac_set_sys_pll();
((si->ps.maccess&0x200) == 0)
) /* '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 not 'EMRSW RAM-option' available */
if (!(si->ps.v5_mem_type & 0x0100))
if ((si->ps.maccess&0x100) == 0) {
/* 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); /* create positive flank to generate memory reset */
temp &=0xffff80ff; ACCW(MACCESS,ACCR(MACCESS) & 0xffff7fff);
temp = temp|((temp&0x8000)>>1)|0x8000; ACCW(MACCESS,ACCR(MACCESS) | 0x00008000);
ACCW(MACCESS, temp); snooze(250);
temp &= 0xffff7fff; /* start memory refresh */
ACCW(MACCESS, temp); 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; /* calculate powergraphics CAS-latency from pins CAS-latency, and update register setting */
temp = (temp &0x7) + 3; ACCW(MCTLWTST,
temp |= si->ps.mem_ctl &0xfffffff8; ((si->ps.mctlwtst_reg & 0xfffffff8) | pwr_cas[(si->ps.mctlwtst_reg & 0x07)]));
ACCW(MCTLWTST, temp);
} }
temp = CFGR(OPTION); /*enable writing to crtc registers*/
temp &=0xffe07fff; VGAW_I(CRTC,0x11,0);
temp |= si->ps.option&0x1f8000; //fixme..
CFGW(OPTION, temp); 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; return B_OK;
} }
@@ -664,27 +763,27 @@ status_t gx00_general_dac_select(int dac)
/*MISCCTRL, clock src,...*/ /*MISCCTRL, clock src,...*/
switch(dac) switch(dac)
{ {
case DS_CRTCDAC_CRTC2MAVEN: /*CRTC->DAC,CRTC2->MAFC*/ case DS_CRTC1DAC_CRTC2MAVEN:
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); /*internal clk*/ DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); /*internal clk*/
CR2W(CTL,(CR2R(CTL)&0xffe00779)|0xD0000002); /*external clk*/ CR2W(CTL,(CR2R(CTL)&0xffe00779)|0xD0000002); /*external clk*/
VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0x77)); VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0x77));
DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x82); DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x82);
break; break;
case DS_CRTCMAVEN_CRTC2DAC: /*CRTC->MAVEN,CRTC2->DAC*/ case DS_CRTC1MAVEN_CRTC2DAC:
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x2); /*external clk*/ DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x2); /*external clk*/
CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x1<<20)); /*internal clk*/ CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x1<<20)); /*internal clk*/
VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)|0x88)); VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)|0x88));
DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x02); DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x02);
break; break;
case DS_CRTCDAC_CRTC2DAC2: case DS_CRTC1CON1_CRTC2CON2:
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:
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); /*internal clk*/ DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); /*internal clk*/
CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x0<<20)); /*internal clk - no DAC PTR*/ 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; break;
default: default:
return B_ERROR; return B_ERROR;
@@ -1,13 +1,17 @@
/* /*
* i2c interface for the G400 MAVEN under BeOS * i2c interface for the G400 MAVEN under BeOS
* Mark Watson 06/2000
* *
* Provides I2CR,I2CW - functions to parallel DACW,DACR * Provides I2CR,I2CW - functions to parallel DACW,DACR
* Bus is run slowly because I do not know how fast the MAVEN is! * Bus should be run at max. 100kHz: see original Philips I2C specification
* *
* Much help was provided by observing the Linux i2c code, * Much help was provided by observing the Linux i2c code,
* so thanks go to: Gerd Knorr * so thanks go to: Gerd Knorr
*
* Other authors:
* Mark Watson 6/2000,
* Rudolf Cornelissen 12/2002
*/ */
#define MODULE_BIT 0x00004000 #define MODULE_BIT 0x00004000
#include "mga_std.h" #include "mga_std.h"
@@ -19,6 +23,48 @@
#define I2C_CLOCK 0x20 #define I2C_CLOCK 0x20
#define I2C_DATA 0x10 #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 *low level hardware access
*/ */
+142 -268
View File
@@ -2,254 +2,13 @@
/* some bits are hacks, where PINS is not known */ /* some bits are hacks, where PINS is not known */
/* Authors: /* Authors:
Mark Watson 2/2000, Mark Watson 2/2000,
Rudolf Cornelissen 10/2002 Rudolf Cornelissen 10-11/2002
*/ */
#define MODULE_BIT 0x00002000 #define MODULE_BIT 0x00002000
#include "mga_std.h" #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 */ /* Parse the BIOS PINS structure if there */
status_t parse_pins () status_t parse_pins ()
{ {
@@ -380,9 +139,15 @@ status_t pins1_read(uint8 *pins, uint8 length)
// bool secondary_dvi; // bool secondary_dvi;
// uint32 memory_size; /* memory in Mb */ // uint32 memory_size; /* memory in Mb */
// uint32 mctlwtst_reg; /* memory control waitstate register */ // uint32 mctlwtst_reg; /* memory control waitstate register */
// uint32 memrdbk_reg; /* memory readback register */
// uint32 option_reg; /* option 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_clk_div; /* pins v3 memory and system clock division factors */
// uint8 v3_mem_type; /* pins v3 memory type info */ // uint8 v3_mem_type; /* pins v3 memory type info */
// uint16 v5_mem_type; /* pins v5 memory type info */
// bool sdram; // bool sdram;
//end remove later on here. //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 [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 [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 [47] < si->ps.std_engine_clock) si->ps.std_engine_clock = pins[47];
if (pins[52] & 0x01) if ((si->ps.card_type == G200) && (pins[58] & 0x04))
si->ps.std_engine_clock *= 3; {
/* G200 can work without divisor */
si->ps.std_engine_clock *= 1;
}
else 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; if (pins[52] & 0x20) si->ps.f_ref = 14.31818;
else si->ps.f_ref = 27.00000; 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); si->ps.memory_size = 2 << ((pins[55] & 0xc0) >> 6);
/* more memory specifics */ /* more memory specifics */
si->ps.mctlwtst_reg = (pins[51] << 24) | (pins[50] << 16) | (pins[49] << 8) | pins [48]; 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_clk_div = pins[52];
si->ps.v3_mem_type = pins[54]; 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 */ /* for cards using this version of PINS both functions are in maven */
si->ps.secondary_head = !(pins[59] & 0x01); si->ps.secondary_head = !(pins[59] & 0x01);
si->ps.secondary_tvout = !(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; si->ps.option_reg = 0;
/* calculate refresh timer info-bits for 15uS interval (or shorter). See G100/G200 specs */ /* calculate refresh timer info-bits for 15uS interval (or shorter). See G100/G200 specs */
/* calculate std memory clock period (nS) */ /* calculate std memory clock period (nS) */
if (pins[52] & 0x02) if ((si->ps.card_type == G200) && (pins[58] & 0x08))
/* only used on G200, not on G100 */ {
mclk_period = 3000.0 / si->ps.std_engine_clock; /* G200 can work without Mclk divisor */
mclk_period = 1000.0 / si->ps.std_engine_clock;
}
else 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! */ /* calculate needed setting, 'round-down' result! */
rfhcnt = (uint32)(((15000 / mclk_period) - 1) / 64); rfhcnt = (uint32)(((15000 / mclk_period) - 1) / 64);
/* check for register limit */ /* check for register limit */
if (rfhcnt > 0x3f) rfhcnt = 0x3f; if (rfhcnt > 0x3f) rfhcnt = 0x3f;
/* add to option register */ /* add to option register */
si->ps.option_reg |= (rfhcnt << 15); 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 */ /* assuming the only possible panellink will be on the first head */
si->ps.primary_dvi = !(pins[59] & 0x40); 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_16 = 136;
si->ps.max_dac2_clock_32dh = 136; si->ps.max_dac2_clock_32dh = 136;
si->ps.max_dac2_clock_32 = 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; 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) status_t pins4_read(uint8 *pins, uint8 length)
{ {
/* used to calculate RAM refreshrate */
float mclk_period;
uint32 rfhcnt;
if (length != 128) if (length != 128)
{ {
LOG(8,("INFO: wrong PINS length, expected 128, got %d\n", length)); 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; else si->ps.f_ref = 27.00000;
si->ps.memory_size = 4 << ((pins[92] >> 2) & 0x03); 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 */ /* for cards using this version of PINS both functions are in maven */
si->ps.secondary_head = !(pins[91] & 0x01); 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.max_video_vco = si->ps.max_pixel_vco;
si->ps.min_video_vco = 50; si->ps.min_video_vco = 50;
//todo:
// uint32 mctlwtst_reg;
// uint32 option_reg;
// bool sdram;
/* not used here: */ /* 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_clk_div = 0;
si->ps.v3_mem_type = 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; return B_OK;
} }
@@ -624,13 +473,27 @@ status_t pins5_read(uint8 *pins, uint8 length)
si->ps.memory_size = ((pins[114] & 0x03) + 1) * 8; si->ps.memory_size = ((pins[114] & 0x03) + 1) * 8;
if ((pins[114] & 0x07) > 3) 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; si->ps.memory_size = 8;
} }
if (pins[110] & 0x01) si->ps.f_ref = 14.31818; if (pins[110] & 0x01) si->ps.f_ref = 14.31818;
else si->ps.f_ref = 27.00000; 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_head = (pins[117] & 0x70);
si->ps.secondary_tvout = (pins[117] & 0x40); si->ps.secondary_tvout = (pins[117] & 0x40);
si->ps.primary_dvi = (pins[117] & 0x02); 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_8 = 0;
si->ps.max_dac2_clock_24 = 0; si->ps.max_dac2_clock_24 = 0;
//todo:
// uint32 mctlwtst_reg;
// uint32 option_reg;
// bool sdram;
/* not used here: */ /* not used here: */
si->ps.v3_option2_reg = 0;
si->ps.v3_clk_div = 0; si->ps.v3_clk_div = 0;
si->ps.v3_mem_type = 0; si->ps.v3_mem_type = 0;
return B_OK; return B_OK;
@@ -697,9 +556,15 @@ void fake_pins(void)
si->ps.std_engine_clock = 0; si->ps.std_engine_clock = 0;
si->ps.std_engine_clock_dh = 0; si->ps.std_engine_clock_dh = 0;
si->ps.mctlwtst_reg = 0; si->ps.mctlwtst_reg = 0;
si->ps.memrdbk_reg = 0;
si->ps.option_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_clk_div = 0;
si->ps.v3_mem_type = 0; si->ps.v3_mem_type = 0;
si->ps.v5_mem_type = 0;
} }
void pinsmil2_fake(void) void pinsmil2_fake(void)
@@ -743,6 +608,7 @@ void pinsg100_fake(void)
/* presume 2Mb RAM mounted */ /* presume 2Mb RAM mounted */
si->ps.memory_size = 2; si->ps.memory_size = 2;
//fixme: should be overrule-able via mga.settings for G100. //fixme: should be overrule-able via mga.settings for G100.
//fail-safe mode for now:
si->ps.sdram = true; si->ps.sdram = true;
} }
@@ -823,11 +689,10 @@ void pinsg400_fake(void)
/* presume 4Mb RAM mounted */ /* presume 4Mb RAM mounted */
si->ps.memory_size = 4; si->ps.memory_size = 4;
/* ask the G400 what type of RAM it has been set to by it's BIOS */ /* ask the G400 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);
//end todo.
} }
/* this routine is currently unused, because G400MAX is detected via pins! */
void pinsg400max_fake(void) void pinsg400max_fake(void)
{ {
/* 'worst case' scenario defaults, overrule-able via mga.settings if needed */ /* 'worst case' scenario defaults, overrule-able via mga.settings if needed */
@@ -865,8 +730,7 @@ void pinsg400max_fake(void)
/* presume 4Mb RAM mounted */ /* presume 4Mb RAM mounted */
si->ps.memory_size = 4; si->ps.memory_size = 4;
/* ask the G400MAX what type of RAM it has been set to by it's BIOS */ /* 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) 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 */ /* ask the G450 what type of RAM it has been set to by it's BIOS */
//todo: //todo:
// si->ps.sdram = !(CFGR(OPTION) & 0x00004000); // si->ps.sdram = !(CFGR(OPTION) & 0x00004000);
//fail-safe mode for now:
si->ps.sdram = true;
} }
void pinsg550_fake(void) 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 */ /* ask the G550 what type of RAM it has been set to by it's BIOS */
//todo: //todo:
// si->ps.sdram = !(CFGR(OPTION) & 0x00004000); // si->ps.sdram = !(CFGR(OPTION) & 0x00004000);
//fail-safe mode for now:
si->ps.sdram = true;
} }
void dump_pins(void) 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")); 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,("card memory_size: %dMb\n", si->ps.memory_size));
LOG(2,("mctlwtst register: $%08x\n", si->ps.mctlwtst_reg)); 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,("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_clock_div: $%02x\n", si->ps.v3_clk_div));
LOG(2,("v3_mem_type: $%02x\n", si->ps.v3_mem_type)); 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: ")); LOG(2,("sdram: "));
if (si->ps.sdram) LOG(2,("SDRAM card\n")); else LOG(2,("SGRAM card\n")); if (si->ps.sdram) LOG(2,("SDRAM card\n")); else LOG(2,("SGRAM card\n"));
LOG(2,("INFO: end pinsdump.\n")); LOG(2,("INFO: end pinsdump.\n"));
@@ -1,6 +1,7 @@
/*general card functions*/ /*general card functions*/
status_t gx00_general_powerup(); status_t gx00_general_powerup();
status_t mga_set_cas_latency(); status_t mga_set_cas_latency();
status_t gx50_general_output_select();
status_t gx00_general_dac_select(int); status_t gx00_general_dac_select(int);
status_t gx00_general_wait_retrace(); status_t gx00_general_wait_retrace();
//status_t gx00_general_bios_to_powergraphics(); //status_t gx00_general_bios_to_powergraphics();
@@ -27,9 +28,6 @@ status_t i2c_maven_probe(void);
/*card info functions*/ /*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 parse_pins(void);
status_t pins1_read(uint8 *pins, uint8 length); status_t pins1_read(uint8 *pins, uint8 length);
status_t pins2_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_pix_pll_find(display_mode target,float * result,uint8 *,uint8 *,uint8 *, uint8);
status_t gx00_dac_set_pix_pll(display_mode target); 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 g400_dac_set_sys_pll();
status_t g200_dac_set_sys_pll(); status_t g200_dac_set_sys_pll();
status_t g100_dac_set_sys_pll(); status_t g100_dac_set_sys_pll();
@@ -123,9 +122,13 @@ status_t gx00_acc_wait_idle();
/*backend scaler functions*/ /*backend scaler functions*/
status_t check_overlay_capability(uint32 feature); 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(); status_t gx00_release_bes();
/* I2C functions */
status_t i2c_sec_tv_adapter();
/*driver structures and enums*/ /*driver structures and enums*/
enum{BPP8=0,BPP15=1,BPP16=2,BPP24=3,BPP32DIR=4,BPP32=7}; 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" #accelerant "mga.accelerant"
# mga.accelerant parameters # mga.accelerant parameters
usebios true # if true rely on bios to coldstart the card instead of by the driver usebios false # if true rely on bios to coldstart the card instead of driver
# currently also: if false use BIOS PINS config info, otherwise just guess...
#memory 2 # in MB, override builtin memory size detection #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 0x00000000 # nothing logged, except errors, is default
#logmask 0x80000000 # log card physical features #logmask 0x80000000 # log card physical features
#logmask 0x80000000 # log following mask #logmask 0x80000000 # log following mask