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