From 71194a68c72f6740bce4927195482d6508721a16 Mon Sep 17 00:00:00 2001 From: shatty Date: Thu, 18 Dec 2003 16:42:54 +0000 Subject: [PATCH] openBeOS_Matrox_V0.15_src git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5703 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../private/graphics/matrox/DriverInterface.h | 19 +- src/add-ons/accelerants/matrox/GetModeInfo.c | 2 + .../accelerants/matrox/InitAccelerant.c | 36 ++- src/add-ons/accelerants/matrox/Jamfile | 4 + .../accelerants/matrox/ProposeDisplayMode.c | 49 ++- .../accelerants/matrox/SetDisplayMode.c | 239 +++++++++------ .../accelerants/matrox/engine/mga_acc.c | 80 +++-- .../accelerants/matrox/engine/mga_crtc.c | 285 ++++++++++-------- .../accelerants/matrox/engine/mga_crtc2.c | 149 +++++++-- .../accelerants/matrox/engine/mga_general.c | 64 ++-- .../accelerants/matrox/engine/mga_maven.c | 146 +++++++-- .../accelerants/matrox/engine/mga_maventv.c | 205 ++++++++++++- .../accelerants/matrox/engine/mga_proto.h | 19 +- .../accelerants/matrox/engine/mga_support.c | 10 +- .../kernel/drivers/graphics/matrox/Jamfile | 10 + .../kernel/drivers/graphics/matrox/driver.c | 5 +- .../drivers/graphics/matrox/mga.settings | 2 +- 17 files changed, 953 insertions(+), 371 deletions(-) diff --git a/headers/private/graphics/matrox/DriverInterface.h b/headers/private/graphics/matrox/DriverInterface.h index 74d2c961a7..d801c89574 100644 --- a/headers/private/graphics/matrox/DriverInterface.h +++ b/headers/private/graphics/matrox/DriverInterface.h @@ -5,7 +5,7 @@ Other authors: Mark Watson; Apsed; - Rudolf Cornelissen 10/2002-4/2003. + Rudolf Cornelissen 10/2002-12/2003. */ #ifndef DRIVERINTERFACE_H @@ -51,6 +51,7 @@ typedef struct { #define TV_PAL (1<<9) #define TV_NTSC (2<<9) #define TV_CAPABLE (1<<11) +#define TV_VIDEO (1<<12) #define SKD_MOVE_CURSOR 0x00000001 #define SKD_PROGRAM_CLUT 0x00000002 @@ -158,6 +159,9 @@ typedef struct { uint32 count; /* last dwgsync slot used */ uint32 last_idle; /* last dwgsync slot we *know* the engine was idle after */ benaphore lock; /* for serializing access to the acceleration engine */ + uint32 src_dst; /* G100 pre SRCORG/DSTORG registers */ + uint8 y_lin; /* MIL1/2 adress linearisation does not always work */ + uint8 depth; } engine; /* card info - information gathered from PINS (and other sources) */ @@ -221,13 +225,20 @@ typedef struct { uint16 v5_mem_type; /* pins v5 memory type info */ } ps; - /*mirror of the ROM (copied in driver, because may not be mapped permanently - only over fb)*/ + /* mirror of the ROM (copied in driver, because may not be mapped permanently - only over fb) */ uint8 rom_mirror[32768]; - /*CRTC delay -> used in timing for MAVEN, depending on which CRTC is driving it*/ + /* CRTC delay -> used in timing for MAVEN, depending on which CRTC is driving it */ uint8 crtc_delay; - /* apsed: some configuration settings from ~/config/settings/kernel/drivers/mga.settings if exists */ + /* MAVEN sync polarity offset from 'reset' situation: MAVEN sync polarity setup + * works in a serial fashion without readback or handy reset options! */ + uint8 maven_syncpol_offset; + + /* On G450/G550 we need this info for secondary head DPMS functionality */ + bool crossed_conns; + + /* apsed: some configuration settings from ~/config/settings/kernel/drivers/mga.settings if exists */ settings settings; struct diff --git a/src/add-ons/accelerants/matrox/GetModeInfo.c b/src/add-ons/accelerants/matrox/GetModeInfo.c index 12fcd463c1..22a18323c6 100644 --- a/src/add-ons/accelerants/matrox/GetModeInfo.c +++ b/src/add-ons/accelerants/matrox/GetModeInfo.c @@ -20,6 +20,8 @@ status_t GET_DISPLAY_MODE(display_mode *current_mode) /* check for NULL pointer */ if (current_mode == NULL) return B_ERROR; + LOG(4, ("GET_DISPLAY_MODE: returning current mode\n")); + *current_mode = si->dm; return B_OK; } diff --git a/src/add-ons/accelerants/matrox/InitAccelerant.c b/src/add-ons/accelerants/matrox/InitAccelerant.c index d20ae2fa45..4af18f4773 100644 --- a/src/add-ons/accelerants/matrox/InitAccelerant.c +++ b/src/add-ons/accelerants/matrox/InitAccelerant.c @@ -4,7 +4,7 @@ Other authors: Mark Watson, - Rudolf Cornelissen 10/2002-3/2003. + Rudolf Cornelissen 10/2002-12/2003. */ #define MODULE_BIT 0x00800000 @@ -75,7 +75,7 @@ error0: return result; } -/* Clean up code shared between primary and cloned accelrants */ +/* Clean up code shared between primary and cloned accelerants */ static void uninit_common(void) { /* release the memory mapped registers */ delete_area(regs_area); @@ -115,7 +115,10 @@ status_t INIT_ACCELERANT(int the_fd) { /* bail out if the common initialization failed */ if (result != B_OK) goto error0; // LOG now available: !NULL si - + + /* signal CRTC2 DPMS on G450/G550 which connector to program (before powerup) */ + si->crossed_conns = false; + /* call the device specific init code */ result = gx00_general_powerup(); @@ -235,11 +238,23 @@ status_t CLONE_ACCELERANT(void *data) { char path[MAXPATHLEN]; /* the data is the device name */ - strcpy(path, "/dev"); + /* Note: the R4 graphics driver kit is in error here (missing trailing '/') */ + strcpy(path, "/dev/"); strcat(path, (const char *)data); /* open the device, the permissions aren't important */ fd = open(path, B_READ_WRITE); - if (fd < 0) { + if (fd < 0) + { + /* we can't use LOG because we didn't get the shared_info struct.. */ + char fname[64]; + FILE *myhand = NULL; + + sprintf (fname, "/boot/home/" DRIVER_PREFIX ".accelerant.0.log"); + myhand=fopen(fname,"a+"); + fprintf(myhand, "CLONE_ACCELERANT: couldn't open kerneldriver %s! Aborting.\n", path); + fclose(myhand); + + /* abort with resultcode from open attempt on kerneldriver */ result = fd; goto error0; } @@ -282,13 +297,18 @@ error0: void UNINIT_ACCELERANT(void) { if (accelerantIsClone) + { LOG(4,("UNINIT_ACCELERANT: shutting down clone accelerant.\n")); + } else + { LOG(4,("UNINIT_ACCELERANT: shutting down primary accelerant.\n")); - /*delete benaphore*/ - DELETE_BEN(si->engine.lock); - DELETE_BEN(si->overlay.lock); + /* delete benaphores ONLY if we are the primary accelerant */ + DELETE_BEN(si->engine.lock); + DELETE_BEN(si->overlay.lock); + } + /* free our mode list area */ delete_area(my_mode_list_area); /* paranoia */ diff --git a/src/add-ons/accelerants/matrox/Jamfile b/src/add-ons/accelerants/matrox/Jamfile index 4dcc504fe5..b6b43847a8 100644 --- a/src/add-ons/accelerants/matrox/Jamfile +++ b/src/add-ons/accelerants/matrox/Jamfile @@ -21,6 +21,10 @@ Addon mga.accelerant : accelerants : : false : libmatrox_engine.a ; +Package openbeos-matrox-1.0 : + mga.accelerant : + boot home config add-ons accelerants ; + Depends mga.accelerant : mga.driver ; SubInclude OBOS_TOP src add-ons accelerants matrox engine ; diff --git a/src/add-ons/accelerants/matrox/ProposeDisplayMode.c b/src/add-ons/accelerants/matrox/ProposeDisplayMode.c index ba728da42b..5241bbaacd 100644 --- a/src/add-ons/accelerants/matrox/ProposeDisplayMode.c +++ b/src/add-ons/accelerants/matrox/ProposeDisplayMode.c @@ -4,7 +4,7 @@ Other authors for MGA driver: Mark Watson, - Rudolf Cornelissen 9/2002-4/2003 + Rudolf Cornelissen 9/2002-12/2003 */ #define MODULE_BIT 0x00400000 @@ -74,9 +74,10 @@ status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, con { status_t status = B_OK; float pix_clock_found; - uint8 m,n,p; + uint8 m,n,p, bpp; status_t result; uint32 max_vclk, row_bytes, pointer_reservation; + bool acc_mode; double target_refresh = ((double)target->timing.pixel_clock * 1000.0) / ( (double)target->timing.h_total * @@ -164,7 +165,7 @@ status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, con target->virtual_height = target->timing.v_display; /* nail virtual size and 'subsequently' calculate rowbytes */ - result = gx00_general_validate_pic_size (target, &row_bytes); + result = gx00_general_validate_pic_size (target, &row_bytes, &acc_mode); if (result == B_ERROR) { LOG(4, ("PROPOSEMODE: could not validate virtual picture size, aborted.\n")); @@ -292,7 +293,8 @@ status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, con * mode (fixed), and all modes support DPMS (fixed); * We support scrolling and panning in every mode, so we 'send a signal' to * BWindowScreen.CanControlFrameBuffer() by setting B_SCROLL. */ - //fixme: secondary head does not support DPMS... + /* BTW: B_PARALLEL_ACCESS in combination with a hardcursor enables + * BDirectWindow windowed modes. */ target->flags |= (B_PARALLEL_ACCESS | B_8_BIT_DAC | B_DPMS | B_SCROLL); /* determine the 'would be' max. pixelclock for the second DAC for the current videomode if dualhead were activated */ @@ -300,33 +302,64 @@ status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, con { case B_CMAP8: max_vclk = si->ps.max_dac2_clock_8; + bpp = 1; break; case B_RGB15_LITTLE: case B_RGB16_LITTLE: max_vclk = si->ps.max_dac2_clock_16; + bpp = 2; break; case B_RGB24_LITTLE: max_vclk = si->ps.max_dac2_clock_24; + bpp = 3; break; case B_RGB32_LITTLE: max_vclk = si->ps.max_dac2_clock_32dh; + bpp = 4; break; default: /* use fail-safe value */ max_vclk = si->ps.max_dac2_clock_32dh; + bpp = 4; break; } /* set DUALHEAD_CAPABLE if suitable */ //fixme: update for independant secondary head use! (reserve fixed memory then) if (si->ps.secondary_head && - (((si->ps.memory_size * 1024 * 1024) - pointer_reservation) >= - /* note: extra line for maven vblank included here! */ - (row_bytes * (target->virtual_height + 1) * 2)) && ((target->space == B_RGB16_LITTLE) || (target->space == B_RGB32_LITTLE)) && (target->timing.pixel_clock <= (max_vclk * 1000))) { - target->flags |= DUALHEAD_CAPABLE; + /* extra line for G400 MAVEN vblank design fault workaround needed! */ + uint16 vblank_fix = 0; + if (si->ps.card_type <= G400MAX) vblank_fix = 1; + + switch (target->flags & DUALHEAD_BITS) + { + case DUALHEAD_ON: + case DUALHEAD_SWITCH: + if ((((si->ps.memory_size * 1024 * 1024) - pointer_reservation) >= + (row_bytes * (target->virtual_height + vblank_fix))) && + ((row_bytes / bpp) >= (target->timing.h_display * 2))) + { + target->flags |= DUALHEAD_CAPABLE; + } + break; + case DUALHEAD_CLONE: + if (((si->ps.memory_size * 1024 * 1024) - pointer_reservation) >= + (row_bytes * (target->virtual_height + vblank_fix))) + { + target->flags |= DUALHEAD_CAPABLE; + } + break; + case DUALHEAD_OFF: + if (((si->ps.memory_size * 1024 * 1024) - pointer_reservation) >= + (row_bytes * (target->virtual_height + vblank_fix) * 2)) + { + target->flags |= DUALHEAD_CAPABLE; + } + break; + } } /* set TV_CAPABLE if suitable: pixelclock is not important (defined by TVstandard) */ diff --git a/src/add-ons/accelerants/matrox/SetDisplayMode.c b/src/add-ons/accelerants/matrox/SetDisplayMode.c index d2e1ab7b56..2fa9078174 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 11/2002-4/2003 + Rudolf Cornelissen 11/2002-12/2003 */ #define MODULE_BIT 0x00200000 @@ -50,10 +50,7 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) uint8 colour_depth1 = 32; status_t result; uint32 startadd,startadd_right; -// apsed TODO startadd is 19 bits if < g200 - - uint8 display,h,v; - si->switched_crtcs = false; + bool display, h, v; /* Adjust mode to valid one and fail if invalid */ target /*= bounds*/ = *mode_to_set; @@ -78,19 +75,23 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) } LOG(1, ("SETMODE: (CONT.) validated command modeflags: $%08x\n", target.flags)); + /* overlay engine, cursor and MOVE_DISPLAY need to know the status even when + * in singlehead mode */ + si->switched_crtcs = false; + /* disable interrupts using the kernel driver */ interrupt_enable(false); /* find current DPMS state, then turn off screen(s) */ - gx00_crtc_dpms_fetch(&display,&h,&v); - gx00_crtc_dpms(0,0,0); - if (si->ps.secondary_head) g400_crtc2_dpms(0,0,0); + gx00_crtc_dpms_fetch(&display, &h, &v); + gx00_crtc_dpms(false, false, false); + if (si->ps.secondary_head) g400_crtc2_dpms(false, false, false); /*where in framebuffer the screen is (should this be dependant on previous MOVEDISPLAY?)*/ startadd = si->fbc.frame_buffer - si->framebuffer; /* calculate and set new mode bytes_per_row */ - gx00_general_validate_pic_size (&target, &si->fbc.bytes_per_row); + gx00_general_validate_pic_size (&target, &si->fbc.bytes_per_row, &si->acc_mode); /*Perform the very long mode switch!*/ if (target.flags & DUALHEAD_BITS) /*if some dualhead mode*/ @@ -169,15 +170,16 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) /* calculate needed MAVEN-CRTC delay: formula valid for straight-through CRTC's */ si->crtc_delay = 44 + 0 * (colour_depth2 == 16); - /* setup vertical timing adjust for crtc1 and crtc2 for straight-through CRTC's */ - /* (extra "blanking" line for MAVEN) */ - target2.timing.v_display++; - /* set the outputs */ switch (si->ps.card_type) { case G400: case G400MAX: + /* setup vertical timing adjust for crtc connected to the MAVEN: + * assuming connected straight through. */ + /* (extra "blanking" line for MAVEN hardware design fault) */ + target2.timing.v_display++; + switch (target.flags & DUALHEAD_BITS) { case DUALHEAD_ON: @@ -203,17 +205,15 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) si->switched_crtcs = false; /* re-calculate MAVEN-CRTC delay: formula valid for crossed CRTC's */ si->crtc_delay = 17 + 4 * (colour_depth1 == 16); - /* re-setup vertical timing adjust for crtc1 and crtc2 for crossed CRTC's */ - /* (extra "blanking" line for MAVEN) */ + /* re-setup vertical timing adjust for crtc connected to the MAVEN: + * cross connected. */ + /* (extra "blanking" line for MAVEN hardware design fault) */ target.timing.v_display++; target2.timing.v_display--; } break; } break; - //fixme: - //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) @@ -313,28 +313,12 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) } /* set the timing */ - result = gx00_crtc_set_timing /*crtc1*/ - ( - target.timing.h_display, - target.timing.h_sync_start, - target.timing.h_sync_end, - target.timing.h_total, - target.timing.v_display, - target.timing.v_sync_start, - target.timing.v_sync_end, - target.timing.v_total, - target.timing.flags&B_POSITIVE_HSYNC, - target.timing.flags&B_POSITIVE_VSYNC - ); + gx00_crtc_set_timing(target); /* we do not need to setup CRTC2 here for a head that's in TVout mode */ if (!(target2.flags & TV_BITS)) result = g400_crtc2_set_timing(target2); /* TVout support: setup CRTC2 and it's pixelclock */ - if (si->ps.secondary_tvout && (target2.flags & TV_BITS)) - { - si->crtc_delay += 5; - maventv_init(target2); - } + if (si->ps.secondary_tvout && (target2.flags & TV_BITS)) maventv_init(target2); } else /* single head mode */ { @@ -389,21 +373,9 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) default: break; } - + /* set the timing */ - result = gx00_crtc_set_timing /*crtc1*/ - ( - target.timing.h_display, - target.timing.h_sync_start, - target.timing.h_sync_end, - target.timing.h_total, - target.timing.v_display, - target.timing.v_sync_start, - target.timing.v_sync_end, - target.timing.v_total, - target.timing.flags&B_POSITIVE_HSYNC, - target.timing.flags&B_POSITIVE_VSYNC - ); + gx00_crtc_set_timing(target); //fixme: shut-off the videoPLL if it exists... } @@ -412,17 +384,17 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) si->dm = target; /* turn screen one on */ - gx00_crtc_dpms(display,h,v); + gx00_crtc_dpms(display, h, v); /* turn screen two on if a dualhead mode is active */ - if (target.flags & DUALHEAD_BITS) g400_crtc2_dpms(display,h,v); + if (target.flags & DUALHEAD_BITS) g400_crtc2_dpms(display, h, v); /* set up acceleration for this mode */ - si->dm.virtual_height += 1;//for clipping! gx00_acc_init(); - si->dm.virtual_height -= 1; - /* clear line at bottom of screen (for maven) if dualhead mode */ - gx00_acc_rectangle(0,si->dm.virtual_width+1,si->dm.virtual_height,1,0); + /* clear line at bottom of screen if dualhead mode: + * MAVEN hardware design fault 'fix'. */ + if ((target.flags & DUALHEAD_BITS) && (si->ps.card_type <= G400MAX)) + gx00_maven_clrline(); MSG(("SETMODE: booted since %f mS\n", system_time()/1000.0)); @@ -574,40 +546,88 @@ void SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags gx00_dac_palette(r,g,b); } - -/* masks for DPMS control bits */ -enum { - H_SYNC_OFF = 0x01, - V_SYNC_OFF = 0x02, - DISPLAY_OFF = 0x04, - BITSMASK = H_SYNC_OFF | V_SYNC_OFF | DISPLAY_OFF -}; - /* Put the display into one of the Display Power Management modes. */ status_t SET_DPMS_MODE(uint32 dpms_flags) { interrupt_enable(false); LOG(4,("SET_DPMS_MODE: 0x%08x\n", dpms_flags)); - if (si->dm.flags&DUALHEAD_BITS) /*dualhead*/ + if (si->dm.flags & DUALHEAD_BITS) /* dualhead */ { switch(dpms_flags) { case B_DPMS_ON: /* H: on, V: on */ - gx00_crtc_dpms(1,1,1); - if (si->ps.secondary_head) g400_crtc2_dpms(1,1,1); + gx00_crtc_dpms(true, true, true); + if (si->ps.secondary_head) g400_crtc2_dpms(true, true, true); break; case B_DPMS_STAND_BY: - gx00_crtc_dpms(0,0,1); - if (si->ps.secondary_head) g400_crtc2_dpms(0,0,1); + if (si->settings.greensync) + { + /* blank screen, but keep sync running */ + gx00_crtc_dpms(false, true, true); + } + else + { + gx00_crtc_dpms(false, false, true); + } + if (si->ps.secondary_head) + { + if ((si->dm.flags & TV_BITS) && (si->ps.card_type > G400MAX)) + { + /* keep display enabled in TVout modes for G450 and G550! */ + g400_crtc2_dpms(true, false, true); + } + else + { + g400_crtc2_dpms(false, false, true); + } + } break; case B_DPMS_SUSPEND: - gx00_crtc_dpms(0,1,0); - if (si->ps.secondary_head) g400_crtc2_dpms(0,1,0); + if (si->settings.greensync) + { + /* blank screen, but keep sync running */ + gx00_crtc_dpms(false, true, true); + } + else + { + gx00_crtc_dpms(false, true, false); + } + if (si->ps.secondary_head) + { + if ((si->dm.flags & TV_BITS) && (si->ps.card_type > G400MAX)) + { + /* keep display enabled in TVout modes for G450 and G550! */ + g400_crtc2_dpms(true, true, false); + } + else + { + g400_crtc2_dpms(false, true, false); + } + } break; case B_DPMS_OFF: /* H: off, V: off, display off */ - gx00_crtc_dpms(0,0,0); - if (si->ps.secondary_head) g400_crtc2_dpms(0,0,0); + if (si->settings.greensync) + { + /* blank screen, but keep sync running */ + gx00_crtc_dpms(false, true, true); + } + else + { + gx00_crtc_dpms(false, false, false); + } + if (si->ps.secondary_head) + { + if ((si->dm.flags & TV_BITS) && (si->ps.card_type > G400MAX)) + { + /* keep display enabled in TVout modes for G450 and G550! */ + g400_crtc2_dpms(true, false, false); + } + else + { + g400_crtc2_dpms(false, false, false); + } + } break; default: LOG(8,("SET: Invalid DPMS settings (DH) 0x%08x\n", dpms_flags)); @@ -615,24 +635,48 @@ status_t SET_DPMS_MODE(uint32 dpms_flags) { return B_ERROR; } } - else /*singlehead*/ + else /* singlehead */ { switch(dpms_flags) { case B_DPMS_ON: /* H: on, V: on */ - gx00_crtc_dpms(1,1,1); + gx00_crtc_dpms(true, true, true); break; case B_DPMS_STAND_BY: - gx00_crtc_dpms(0,0,1); + if (si->settings.greensync) + { + /* blank screen, but keep sync running */ + gx00_crtc_dpms(false, true, true); + } + else + { + gx00_crtc_dpms(false, false, true); + } break; case B_DPMS_SUSPEND: - gx00_crtc_dpms(0,1,0); + if (si->settings.greensync) + { + /* blank screen, but keep sync running */ + gx00_crtc_dpms(false, true, true); + } + else + { + gx00_crtc_dpms(false, true, false); + } break; case B_DPMS_OFF: /* H: off, V: off, display off */ - gx00_crtc_dpms(0,0,0); + if (si->settings.greensync) + { + /* blank screen, but keep sync running */ + gx00_crtc_dpms(false, true, true); + } + else + { + gx00_crtc_dpms(false, false, false); + } break; default: - LOG(8,("SET: Invalid DPMS settings (DH) 0x%08x\n", dpms_flags)); + LOG(8,("SET: Invalid DPMS settings (SH) 0x%08x\n", dpms_flags)); interrupt_enable(true); return B_ERROR; } @@ -641,29 +685,34 @@ status_t SET_DPMS_MODE(uint32 dpms_flags) { return B_OK; } -/* - Report device DPMS capabilities. -*/ -uint32 DPMS_CAPABILITIES(void) { - return B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND|B_DPMS_OFF; +/* Report device DPMS capabilities. */ +uint32 DPMS_CAPABILITIES(void) +{ + if (si->settings.greensync) + /* we can blank the screen on CRTC1, G400 CRTC2 does not support intermediate + * modes anyway. */ + //fixme: G450/G550 support full DPMS on CRTC2... + return B_DPMS_ON | B_DPMS_OFF; + else + /* normally CRTC1 supports full DPMS (and on G450/G550 CRTC2 also).. */ + return B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF; } - -/* - Return the current DPMS mode. -*/ +/* Return the current DPMS mode. */ uint32 DPMS_MODE(void) { - uint8 display,h,v; - + bool display, h, v; + interrupt_enable(false); - gx00_crtc_dpms_fetch(&display,&h,&v); + gx00_crtc_dpms_fetch(&display, &h, &v); interrupt_enable(true); - if (display&h&v) + if (display && h && v) return B_DPMS_ON; - else if(v) + else if (si->settings.greensync) + return B_DPMS_OFF; + else if (v) return B_DPMS_STAND_BY; - else if(h) + else if (h) return B_DPMS_SUSPEND; else return B_DPMS_OFF; diff --git a/src/add-ons/accelerants/matrox/engine/mga_acc.c b/src/add-ons/accelerants/matrox/engine/mga_acc.c index 829171f0db..15b50d7783 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-4/2003. + Rudolf Cornelissen 10/2002-11/2003. */ #define MODULE_BIT 0x00080000 @@ -17,27 +17,23 @@ invert rectangle blit */ -/* G100 pre SRCORG/DSTORG registers */ -static uint32 src_dst; -/* MIL1/2 adress linearisation does not always work */ -static uint8 y_lin; -static uint8 depth; - /* needed by MIL 1/2 because of adress linearisation constraints */ #define ACCW_YDSTLEN(dst, len) do { \ - if (y_lin) { \ - ACCW(YDST,((dst)* (si->fbc.bytes_per_row / (depth >> 3))) >> 5); \ + if (si->engine.y_lin) { \ + ACCW(YDST,((dst)* (si->fbc.bytes_per_row / (si->engine.depth >> 3))) >> 5); \ ACCW(LEN,len); \ } else ACCW(YDSTLEN,((dst)<<16)|(len)); \ } while (0) status_t gx00_acc_wait_idle() { - volatile int i; - while (ACCR(STATUS)&(1<<16)) + /* wait until engine completely idle */ + while (ACCR(STATUS) & 0x00010000) { - for (i=0;i<10000;i++); /*spin in place so I do not hammer the bus*/ - }; + /* snooze a bit so I do not hammer the bus */ + snooze (100); + } + return B_OK; } @@ -55,9 +51,9 @@ status_t gx00_acc_init() } /* preset using hardware adress linearisation */ - y_lin = 0x00; + si->engine.y_lin = 0x00; /* reset depth */ - depth = 0; + si->engine.depth = 0; /* cleanup bitblt */ ACCW(OPMODE,0); @@ -70,15 +66,15 @@ status_t gx00_acc_init() { case B_CMAP8: ACCW(MACCESS, ((maccess & 0xfffffffc) | 0x00)); - depth = 8; + si->engine.depth = 8; break; case B_RGB15_LITTLE:case B_RGB16_LITTLE: ACCW(MACCESS, ((maccess & 0xfffffffc) | 0x01)); - depth = 16; + si->engine.depth = 16; break; case B_RGB32_LITTLE:case B_RGBA32_LITTLE: ACCW(MACCESS, ((maccess & 0xfffffffc) | 0x02)); - depth = 32; + si->engine.depth = 32; break; default: LOG(8,("ACC: init, invalid bit depth\n")); @@ -89,7 +85,7 @@ status_t gx00_acc_init() switch (si->ps.card_type) { case MIL1: - switch (si->fbc.bytes_per_row / (depth >> 3)) + switch (si->fbc.bytes_per_row / (si->engine.depth >> 3)) { case 640: case 768: @@ -105,14 +101,15 @@ status_t gx00_acc_init() break; default: /* we are using software adress linearisation */ - y_lin = 0x01; + si->engine.y_lin = 0x01; LOG(8,("ACC: using software adress linearisation\n")); break; } - ACCW(PITCH, (y_lin << 15) | ((si->fbc.bytes_per_row / (depth >> 3)) & 0x0FFF)); + ACCW(PITCH, (si->engine.y_lin << 15) | + ((si->fbc.bytes_per_row / (si->engine.depth >> 3)) & 0x0FFF)); break; case MIL2: - switch (si->fbc.bytes_per_row / (depth >> 3)) + switch (si->fbc.bytes_per_row / (si->engine.depth >> 3)) { case 512: case 640: @@ -131,22 +128,23 @@ status_t gx00_acc_init() break; default: /* we are using software adress linearisation */ - y_lin = 0x01; + si->engine.y_lin = 0x01; LOG(8,("ACC: using software adress linearisation\n")); break; } - ACCW(PITCH, (y_lin << 15) | ((si->fbc.bytes_per_row / (depth >> 3)) & 0x0FFF)); + ACCW(PITCH, (si->engine.y_lin << 15) | + ((si->fbc.bytes_per_row / (si->engine.depth >> 3)) & 0x0FFF)); break; case G100: /* always using hardware adress linearisation, because 2D/3D * engine works on every pitch multiple of 32 */ - ACCW(PITCH, ((si->fbc.bytes_per_row / (depth >> 3)) & 0x0FFF)); + ACCW(PITCH, ((si->fbc.bytes_per_row / (si->engine.depth >> 3)) & 0x0FFF)); break; default: /* G200 and up are equal.. */ /* always using hardware adress linearisation, because 2D/3D * engine works on every pitch multiple of 32 */ - ACCW(PITCH, ((si->fbc.bytes_per_row / (depth >> 3)) & 0x1FFF)); + ACCW(PITCH, ((si->fbc.bytes_per_row / (si->engine.depth >> 3)) & 0x1FFF)); break; } @@ -163,8 +161,8 @@ status_t gx00_acc_init() } /* init YDSTORG - apsed, if not inited, BitBlts may fails on <= G200 */ - src_dst = 0; - ACCW(YDSTORG, src_dst); + si->engine.src_dst = 0; + ACCW(YDSTORG, si->engine.src_dst); /* <= G100 uses this register as SRCORG/DSTORG replacement, but * MIL 1/2 does not need framebuffer space for the hardcursor! */ @@ -173,32 +171,32 @@ status_t gx00_acc_init() switch (si->dm.space) { case B_CMAP8: - src_dst = 1024 / 1; + si->engine.src_dst = 1024 / 1; break; case B_RGB15_LITTLE: case B_RGB16_LITTLE: - src_dst = 1024 / 2; + si->engine.src_dst = 1024 / 2; break; case B_RGB32_LITTLE: - src_dst = 1024 / 4; + si->engine.src_dst = 1024 / 4; break; default: LOG(8,("ACC: G100 hardcursor not supported for current colorspace\n")); return B_ERROR; } } - ACCW(YDSTORG,src_dst); + ACCW(YDSTORG, si->engine.src_dst); /* clipping */ /* i.e. highest and lowest X pixel adresses */ - ACCW(CXBNDRY,(((si->fbc.bytes_per_row / (depth >> 3)) - 1) << 16) | (0)); + ACCW(CXBNDRY,(((si->fbc.bytes_per_row / (si->engine.depth >> 3)) - 1) << 16) | (0)); /* Y pixel addresses must be linear */ /* lowest adress */ - ACCW(YTOP, 0 + src_dst); + ACCW(YTOP, 0 + si->engine.src_dst); /* highest adress */ ACCW(YBOT,((si->dm.virtual_height - 1) * - (si->fbc.bytes_per_row / (depth >> 3))) + src_dst); + (si->fbc.bytes_per_row / (si->engine.depth >> 3))) + si->engine.src_dst); return B_OK; } @@ -211,12 +209,12 @@ status_t gx00_acc_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint16 w,uint16 h uint32 b_start,b_end; /*find where the top,bottom and offset are*/ - offset = (si->fbc.bytes_per_row / (depth >> 3)); + offset = (si->fbc.bytes_per_row / (si->engine.depth >> 3)); - t_end = t_start = xs + (offset*ys) + src_dst; + t_end = t_start = xs + (offset*ys) + si->engine.src_dst; t_end += w; - b_end = b_start = xs + (offset*(ys+h)) + src_dst; + b_end = b_start = xs + (offset*(ys+h)) + si->engine.src_dst; b_end +=w; /* sgnzero bit _must_ be '0' before accessing SGN! */ @@ -280,12 +278,12 @@ status_t gx00_acc_transparent_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint1 return B_ERROR; /*find where the top,bottom and offset are*/ - offset = (si->fbc.bytes_per_row / (depth >> 3)); + offset = (si->fbc.bytes_per_row / (si->engine.depth >> 3)); - t_end = t_start = xs + (offset*ys) + src_dst; + t_end = t_start = xs + (offset*ys) + si->engine.src_dst; t_end += w; - b_end = b_start = xs + (offset*(ys+h)) + src_dst; + b_end = b_start = xs + (offset*(ys+h)) + si->engine.src_dst; b_end +=w; /* sgnzero bit _must_ be '0' before accessing SGN! */ diff --git a/src/add-ons/accelerants/matrox/engine/mga_crtc.c b/src/add-ons/accelerants/matrox/engine/mga_crtc.c index d9e9d55711..c41aca7fc2 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 11/2002-4/2003 + Rudolf Cornelissen 11/2002-12/2003 */ #define MODULE_BIT 0x00040000 @@ -15,82 +15,65 @@ status_t gx00_crtc_validate_timing( uint16 *vd_e,uint16 *vs_s,uint16 *vs_e,uint16 *vt ) { -/*horizontal*/ - /*make all parameters multiples of 8 and confine to required number of bits*/ - *hd_e&=0x7F8; - *hs_s&=0xFF8; - *hs_e&=0xFF8; - *ht &=0xFF8; +/* horizontal */ + /* make all parameters multiples of 8 */ + *hd_e &= 0x0ff8; /* 2048 is a valid value for this item! */ + *hs_s &= 0x0ff8; + *hs_e &= 0x0ff8; + *ht &= 0x0ff8; - /*confine to a reasonable width*/ - if (*hd_e<640) *hd_e=640; - if (*hd_e>2048) *hd_e=2048; + /* confine to required number of bits, taking logic into account */ + if (*hd_e > ((0x00ff + 1) << 3)) *hd_e = ((0x00ff + 1) << 3); + if (*hs_s > ((0x01ff - 1) << 3)) *hs_s = ((0x01ff - 1) << 3); + if (*hs_e > ( 0x01ff << 3)) *hs_e = ( 0x01ff << 3); + if (*ht > ((0x01ff + 5) << 3)) *ht = ((0x01ff + 5) << 3); - /*if horizontal total does not leave room for a sensible sync pulse, increase it!*/ - if (*ht<(*hd_e+80)) *ht=*hd_e+80; + /* NOTE: keep horizontal timing at multiples of 8! */ + /* confine to a reasonable width */ + if (*hd_e < 640) *hd_e = 640; + if (*hd_e > 2048) *hd_e = 2048; - /*make sure sync pulse is not during display*/ - if (*hs_e>(*ht-0x8)) *hs_e=*ht-0x8; - if (*hs_s<(*hd_e+0x8)) *hs_e=*hd_e+0x8; + /* if hor. total does not leave room for a sensible sync pulse, increase it! */ + if (*ht < (*hd_e + 80)) *ht = (*hd_e + 80); - /*correct sync pulse if it is too long*/ - if (*hs_e>(*hs_s+0xF8)) *hs_e=*hs_s+0xF8; + /* make sure sync pulse is not during display */ + if (*hs_e > (*ht - 8)) *hs_e = (*ht - 8); + if (*hs_s < (*hd_e + 8)) *hs_s = (*hd_e + 8); - /*fail if they are now outside required number of bits*/ - if ( - *hd_e!=(*hd_e&0x7F8) || - *hs_s!=(*hs_s&0xFF8) || - *hs_e!=(*hs_e&0xFF8) || - *ht !=(*ht &0xFF8) - ) - { - LOG(8,("CRTC:Horizontal timing fell out of bits\n")); - return B_ERROR; - } + /* correct sync pulse if it is too long: + * there are only 5 bits available to save this in the card registers! */ + if (*hs_e > (*hs_s + 0xf8)) *hs_e = (*hs_s + 0xf8); /*vertical*/ - /*squish to required number of bits*/ - *vd_e&=0x7FF; - *vs_s&=0xFFF; - *vs_e&=0xFFF; - *vt &=0xFFF; + /* confine to required number of bits, taking logic into account */ + if (*vd_e > 0x7ff ) *vd_e = 0x7ff ; /* linecomp max value = 0x7ff! */ + if (*vs_s > (0xfff - 1)) *vs_s = (0xfff - 1); + if (*vs_e > 0xfff ) *vs_e = 0xfff ; + if (*vt > (0xfff + 2)) *vt = (0xfff + 2); - /*confine to a reasonable height*/ - if (*vd_e<400) *vd_e=400; - if (*vd_e>2048) *vd_e=2048; + /* confine to a reasonable height */ + if (*vd_e < 480) *vd_e = 480; + if (*vd_e > 2047) *vd_e = 2047; /*if vertical total does not leave room for a sync pulse, increase it!*/ - if (*vt<(*vd_e+3)) *vt=*vd_e+3; + if (*vt < (*vd_e + 3)) *vt = (*vd_e + 3); - /*make sure sync pulse if not during display*/ - if (*vs_e>(*vt-1)) *vs_e=*vt-1; - if (*vs_s<(*vd_e+1)) *vs_s=*vd_e+1; + /* make sure sync pulse is not during display */ + if (*vs_e > (*vt - 1)) *vs_e = (*vt - 1); + if (*vs_s < (*vd_e + 1)) *vs_s = (*vd_e + 1); - /*correct sync pulse if it is too long*/ - if (*vs_e>(*vs_s+0xF)) *vs_e=*vs_s+0xF; + /* correct sync pulse if it is too long: + * there are only 4 bits available to save this in the card registers! */ + if (*vs_e > (*vs_s + 0x0f)) *vs_e = (*vs_s + 0x0f); - /*fail if now outside required number of bits*/ - if ( - *vd_e!=(*vd_e&0x7FF) || - *vs_s!=(*vs_s&0xFFF) || - *vs_e!=(*vs_e&0xFFF) || - *vt !=(*vt &0xFFF) - ) - { - LOG(8,("CRTC:Vertical timing fell out of bits\n")); - return B_ERROR; - } return B_OK; } - -/*set a mode line - inputs are in pixels*/ -status_t gx00_crtc_set_timing( - uint16 hd_e,uint16 hs_s,uint16 hs_e,uint16 ht, - uint16 vd_e,uint16 vs_s,uint16 vs_e,uint16 vt, - uint8 hsync_pos,uint8 vsync_pos -) +/* set a mode line - inputs are in pixels */ +status_t gx00_crtc_set_timing(display_mode target) { + uint8 temp; + uint32 htotal; /*total horizontal total VCLKs*/ uint32 hdisp_e; /*end of horizontal display (begins at 0)*/ uint32 hsync_s; /*begin of horizontal sync pulse*/ @@ -109,23 +92,25 @@ 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); //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); + /* Modify parameters as required by standard VGA */ + htotal = ((target.timing.h_total >> 3) - 5); + hdisp_e = ((target.timing.h_display >> 3) - 1); + hblnk_s = hdisp_e; + hblnk_e = (htotal + 4); + hsync_s = (target.timing.h_sync_start >> 3); + hsync_e = (target.timing.h_sync_end >> 3); - vtotal=vt-2; - vdisp_e=vd_e-1; - vsync_s=vs_s-1; - vsync_e=vs_e-1; - vblnk_s=vdisp_e; - vblnk_e=vtotal+1; + vtotal = target.timing.v_total - 2; + vdisp_e = target.timing.v_display - 1; + vblnk_s = vdisp_e; + vblnk_e = (vtotal + 1); + vsync_s = target.timing.v_sync_start - 1; /* Matrox */ + vsync_e = target.timing.v_sync_end - 1; /* Matrox */ + + /* We use the Matrox linecomp INT function to detect the + * vertical retrace at the earliest possible moment.. */ + linecomp = target.timing.v_display; - linecomp=256; /*should display half the screen!*/ - /*log the mode I am setting*/ LOG(2,("CRTC:\n\tHTOT:%x\n\tHDISPEND:%x\n\tHBLNKS:%x\n\tHBLNKE:%x\n\tHSYNCS:%x\n\tHSYNCE:%x\n\t",htotal,hdisp_e,hblnk_s,hblnk_e,hsync_s,hsync_e)); LOG(2,("VTOT:%x\n\tVDISPEND:%x\n\tVBLNKS:%x\n\tVBLNKE:%x\n\tVSYNCS:%x\n\tVSYNCE:%x\n",vtotal,vdisp_e,vblnk_s,vblnk_e,vsync_s,vsync_e)); @@ -133,55 +118,79 @@ status_t gx00_crtc_set_timing( /*actually program the card! Note linecomp is programmed to vblnk_s for VBI*/ /*horizontal - VGA regs*/ - VGAW_I(CRTC,0,htotal&0xFF); - VGAW_I(CRTC,1,hdisp_e&0xFF); - VGAW_I(CRTC,2,hblnk_s&0xFF); - VGAW_I(CRTC,3,(hblnk_e&0x1F)|0x80); - VGAW_I(CRTC,4,hsync_s&0xFF); - VGAW_I(CRTC,5,(hsync_e&0x1F)|((hblnk_e&0x20)<<2)); + VGAW_I(CRTC, 0x00, (htotal & 0x0ff)); + VGAW_I(CRTC, 0x01, (hdisp_e & 0x0ff)); + VGAW_I(CRTC, 0x02, (hblnk_s & 0x0ff)); + /* b7 should be set for compatibility reasons */ + VGAW_I(CRTC, 0x03, ((hblnk_e & 0x01f) | 0x80)); + VGAW_I(CRTC, 0x04, (hsync_s & 0x0ff)); + VGAW_I(CRTC, 0x05, (hsync_e & 0x01f) | ((hblnk_e & 0x020) << 2)); /*vertical - VGA regs*/ - VGAW_I(CRTC,6,vtotal&0xFF); - VGAW_I(CRTC,7, + VGAW_I(CRTC, 0x06, (vtotal & 0x0ff)); + VGAW_I(CRTC, 0x07, ( - ((vtotal&0x100)>>(8-0)) |((vtotal&0x200)>>(9-5))| - ((vdisp_e&0x100)>>(8-1))|((vdisp_e&0x200)>>(9-6))| - ((vsync_s&0x100)>>(8-2))|((vsync_s&0x200)>>(9-7))| - ((vblnk_s&0x100)>>(8-3))|((linecomp&0x100)>>(8-4)) + ((vtotal & 0x100) >> (8 - 0)) | ((vtotal & 0x200) >> (9 - 5)) | + ((vdisp_e & 0x100) >> (8 - 1)) | ((vdisp_e & 0x200) >> (9 - 6)) | + ((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)); - VGAW_I(CRTC,0x12,vdisp_e&0xFF); - VGAW_I(CRTC,0x15,vblnk_s&0xFF); - VGAW_I(CRTC,0x16,vblnk_e&0xFF); - VGAW_I(CRTC,0x18,linecomp&0xFF); + VGAW_I(CRTC, 0x08, 0x00); + VGAW_I(CRTC, 0x09, ((vblnk_s & 0x200) >> (9 - 5)) | ((linecomp & 0x200) >> (9 - 6))); + VGAW_I(CRTC, 0x10, (vsync_s & 0x0ff)); + VGAW_I(CRTC, 0x11, (((VGAR_I(CRTC, 0x11)) & 0xf0) | (vsync_e & 0x00f))); + VGAW_I(CRTC, 0x12, (vdisp_e & 0x0ff)); + VGAW_I(CRTC, 0x15, (vblnk_s & 0x0ff)); + VGAW_I(CRTC, 0x16, (vblnk_e & 0x0ff)); + VGAW_I(CRTC, 0x18, (linecomp & 0x0ff)); /* horizontal - extended regs */ /* do not touch external sync reset inputs: used for TVout */ - VGAW_I(CRTCEXT,1, + VGAW_I(CRTCEXT, 1, ( - ((htotal&0x100)>>8)| - ((hblnk_s&0x100)>>7)| - ((hsync_s&0x100)>>6)| - (hblnk_e&0x40)| - (VGAR_I(CRTCEXT,1)&0xb8) + ((htotal & 0x100) >> (8 - 0)) | + ((hblnk_s & 0x100) >> (8 - 1)) | + ((hsync_s & 0x100) >> (8 - 2)) | + ((hblnk_e & 0x040) >> (6 - 6)) | + (VGAR_I(CRTCEXT, 1) & 0xb8) )); /*vertical - extended regs*/ - VGAW_I(CRTCEXT,2, + VGAW_I(CRTCEXT, 2, ( - ((vtotal&0xC00)>>10)| - ((vdisp_e&0x400)>>8)| - ((vblnk_s&0xC00)>>7)| - ((vsync_s&0xC00)>>5)| - ((linecomp&0x400)>>3) + ((vtotal & 0xc00) >> (10 - 0)) | + ((vdisp_e & 0x400) >> (10 - 2)) | + ((vblnk_s & 0xc00) >> (10 - 3)) | + ((vsync_s & 0xc00) >> (10 - 5)) | + ((linecomp & 0x400) >> (10 - 7)) )); - /*set up HSYNC & VSYNC polarity*/ - VGAW(MISCW,(VGAR(MISCR)&0x3F)|((!vsync_pos)<<7)|((!hsync_pos)<<6)); - LOG(2,("HSYNC/VSYNC pol:%x %x MISC dump:%x\n",hsync_pos,vsync_pos,VGAR(MISCR))); + /* setup HSYNC & VSYNC polarity */ + LOG(2,("CRTC: sync polarity: ")); + temp = VGAR(MISCR); + if (target.timing.flags & B_POSITIVE_HSYNC) + { + LOG(2,("H:pos ")); + temp &= ~0x40; + } + else + { + LOG(2,("H:neg ")); + temp |= 0x40; + } + if (target.timing.flags & B_POSITIVE_VSYNC) + { + LOG(2,("V:pos ")); + temp &= ~0x80; + } + else + { + LOG(2,("V:neg ")); + temp |= 0x80; + } + VGAW(MISCW, temp); + + LOG(2,(", MISC reg readback: $%02x\n", VGAR(MISCR))); return B_OK; } @@ -239,12 +248,41 @@ status_t gx00_crtc_depth(int mode) return B_OK; } -status_t gx00_crtc_dpms(uint8 display,uint8 h,uint8 v) // MIL2 +status_t gx00_crtc_dpms(bool display, bool h, bool v) // MIL2 { - LOG(4,("gx00_crtc_dpms (%d,%d,%d)\n", display,h,v)); - VGAW_I(SEQ,1,(!display)<<5); - VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0xCF)|((!v)<<5))|((!h)<<4); - + LOG(4,("CRTC: setting DPMS: ")); + + if (display) + { + VGAW_I(SEQ,1, 0x00); + LOG(4,("display on, ")); + } + else + { + VGAW_I(SEQ,1, 0x20); + LOG(4,("display off, ")); + } + if (h) + { + VGAW_I(CRTCEXT, 1, (VGAR_I(CRTCEXT, 1) & 0xef)); + LOG(4,("hsync enabled, ")); + } + else + { + VGAW_I(CRTCEXT, 1, (VGAR_I(CRTCEXT, 1) | 0x10)); + LOG(4,("hsync disabled, ")); + } + if (v) + { + VGAW_I(CRTCEXT, 1, (VGAR_I(CRTCEXT, 1) & 0xdf)); + LOG(4,("vsync enabled\n")); + } + else + { + VGAW_I(CRTCEXT, 1, (VGAR_I(CRTCEXT, 1) | 0x20)); + LOG(4,("vsync disabled\n")); + } + /* set some required fixed values for proper MGA mode initialisation */ VGAW_I(CRTC,0x17,0xC3); VGAW_I(CRTC,0x14,0x00); @@ -252,13 +290,20 @@ status_t gx00_crtc_dpms(uint8 display,uint8 h,uint8 v) // MIL2 return B_OK; } -status_t gx00_crtc_dpms_fetch(uint8 * display,uint8 * h,uint8 * v) // MIL2 +status_t gx00_crtc_dpms_fetch(bool *display, bool *h, bool *v) // MIL2 { - *display=!((VGAR_I(SEQ,1)&0x20)>>5); - *h=!((VGAR_I(CRTCEXT,1)&0x10)>>4); - *v=!((VGAR_I(CRTCEXT,1)&0x20)>>5); + *display=!(VGAR_I(SEQ, 1) & 0x20); + *h=!(VGAR_I(CRTCEXT, 1) & 0x10); + *v=!(VGAR_I(CRTCEXT, 1) & 0x20); + + LOG(4,("CTRC: fetched DPMS state: ")); + if (*display) LOG(4,("display on, ")); + else LOG(4,("display off, ")); + if (*h) LOG(4,("hsync enabled, ")); + else LOG(4,("hsync disabled, ")); + if (*v) LOG(4,("vsync enabled\n")); + else LOG(4,("vsync disabled\n")); - LOG(4,("gx00_crtc_dpms_fetch (%d,%d,%d)\n", *display,*h,*v)); return B_OK; } diff --git a/src/add-ons/accelerants/matrox/engine/mga_crtc2.c b/src/add-ons/accelerants/matrox/engine/mga_crtc2.c index 921e596c72..b080bdec1c 100644 --- a/src/add-ons/accelerants/matrox/engine/mga_crtc2.c +++ b/src/add-ons/accelerants/matrox/engine/mga_crtc2.c @@ -2,7 +2,7 @@ Authors: Mark Watson 6/2000, - Rudolf Cornelissen 12/2002 - 4/2003 + Rudolf Cornelissen 12/2002 - 12/2003 */ #define MODULE_BIT 0x00020000 @@ -157,39 +157,140 @@ status_t g400_crtc2_depth(int mode) return B_OK; } -status_t g400_crtc2_dpms(uint8 display,uint8 h,uint8 v) +status_t g400_crtc2_dpms(bool display, bool h, bool v) { - if (display & h & v) - { - /* enable CRTC2 and don't touch the rest */ - CR2W(CTL, ((CR2R(CTL) & 0xFFF0177E) | 0x01)); - } - else - { - /* disable CRTC2 and don't touch the rest */ - CR2W(CTL, (CR2R(CTL) & 0xFFF0177E)); - } + LOG(4,("CRTC2: setting DPMS: ")); - if (si->ps.card_type >= G450) + if (si->ps.card_type <= G400MAX) { - //fixme: - /* setup monitor mode DPMS: G450 and later fully support this on CRTC2 */ - //for now: - //enable 'straight-through' sync outputs on both analog output connectors... - DXIW(SYNCCTRL,0x00); - } + if (display && h && v) + { + /* enable CRTC2 and don't touch the rest */ + CR2W(CTL, ((CR2R(CTL) & 0xFFF0177E) | 0x01)); + LOG(4,("display on, hsync enabled, vsync enabled\n")); + } + else + { + /* disable CRTC2 and don't touch the rest */ + CR2W(CTL, (CR2R(CTL) & 0xFFF0177E)); + LOG(4,("display off, hsync disabled, vsync disabled\n")); + } - /* On <= G400MAX dualhead cards we always need to send a 'copy' to the MAVEN */ - if (si->ps.secondary_head) gx00_maven_dpms(display, h, v); + /* On <= G400MAX dualhead cards we always need to send a 'copy' to the MAVEN */ + if (si->ps.secondary_head) gx00_maven_dpms(display, h, v); + } + else /* G450/G550 */ + { + /* set HD15 and DVI-A sync pol. to be fixed 'straight through' from the CRTCs, + * and preset enabled sync signals on both connectors. + * (polarities and primary DPMS are done via other registers.) */ + uint8 temp = 0x00; + + if (display) + { + /* enable CRTC2 and don't touch the rest */ + CR2W(CTL, ((CR2R(CTL) & 0xFFF0177E) | 0x01)); + LOG(4,("display on, ")); + } + else + { + /* disable CRTC2 and don't touch the rest */ + CR2W(CTL, (CR2R(CTL) & 0xFFF0177E)); + LOG(4,("display off, ")); + } + + if (si->crossed_conns) + { + if (h) + { + /* enable DVI-A hsync */ + temp &= ~0x01; + LOG(4,("hsync enabled, ")); + } + else + { + /* disable DVI-A hsync */ + temp |= 0x01; + LOG(4,("hsync disabled, ")); + } + if (v) + { + /* enable DVI-A vsync */ + temp &= ~0x02; + LOG(4,("vsync enabled\n")); + } + else + { + /* disable DVI-A vsync */ + temp |= 0x02; + LOG(4,("vsync disabled\n")); + } + } + else + { + if (h) + { + /* enable HD15 hsync */ + temp &= ~0x10; + LOG(4,("hsync enabled, ")); + } + else + { + /* disable HD15 hsync */ + temp |= 0x10; + LOG(4,("hsync disabled, ")); + } + if (v) + { + /* enable HD15 vsync */ + temp &= ~0x20; + LOG(4,("vsync enabled\n")); + } + else + { + /* disable HD15 vsync */ + temp |= 0x20; + LOG(4,("vsync disabled\n")); + } + } + /* program new syncs */ + DXIW(SYNCCTRL, temp); + } return B_OK; } -status_t g400_crtc2_dpms_fetch(uint8 * display,uint8 * h,uint8 * v) +status_t g400_crtc2_dpms_fetch(bool *display, bool *h, bool *v) { - *display=CR2R(CTL)&1; + *display = (CR2R(CTL) & 0x00000001); - *h=*v=1; /*h/vsync always enabled on second CRTC, does not support other*/ + if ((si->ps.card_type <= G400MAX)) + { + /* no full DPMS support: display controls all signals */ + *h = *v = *display; + } + else + { + /* G450 and G550 have full DPMS support on CRTC2 */ + if (si->crossed_conns) + { + *h = !(DXIR(SYNCCTRL) & 0x01); + *v = !(DXIR(SYNCCTRL) & 0x02); + } + else + { + *h = !(DXIR(SYNCCTRL) & 0x10); + *v = !(DXIR(SYNCCTRL) & 0x20); + } + } + + LOG(4,("CTRC2: fetched DPMS state: ")); + if (*display) LOG(4,("display on, ")); + else LOG(4,("display off, ")); + if (*h) LOG(4,("hsync enabled, ")); + else LOG(4,("hsync disabled, ")); + if (*v) LOG(4,("vsync enabled\n")); + else LOG(4,("vsync disabled\n")); 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 5c127f9373..ae3df8dbff 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-4/2003 + Rudolf Cornelissen 10/2002-12/2003 */ #define MODULE_BIT 0x00008000 @@ -56,7 +56,7 @@ status_t gx00_general_powerup() status_t status; uint32 card_class; - LOG(1,("POWERUP: Matrox (open)BeOS Accelerant 0.14 running.\n")); + LOG(1,("POWERUP: Matrox (open)BeOS Accelerant 0.15 running.\n")); /* detect card type and power it up */ switch(CFGR(DEVID)) @@ -292,7 +292,7 @@ status_t g100_general_powerup() /*power up the PLLs,LUT,DAC*/ 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_dpms(false, false, false); gx00_crtc_cursor_hide(); /* G100 SGRAM and SDRAM use external pix and dac refs, do *not* activate internals! * (this would create electrical shortcuts, @@ -368,7 +368,7 @@ status_t g100_general_powerup() VGAW_I(CRTC,0x11,0); /*turn on display one*/ - gx00_crtc_dpms(1,1,1); + gx00_crtc_dpms(true, true, true); return B_OK; } @@ -394,7 +394,7 @@ status_t g200_general_powerup() /*power up the PLLs,LUT,DAC*/ 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_dpms(false, false, false); gx00_crtc_cursor_hide(); /* G200 SGRAM and SDRAM use external pix and dac refs, do *not* activate internals! * (this would create electrical shortcuts, @@ -468,7 +468,7 @@ status_t g200_general_powerup() VGAW_I(CRTC,0x11,0); /*turn on display one*/ - gx00_crtc_dpms(1,1,1); + gx00_crtc_dpms(true, true, true); return B_OK; } @@ -491,11 +491,19 @@ status_t g400_general_powerup() /* 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(); + /* reset MAVEN so we know the sync polarity is at reset situation (Hpos, Vpos) */ + if (si->ps.secondary_tvout) + { + ACCW(RST, 0x00000002); + snooze(1000); + ACCW(RST, 0x00000000); + } + /*power up the PLLs,LUT,DAC*/ 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_dpms(false, false, false); + g400_crtc2_dpms(false, false, false); gx00_crtc_cursor_hide(); /* set voltage reference - not using DAC reference block */ @@ -573,7 +581,7 @@ status_t g400_general_powerup() } /*turn on display one*/ - gx00_crtc_dpms(1,1,1); + gx00_crtc_dpms(true, true, true); return B_OK; } @@ -605,8 +613,8 @@ status_t g450_general_powerup() /* disable outputs */ DXIW(OUTPUTCONN,0x00); /* turn off both displays and the hardcursor (also disables transfers) */ - gx00_crtc_dpms(0,0,0); - g400_crtc2_dpms(0,0,0); + gx00_crtc_dpms(false, false, false); + g400_crtc2_dpms(false, false, false); gx00_crtc_cursor_hide(); /* power up everything except DVI electronics (for now) */ @@ -721,7 +729,7 @@ status_t g450_general_powerup() gx50_general_output_select(); /*turn on display one*/ - gx00_crtc_dpms(1,1,1); + gx00_crtc_dpms(true, true, true); /* enable 'straight-through' sync outputs on both analog output connectors */ DXIW(SYNCCTRL,0x00); @@ -806,6 +814,8 @@ status_t gx00_general_dac_select(int dac) /* Select 1.5 Volt MAVEN DAC ref. for monitor mode */ DXIW(GENIOCTRL, DXIR(GENIOCTRL) & ~0x40); DXIW(GENIODATA, 0x00); + /* signal CRTC2 DPMS which connector to program */ + si->crossed_conns = false; break; //fixme: toggle PLL's below if possible: // otherwise toggle PLL's for G400 2nd case? @@ -821,6 +831,8 @@ status_t gx00_general_dac_select(int dac) /* Select 1.5 Volt MAVEN DAC ref. for monitor mode */ DXIW(GENIOCTRL, DXIR(GENIOCTRL) & ~0x40); DXIW(GENIODATA, 0x00); + /* signal CRTC2 DPMS which connector to program */ + si->crossed_conns = true; break; default: return B_ERROR; @@ -828,13 +840,6 @@ status_t gx00_general_dac_select(int dac) return B_OK; } -/*busy wait until retrace!*/ -status_t gx00_general_wait_retrace() -{ - while (!(ACCR(STATUS)&0x8)); - return B_OK; -} - /* basic change of card state from VGA to powergraphics -> should work from BIOS init state*/ static status_t gx00_general_bios_to_powergraphics() @@ -858,6 +863,13 @@ status_t gx00_general_bios_to_powergraphics() { case G400: case G400MAX: + /* reset MAVEN so we know the sync polarity is at reset situation (Hpos, Vpos) */ + if (si->ps.secondary_tvout) + { + ACCW(RST, 0x00000002); + snooze(1000); + ACCW(RST, 0x00000000); + } /* makes CRTC2 stable! Matrox specify 8, but use 4 - grrrr! */ DXIW(MAFCDEL,0x02); break; @@ -901,7 +913,7 @@ status_t gx00_general_bios_to_powergraphics() * Mode slopspace is reflected in fbc->bytes_per_row BTW. */ //fixme: seperate heads for real dualhead modes: //CRTC1 and 2 constraints differ! -status_t gx00_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row) +status_t gx00_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode) { /* Note: * This routine assumes that the CRTC memory pitch granularity is 'smaller than', @@ -1003,7 +1015,7 @@ status_t gx00_general_validate_pic_size (display_mode *target, uint32 *bytes_per /* check if we can setup this mode with acceleration: * Max sizes need to adhere to both the acceleration engine _and_ the CRTC constraints! */ - si->acc_mode = true; + *acc_mode = true; /* check virtual_width */ switch (si->ps.card_type) { @@ -1011,19 +1023,19 @@ status_t gx00_general_validate_pic_size (display_mode *target, uint32 *bytes_per case MIL2: case G100: /* acc constraint: */ - if (target->virtual_width > 2048) si->acc_mode = false; + if (target->virtual_width > 2048) *acc_mode = false; break; default: /* G200-G550 */ /* acc constraint: */ - if (target->virtual_width > 4096) si->acc_mode = false; + if (target->virtual_width > 4096) *acc_mode = false; /* for 32bit mode a lower CRTC1 restriction applies! */ if ((target->space == B_RGB32_LITTLE) && (target->virtual_width > (4092 & ~acc_mask))) - si->acc_mode = false; + *acc_mode = false; break; } /* virtual_height */ - if (target->virtual_height > 2048) si->acc_mode = false; + if (target->virtual_height > 2048) *acc_mode = false; /* now check virtual_size based on CRTC constraints, * making sure virtual_width stays within the 'mask' constraint: which is only @@ -1064,7 +1076,7 @@ status_t gx00_general_validate_pic_size (display_mode *target, uint32 *bytes_per /* OK, now we know that virtual_width is valid, and it's needing no slopspace if * it was confined above, so we can finally calculate safely if we need slopspace * for this mode... */ - if (si->acc_mode) + if (*acc_mode) video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask); else video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask); diff --git a/src/add-ons/accelerants/matrox/engine/mga_maven.c b/src/add-ons/accelerants/matrox/engine/mga_maven.c index 3c48cbabdf..ca565ac309 100644 --- a/src/add-ons/accelerants/matrox/engine/mga_maven.c +++ b/src/add-ons/accelerants/matrox/engine/mga_maven.c @@ -2,7 +2,7 @@ /* Authors: Mark Watson 6/2000, - Rudolf Cornelissen 1/2003-4/2003 + Rudolf Cornelissen 1/2003-12/2003 Thanx to Petr Vandrovec for writing matroxfb. */ @@ -14,12 +14,67 @@ status_t g450_g550_maven_set_vid_pll(display_mode target); status_t g100_g400max_maven_set_vid_pll(display_mode target); -status_t gx00_maven_dpms(uint8 display,uint8 h,uint8 v) +/* This routine blanks the first 'line' below the screen used if there's memory left + * to place it in. This will prevent overscanning rubbish on the MAVEN DAC, but only + * if no screen using virtual height is setup. + * In the rare event the mode and overlay use up so much RAM there's not enough room + * left for one blank line, you will get overscanning rubbish from the overlay as it + * will overwrite the blank line placed here. + * This 'rectangle fill' is done in software because not all modes are supported by + * the acc engine. + * This function exists to partly overcome a G400 MAVEN hardware design fault, which + * influences output in both monitor and TVout modes. The fault is that the MAVEN + * keeps repeatedly displaying the last 8 pixels fetched from memory until fetching + * restarts after a vertical retrace. + * In order to let the maven fetch black pixels, an extra line has to be added to its + * CRTC timing. This line needs to be entirely filled black, so with zeros. This line + * will be displayed as last visible line, and the last 8 pixels of it will be + * repeated during vertical retrace. + * Note that the overscanning rubbish can be suppressed in TVout modes by extending + * the vertical sync pulse all the way 'to the end'. */ +status_t gx00_maven_clrline() +{ + uint32 x, screensize, pointer_reservation; + uint8* adr; + + /* this function is nolonger needed on G450/G550 cards */ + if (si->ps.card_type > G400MAX) return B_OK; + + /* checkout space needed for hardcursor (if any) */ + pointer_reservation = 0; + /* MIL 1/2 cards have a seperate buffer for the cursorbitmap inside the DAC */ + if ((si->ps.card_type >= G100) && si->settings.hardcursor) pointer_reservation = 1024; + + /* calculate actual screensize */ + screensize = si->fbc.bytes_per_row * si->dm.virtual_height; + + /* check if there's room left for a full blank line following the actual screen */ + if ((screensize + si->fbc.bytes_per_row + pointer_reservation) <= + (si->ps.memory_size * 1024 * 1024)) + { + LOG(4,("MAVEN: clearing line directly below screen\n")); + + /* calculate first adress beyond actual screen */ + adr = (uint8*)si->fbc.frame_buffer; + adr += screensize; + /* clear the line */ + for (x = 0; x < si->fbc.bytes_per_row; x++) + { + *(adr + x) = 0x00; + } + } + else + LOG(4,("MAVEN: not clearing line directly below screen: no memory left\n")); + + return B_OK; +} + +status_t gx00_maven_dpms(bool display, bool h, bool v) { /* this function is nolonger needed on G450/G550 cards */ if (si->ps.card_type > G400MAX) return B_OK; - if (display & h & v) + if (display && h && v) { /* turn on screen */ if (!(si->dm.flags & TV_BITS)) @@ -56,6 +111,8 @@ status_t gx00_maven_dpms(uint8 display,uint8 h,uint8 v) /*set a mode line - inputs are in pixels/scanlines*/ status_t gx00_maven_set_timing(display_mode target) { + uint8 temp, cnt, offset, loop; + /* this function is nolonger needed on G450/G550 cards */ if (si->ps.card_type > G400MAX) return B_OK; @@ -87,20 +144,66 @@ status_t gx00_maven_set_timing(display_mode target) MAVWW(HVIDRSTL, (target.timing.h_total - si->crtc_delay)); MAVWW(VVIDRSTL, (target.timing.v_total - 2)); + /* setup HSYNC & VSYNC polarity */ + LOG(2,("MAVEN: sync polarity: ")); + temp = MAVR(LUMA); + + /* find out which offset from the 'reset position' we need */ + switch (((target.timing.flags & B_POSITIVE_HSYNC) >> (29 - 0)) | + ((target.timing.flags & B_POSITIVE_VSYNC) >> (30 - 1))) + { + case 0: + /* H neg, V neg */ + LOG(2,("H:neg V:neg\n")); + offset = 2; + break; + case 1: + /* H pos, V neg */ + LOG(2,("H:pos V:neg\n")); + offset = 3; + break; + case 2: + /* H neg, V pos */ + LOG(2,("H:neg V:pos\n")); + offset = 1; + break; + case 3: + default: + /* H pos, V pos */ + LOG(2,("H:pos V:pos\n")); + offset = 0; + break; + } + /* calculate the number of steps we need to make from the current 'position' */ + cnt = 0; + if ((offset - ((int)si->maven_syncpol_offset)) < 0) cnt = 4; + cnt += offset - si->maven_syncpol_offset; + /* note the offset from 'reset position' we will have now */ + si->maven_syncpol_offset = offset; + + /* program the maven: */ + /* make sure pulse bit is reset */ + temp &= ~0x20; + MAVW(LUMA, temp); + snooze(5); + /* enable maven sync polarity programming */ + temp |= 0x10; + MAVW(LUMA, temp); + snooze(5); + /* pulse sync programming bit until we have the polarities we want */ + for (loop = 0; loop < cnt; loop++) + { + MAVW(LUMA, (temp | 0x20)); + snooze(5); + MAVW(LUMA, (temp & ~0x20)); + snooze(5); + } + /* disable maven sync polarity programming and reset pulse bit */ + MAVW(LUMA, (temp & ~0x30)); + return B_OK; } -//not used: -/* -void gx00_maven_delay(int number) -{ - // this function is nolonger needed on G450/G550 cards - if (si->ps.card_type > G400MAX) return; - - MAVWW(HVIDRSTL,(si->dm.timing.h_total-number)); -} -*/ - /*set the mode, brightness is a value from 0->2 (where 1 is equivalent to direct)*/ status_t gx00_maven_mode(int mode,float brightness) { @@ -109,11 +212,16 @@ status_t gx00_maven_mode(int mode,float brightness) /* this function is nolonger needed on G450/G550 cards */ if (si->ps.card_type > G400MAX) return B_OK; - /*set luma to a suitable value for brightness*/ - /*assuming 1A is a sensible value*/ - luma = (uint8)(0x1a * brightness); - MAVW(LUMA,luma); - LOG(4,("MAVEN: LUMA setting - %x\n",luma)); + /* set luma to a suitable value for brightness */ + /* assuming 0x0a is a sensible value */ + /* fixme: + * it looks like b6 and/or b7 determine the luma: just two values possible. */ + /* NOTE: b4 and b5 have another function, don't set! (sync polarity programming) */ + luma = (uint8)(0x0a * brightness); + if (luma > 0x0f) luma = 0x0f; + + MAVW(LUMA, luma); + LOG(4,("MAVEN: LUMA setting - %x\n", luma)); return B_OK; } diff --git a/src/add-ons/accelerants/matrox/engine/mga_maventv.c b/src/add-ons/accelerants/matrox/engine/mga_maventv.c index 7a86ca80d8..16f0f1e070 100644 --- a/src/add-ons/accelerants/matrox/engine/mga_maventv.c +++ b/src/add-ons/accelerants/matrox/engine/mga_maventv.c @@ -1,6 +1,6 @@ /* Authors: Mark Watson 2000, - Rudolf Cornelissen 1/2003-3/2003 + Rudolf Cornelissen 1/2003-12/2003 Thanx to Petr Vandrovec for writing matroxfb. */ @@ -20,9 +20,6 @@ typedef struct { float chroma_subcarrier; } gx50_maven_timing; -//fixme: setup fixed CRTC2 modes for all modes and block other modes: -// - 640x480, 800x600, 1024x768 NTSC and PAL overscan compensated modes (desktop) -// - 640x480, 720x480 NTSC and 768x576, 720x576 non-overscan compensated modes (video) //fixme: try to implement 'fast' and 'slow' settings for all modes, // so buffer duplication or skipping won't be neccesary for realtime video. //fixme: try to setup the CRTC2 in interlaced mode for the video modes on <= G400MAX cards. @@ -694,10 +691,190 @@ int maventv_init(display_mode target) MAVW(LOCK, 0x01); MAVW(OUTMODE, 0x08); + + /* set high contrast/brightness range for TVout */ + /* Note: + * b4-5 have contrast/brightness function during TVout, while these bits + * are used to set sync polarity in a serial fashion during monitor modes. + * Setting both these bits here will 'increase' the sync polarity offset + * by one! */ MAVW(LUMA, 0x78); + /* We just made a sync polarity programming step for monitor modes, so: + * note the offset from 'reset position' we will have now */ + si->maven_syncpol_offset += 1; + if (si->maven_syncpol_offset > 3) si->maven_syncpol_offset = 0; + + //unknown regs: MAVW(STABLE, 0x02); MAVW(MONEN, 0xB3); + /* modify mode to center and size correctly on TV */ + { + int diff; + float uscan_fact; + bool tweak = false; /* needed for NTSC VCD mode */ + + if (!(tv_target.flags & TV_VIDEO)) /* Desktop modes */ + { + LOG(4,("MAVENTV: setting underscanning ('downscaled') desktop mode\n")); + + /* adapt mode to underscan correctly */ + if ((tv_target.timing.h_display < 704) && ((tv_target.flags & TV_BITS) == TV_PAL)) + { + /* can't be higher because of scaling limitations in MAVEN! */ + uscan_fact = 0.77; + } + else + { + /* optimal setting for desktop modes.. */ + uscan_fact = 0.80; + } + /* horizontal */ + tv_target.timing.h_total = (tv_target.timing.h_display / uscan_fact); + /* adhere to CRTC constraints */ + tv_target.timing.h_total &= ~0x0007; + /* vertical */ + tv_target.timing.v_total = (tv_target.timing.v_display / uscan_fact); + + /* now do vertical centering */ + if ((tv_target.flags & TV_BITS) == TV_PAL) + { + diff = tv_target.timing.v_total - tv_target.timing.v_display; + tv_target.timing.v_sync_start = tv_target.timing.v_display + ((diff * 7) / 20); + /* sync all the way 'to the end' to prevent vertical overscanning + * rubbish on top of screen due to MAVEN hardware design fault */ + tv_target.timing.v_sync_end = tv_target.timing.v_total; + } + else + { + diff = tv_target.timing.v_total - tv_target.timing.v_display; + tv_target.timing.v_sync_start = tv_target.timing.v_display + ((diff * 5) / 20); + /* sync all the way 'to the end' to prevent vertical overscanning + * rubbish on top of screen due to MAVEN hardware design fault */ + tv_target.timing.v_sync_end = tv_target.timing.v_total; + } + } + else /* Video modes */ + { + uint16 mode = + (((tv_target.flags & TV_BITS) << (14 - 9)) | tv_target.timing.h_display); + + LOG(4,("MAVENTV: setting overscanning ('unscaled') video mode\n")); + + /* adapt standard modes to be displayed 1:1 */ + switch (mode) + { + case ((TV_NTSC << (14 - 9)) | 640): /* NTSC VCD mode */ + /* horizontal: adhere to CRTC granularity (8) */ + /* Note: h_total = 704 has no PLL match! */ + tv_target.timing.h_total = 696; + /* because this 'low' horizontal resolution cannot be scaled up + * for overscanning use (MAVEN restriction) we need to do some + * tweaking to get a mode we can work with that still has the + * correct aspect ratio. + * This mode has just a little bit horizontal overscanning. */ + tweak = true; + break; + case ((TV_NTSC << (14 - 9)) | 720): /* NTSC DVD mode */ + /* horizontal: adhere to CRTC granularity (8) */ + tv_target.timing.h_total = 784; + break; + case ((TV_PAL << (14 - 9)) | 768): /* PAL VCD mode */ + /* horizontal: adhere to CRTC granularity (8) */ + tv_target.timing.h_total = 832; + break; + case ((TV_PAL << (14 - 9)) | 720): /* PAL DVD mode */ + /* horizontal: adhere to CRTC granularity (8) */ + tv_target.timing.h_total = 784; + break; + default: + /* non-standard mode: just hope for he best. */ + break; + } + + /* now do vertical centering and clipping */ + if ((tv_target.flags & TV_BITS) == TV_PAL) + { + /* defined by the PAL standard */ + tv_target.timing.v_total = m_timing.v_total; + /* we need to center the image on TV vertically. + * note that 576 is the maximum supported resolution for the PAL standard, + * this is already overscanning by approx 8-10% */ + diff = 576 - tv_target.timing.v_display; + /* if we cannot display the current vertical resolution fully, clip it */ + if (diff < 0) + { + tv_target.timing.v_display = 576; + diff = 0; + } + /* now center the image on TV */ + tv_target.timing.v_sync_start = tv_target.timing.v_display + (diff / 2); + /* sync all the way 'to the end' to prevent vertical overscanning + * rubbish on top of screen due to MAVEN hardware design fault */ + /* note: probably invisible in these Video modes */ + tv_target.timing.v_sync_end = tv_target.timing.v_total; + } + else + { + /* defined by the NTSC standard */ + tv_target.timing.v_total = m_timing.v_total; + /* NTSC VCD mode needs to be scaled down vertically to get correct + * aspect ratio... */ + if (tweak) tv_target.timing.v_total += 32; + /* we need to center the image on TV vertically. + * note that 480 is the maximum supported resolution for the NTSC standard, + * this is already overscanning by approx 8-10% */ + diff = 480 - tv_target.timing.v_display; + /* if we cannot display the current vertical resolution fully, clip it */ + if (diff < 0) + { + tv_target.timing.v_display = 480; + diff = 0; + } + /* now center the image on TV */ + tv_target.timing.v_sync_start = tv_target.timing.v_display + (diff / 2); + /* ...NTSC VCD mode needs to be moved up to center the tweaked mode + * correcty... */ + if (tweak) tv_target.timing.v_sync_start += 9; + /* sync all the way 'to the end' to prevent vertical overscanning + * rubbish on top of screen due to MAVEN hardware design fault */ + /* note: might be visible in the NTSC VCD Video mode */ + tv_target.timing.v_sync_end = tv_target.timing.v_total; + } + } + + /* finally do horizontal centering */ + if ((tv_target.flags & TV_BITS) == TV_PAL) + { + diff = tv_target.timing.h_total - tv_target.timing.h_display; + tv_target.timing.h_sync_start = tv_target.timing.h_display - 0 + (diff / 2); + /* keep adhering to CRTC constraints */ + tv_target.timing.h_sync_start &= ~0x0007; + tv_target.timing.h_sync_end = tv_target.timing.h_sync_start + 16; + } + else + { + diff = tv_target.timing.h_total - tv_target.timing.h_display; + tv_target.timing.h_sync_start = tv_target.timing.h_display - 16 + (diff / 2); + /* ...and finally the NTSC VCD mode needs to be moved to the right to + * center the tweaked mode correctly. */ + if (tweak) tv_target.timing.h_sync_start -= 16; + /* keep adhering to CRTC constraints */ + tv_target.timing.h_sync_start &= ~0x0007; + tv_target.timing.h_sync_end = tv_target.timing.h_sync_start + 16; + } + } + + /* tune crtc delay */ + if ((tv_target.timing.h_display >= 1000) && (((tv_target.flags & TV_BITS) != TV_PAL))) + { + si->crtc_delay += 1; + } + else + { + si->crtc_delay -= 3; + } + /* setup video PLL */ g100_g400max_maventv_vid_pll_find( tv_target, &ht_new, &ht_last_line, &m_result, &n_result, &p_result); @@ -767,13 +944,11 @@ int maventv_init(display_mode target) int index; /* calc hor scale-back factor from input to output picture (in 1.7 format) - * the MAVEN has 736 pixels fixed visible? outputline length for TVout */ - //fixme: shouldn't this be 768 (= PAL 1:1 output 4:3 ratio format)?!? + * the MAVEN has 736 pixels fixed total outputline length for TVout */ h_scale_tv = (736 << 7) / tv_target.timing.h_total;//should be PLL corrected LOG(4,("MAVENTV: horizontal scale-back factor is: %f\n", (h_scale_tv / 128.0))); /* limit values to MAVEN capabilities (scale-back factor is 0.5-1.0) */ - //fixme: how about lowres upscaling? if (h_scale_tv > 0x80) { h_scale_tv = 0x80; @@ -912,9 +1087,19 @@ int maventv_init(display_mode target) MAVW(GAMMA9, 0xC8); /* 200 */ /* set flickerfilter */ - /* OFF: is dependant on MAVEN chip version(?): MGA_TVO_B = $40, else $00. - * ON : always set $a2. */ - MAVW(FFILTER, 0xa2); + if (!(tv_target.flags & TV_VIDEO)) + { + /* Desktop modes (those are scaled): filter on to prevent artifacts */ + MAVW(FFILTER, 0xa2); + LOG(4,("MAVENTV: enabling flicker filter\n")); + } + else + { + /* Video modes (those are unscaled): filter off to increase sharpness */ + //fixme? OFF is dependant on MAVEN version(?): MGA_TVO_B = $40, else $00. + MAVW(FFILTER, 0x00); + LOG(4,("MAVENTV: disabling flicker filter\n")); + } /* 0x10 or anything ored with it */ //fixme? linux uses 0x14... diff --git a/src/add-ons/accelerants/matrox/engine/mga_proto.h b/src/add-ons/accelerants/matrox/engine/mga_proto.h index b5f2da126e..0990aa946d 100644 --- a/src/add-ons/accelerants/matrox/engine/mga_proto.h +++ b/src/add-ons/accelerants/matrox/engine/mga_proto.h @@ -4,7 +4,7 @@ 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_validate_pic_size (display_mode *target, uint32 *bytes_per_row); +status_t gx00_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode); //status_t gx00_general_bios_to_powergraphics(); /* apsed: logging macros */ @@ -62,7 +62,8 @@ status_t mil2_dac_init(void); status_t mil2_dac_set_pix_pll(float f_vco,int bpp); /*MAVEN functions*/ -status_t gx00_maven_dpms(uint8,uint8,uint8); +status_t gx00_maven_clrline(); +status_t gx00_maven_dpms(bool display, bool h, bool v); status_t gx00_maven_set_timing(display_mode target); status_t gx00_maven_mode(int,float); @@ -83,17 +84,13 @@ status_t gx00_crtc_validate_timing( uint16 *hd_e,uint16 *hs_s,uint16 *hs_e,uint16 *ht, uint16 *vd_e,uint16 *vs_s,uint16 *vs_e,uint16 *vt ); -status_t gx00_crtc_set_timing( - uint16 hd_e,uint16 hs_s,uint16 hs_e,uint16 ht, - uint16 vd_e,uint16 vs_s,uint16 vs_e,uint16 vt, - uint8 hsync_pos,uint8 vsync_pos -); +status_t gx00_crtc_set_timing(display_mode target); status_t gx00_crtc_depth(int mode); status_t gx00_crtc_set_display_start(uint32 startadd,uint8 bpp); status_t gx00_crtc_set_display_pitch(); -status_t gx00_crtc_dpms(uint8,uint8,uint8); -status_t gx00_crtc_dpms_fetch(uint8*,uint8*,uint8*); +status_t gx00_crtc_dpms(bool display,bool h,bool v); +status_t gx00_crtc_dpms_fetch(bool *display, bool *h, bool *v); status_t gx00_crtc_mem_priority(uint8); status_t gx00_crtc_cursor_init(); /*Yes, cursor follows CRTC1 - not the DAC!*/ @@ -109,8 +106,8 @@ status_t g400_crtc2_depth(int mode); status_t g400_crtc2_set_display_pitch(); status_t g400_crtc2_set_display_start(uint32 startadd,uint8 bpp); -status_t g400_crtc2_dpms(uint8 display,uint8 h,uint8 v); -status_t g400_crtc2_dpms_fetch(uint8 * display,uint8 * h,uint8 * v); +status_t g400_crtc2_dpms(bool display, bool h, bool v); +status_t g400_crtc2_dpms_fetch(bool *display, bool *h, bool *v); /*acceleration functions*/ status_t check_acc_capability(uint32 feature); diff --git a/src/add-ons/accelerants/matrox/engine/mga_support.c b/src/add-ons/accelerants/matrox/engine/mga_support.c index 1c8473c794..6f8858e856 100644 --- a/src/add-ons/accelerants/matrox/engine/mga_support.c +++ b/src/add-ons/accelerants/matrox/engine/mga_support.c @@ -1,5 +1,6 @@ /* Some commmon support functions */ -/* Mark Watson 2/2000 */ +/* Mark Watson 2/2000 + * Rudolf Cornelissen 11/2003 */ #define MODULE_BIT 0x00000800 @@ -17,12 +18,15 @@ void delay(bigtime_t i) void mga_log(char *fmt, ...) { char buffer[1024]; + char fname[64]; FILE *myhand; va_list args; - myhand=fopen("/boot/home/" DRIVER_PREFIX ".accelerant.log","a+"); + sprintf (fname, "/boot/home/" DRIVER_PREFIX ".accelerant.%d.log", accelerantIsClone); + myhand=fopen(fname,"a+"); + if (myhand == NULL) return; - + va_start(args,fmt); vsprintf (buffer, fmt, args); fprintf(myhand, "%s", buffer); diff --git a/src/add-ons/kernel/drivers/graphics/matrox/Jamfile b/src/add-ons/kernel/drivers/graphics/matrox/Jamfile index 73483f6541..7a80bc9f63 100644 --- a/src/add-ons/kernel/drivers/graphics/matrox/Jamfile +++ b/src/add-ons/kernel/drivers/graphics/matrox/Jamfile @@ -7,6 +7,16 @@ R5KernelAddon mga.driver : kernel drivers bin : driver.c ; +Package openbeos-matrox-1.0 : + mga.driver : + boot home config add-ons kernel drivers bin ; +Package openbeos-matrox-1.0 : + mga.driver : + boot home config add-ons kernel drivers dev graphics ; +Package openbeos-matrox-1.0 : + mga.settings : + boot home config settings kernel drivers ; + # Link to kernel/drivers/dev/graphics { local dir = [ FDirName $(OBOS_ADDON_DIR) kernel drivers dev graphics ] ; diff --git a/src/add-ons/kernel/drivers/graphics/matrox/driver.c b/src/add-ons/kernel/drivers/graphics/matrox/driver.c index dbaf050467..9d6f585f17 100644 --- a/src/add-ons/kernel/drivers/graphics/matrox/driver.c +++ b/src/add-ons/kernel/drivers/graphics/matrox/driver.c @@ -4,7 +4,7 @@ Other authors: Mark Watson; - Rudolf Cornelissen 3/2002. + Rudolf Cornelissen 3/2002-11/2003. */ /* standard kernel driver stuff */ @@ -688,6 +688,9 @@ static status_t open_hook (const char* name, uint32 flags, void** cookie) { (di->pcii.u.h0.interrupt_line == 0xff) || /* no IRQ assigned */ (di->pcii.u.h0.interrupt_line <= 0x02)) /* system IRQ assigned */ { + /* we are aborting! */ + /* Note: the R4 graphics driver kit lacks this statement!! */ + result = B_ERROR; /* interrupt does not exist so exit without installing our handler */ goto delete_the_sem; } diff --git a/src/add-ons/kernel/drivers/graphics/matrox/mga.settings b/src/add-ons/kernel/drivers/graphics/matrox/mga.settings index 81a2934ce3..6132882c75 100644 --- a/src/add-ons/kernel/drivers/graphics/matrox/mga.settings +++ b/src/add-ons/kernel/drivers/graphics/matrox/mga.settings @@ -10,7 +10,7 @@ # mga.accelerant parameters usebios false # if true rely on bios to coldstart the card instead of driver #memory 2 # in MB, override builtin memory size detection -hardcursor false # if true use on-chip cursor capabilities +hardcursor true # 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