Update for the S3 driver by Gerald:

* The hardware cursor is now disabled at 640x480 with a Virge VX (before it
  was just invisible).
* EDID info can now be read for all S3 chips.
* For the Savage IX, Savage MX, and SuperSavage chips the display is no 
  longer expanded to fill a laptop LCD display when the mode resolution is 
  less than the size of LCD display.
* Savage IX, Savage MX, and SuperSavage chips will now display mode 
  1400x1050 on a 1400x1050 laptop LCD display.  Previously the display was 
  blank at that resolution. 
* Previously about half the Savage chips would not draw properly at 
  1400x1050.  That is, the image was badly skewed and unusable.  All of 
  them now draw properly at 1400x1050.
* Some code was reorganized to remove unnecessary and redundant code.  


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27863 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-10-04 08:09:40 +00:00
parent da720168c1
commit c1379d357b
21 changed files with 986 additions and 1143 deletions
+52 -66
View File
@@ -2,7 +2,7 @@
Copyright 2007-2008 Haiku, Inc. All rights reserved. Copyright 2007-2008 Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT license. Distributed under the terms of the MIT license.
Other authors: Authors:
Gerald Zajac 2007-2008 Gerald Zajac 2007-2008
*/ */
@@ -16,27 +16,42 @@
#include <edid.h> #include <edid.h>
// This is the info that needs to be shared between the kernel driver and // This file contains info that is shared between the kernel driver and the
// the accelerant for the sample driver. // accelerant, and info that is shared among the source files of the accelerant.
#if defined(__cplusplus)
extern "C" {
#endif
#define ENABLE_DEBUG_TRACE // if defined, turns on debug output to syslog #define ENABLE_DEBUG_TRACE // if defined, turns on debug output to syslog
#define NUM_ELEMENTS(a) ((int)(sizeof(a) / sizeof(a[0]))) // for computing number of elements in an array #define NUM_ELEMENTS(a) ((int)(sizeof(a) / sizeof(a[0]))) // for computing number of elements in an array
struct benaphore { struct Benaphore {
sem_id sem; sem_id sem;
int32 ben; int32 count;
};
#define INIT_BEN(x) x.sem = create_sem(0, "S3 "#x" benaphore"); x.ben = 0; status_t Init(const char* name)
#define AQUIRE_BEN(x) if((atomic_add(&(x.ben), 1)) >= 1) acquire_sem(x.sem); {
#define RELEASE_BEN(x) if((atomic_add(&(x.ben), -1)) > 1) release_sem(x.sem); count = 0;
#define DELETE_BEN(x) delete_sem(x.sem); sem = create_sem(0, name);
return sem < 0 ? sem : B_OK;
}
status_t Acquire()
{
if (atomic_add(&count, 1) > 0)
return acquire_sem(sem);
return B_OK;
}
status_t Release()
{
if (atomic_add(&count, -1) > 1)
return release_sem(sem);
return B_OK;
}
void Delete() { delete_sem(sem); }
};
#define S3_PRIVATE_DATA_MAGIC 0x4521 // a private driver rev, of sorts #define S3_PRIVATE_DATA_MAGIC 0x4521 // a private driver rev, of sorts
@@ -45,6 +60,7 @@ struct benaphore {
enum { enum {
S3_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1, S3_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1,
S3_DEVICE_NAME, S3_DEVICE_NAME,
S3_GET_EDID,
S3_GET_PIO, S3_GET_PIO,
S3_SET_PIO, S3_SET_PIO,
S3_RUN_INTERRUPTS, S3_RUN_INTERRUPTS,
@@ -54,7 +70,7 @@ enum {
// Chip type numbers. These are used to group the chips into related // Chip type numbers. These are used to group the chips into related
// groups. See table S3_ChipTable in driver.c // groups. See table S3_ChipTable in driver.c
enum S3_ChipType { enum ChipType {
S3_TRIO64 = 1, S3_TRIO64 = 1,
S3_TRIO64_VP, // Trio64V+ has same ID as Trio64 but different revision number S3_TRIO64_VP, // Trio64V+ has same ID as Trio64 but different revision number
S3_TRIO64_UVP, S3_TRIO64_UVP,
@@ -106,33 +122,10 @@ enum MonitorType {
}; };
// Bitmap descriptor structures for BCI (for Savage chips)
struct HIGH {
unsigned short Stride;
unsigned char Bpp;
unsigned char ResBWTile;
};
struct BMPDESC1 {
unsigned long Offset;
HIGH HighPart;
};
struct BMPDESC2 {
unsigned long LoPart;
unsigned long HiPart;
};
union BMPDESC {
BMPDESC1 bd1;
BMPDESC2 bd2;
};
struct DisplayModeEx : display_mode { struct DisplayModeEx : display_mode {
uint32 bpp; // bits/pixel uint32 bpp; // bits/pixel
uint32 bytesPerRow; // number of bytes in one line/row uint32 bytesPerRow; // actual number of bytes in one line/row
}; };
@@ -147,6 +140,9 @@ struct SharedInfo {
bool bAccelerantInUse; // true = accelerant has been initialized bool bAccelerantInUse; // true = accelerant has been initialized
bool bInterruptAssigned; // card has a useable interrupt assigned to it bool bInterruptAssigned; // card has a useable interrupt assigned to it
bool bDisableHdwCursor; // true = disable hardware cursor & use software cursor
bool bDisableAccelDraw; // true = disable accelerated drawing
sem_id vertBlankSem; // vertical blank semaphore; if < 0, there is no semaphore sem_id vertBlankSem; // vertical blank semaphore; if < 0, there is no semaphore
// Memory mappings. // Memory mappings.
@@ -169,11 +165,8 @@ struct SharedInfo {
area_id modeArea; // area containing list of display modes the driver supports area_id modeArea; // area containing list of display modes the driver supports
uint32 modeCount; // number of display modes in the list uint32 modeCount; // number of display modes in the list
// Cursor info. uint16 cursorHotX; // Cursor hot spot. Top left corner of the cursor
struct { uint16 cursorHotY; // is 0,0
uint16 hot_x; // Cursor hot spot. Top left corner of the cursor
uint16 hot_y; // is 0,0
} cursor;
// Current display mode configuration, and other parameters related to // Current display mode configuration, and other parameters related to
// current display mode. // current display mode.
@@ -183,12 +176,7 @@ struct SharedInfo {
edid1_info edidInfo; edid1_info edidInfo;
bool bHaveEDID; // true = EDID info from device is in edidInfo bool bHaveEDID; // true = EDID info from device is in edidInfo
// Acceleration engine. Benaphore engineLock; // for serializing access to the acceleration engine
struct {
uint64 count; // last fifo slot used
uint64 lastIdle; // last fifo slot we *know* the engine was idle after
benaphore lock; // for serializing access to the acceleration engine
} engine;
int mclk; int mclk;
@@ -198,41 +186,39 @@ struct SharedInfo {
uint16 panelY; // laptop LCD height uint16 panelY; // laptop LCD height
// Command Overflow Buffer (COB) parameters for Savage chips. // Command Overflow Buffer (COB) parameters for Savage chips.
bool bDisableCOB; // enable/disable COB for Savage 4 & ProSavage uint32 cobSizeIndex; // size index
uint32 cobIndex; // size index
uint32 cobSize; // size in bytes
uint32 cobOffset; // offset in video memory uint32 cobOffset; // offset in video memory
uint32 bciThresholdLo; // low and high thresholds for
uint32 bciThresholdHi; // shadow status update (32bit words)
BMPDESC GlobalBD; // Bitmap Descriptor for BCI uint32 globalBitmapDesc; // Global Bitmap Descriptor for BCI
}; };
// Set some boolean condition (like enabling or disabling interrupts) // Set some boolean condition (like enabling or disabling interrupts)
struct S3SetBoolState { struct S3SetBoolState {
uint32 magic; // magic number to make sure the caller groks us uint32 magic; // magic number
bool bEnable; // state to set bool bEnable; // state to set
}; };
// Retrieve the area_id of the kernel/accelerant shared info // Retrieve the area_id of the kernel/accelerant shared info
struct S3GetPrivateData { struct S3GetPrivateData {
uint32 magic; // magic number to make sure the caller groks us uint32 magic; // magic number
area_id sharedInfoArea; // ID of area containing shared information area_id sharedInfoArea; // ID of area containing shared information
}; };
struct S3GetSetPIO { struct S3GetEDID {
uint32 magic; // magic number to make sure the caller groks us uint32 magic; // magic number
uint32 offset; // offset of PIO register to read/write edid1_raw rawEdid; // raw EDID info to obtain
uint32 size; // number of bytes to transfer
uint32 value; // value to write or value that was read
}; };
#if defined(__cplusplus) struct S3GetSetPIO {
} uint32 magic; // magic number
#endif uint32 offset; // offset of PIO register to read/write
uint32 size; // number of bytes to transfer
uint32 value; // value to write or value that was read
};
#endif // DRIVERINTERFACE_H #endif // DRIVERINTERFACE_H
+8 -8
View File
@@ -97,15 +97,15 @@ InitAccelerant(int fileDesc)
} else { } else {
result = gInfo.ChipInit(); // perform init related to current chip result = gInfo.ChipInit(); // perform init related to current chip
if (result == B_OK) { if (result == B_OK) {
result = si.engineLock.Init("ATI engine lock");
if (result == B_OK) {
if (gInfo.ShowCursor != NULL)
gInfo.ShowCursor(false);
INIT_BEN(si.engine.lock); // ensure that this function won't be executed again
si.engine.lastIdle = 0; // (copies should be clones)
si.engine.count = 0; si.bAccelerantInUse = true;
}
gInfo.ShowCursor(false);
// ensure that this function won't be executed again (copies should be clones)
si.bAccelerantInUse = true;
} }
} }
+17 -17
View File
@@ -13,11 +13,6 @@
#include "register_io.h" #include "register_io.h"
#if defined(__cplusplus)
extern "C" {
#endif
#undef TRACE #undef TRACE
@@ -43,7 +38,7 @@ struct AccelerantInfo {
display_mode* modeList; // list of standard display modes display_mode* modeList; // list of standard display modes
area_id modeListArea; // mode list area ID area_id modeListArea; // mode list area ID
bool bAccelerantIsClone;// true if this is a cloned accelerant bool bAccelerantIsClone; // true if this is a cloned accelerant
// Pointers to wait handlers. // Pointers to wait handlers.
void (*WaitQueue)(uint32); void (*WaitQueue)(uint32);
@@ -51,7 +46,7 @@ struct AccelerantInfo {
// Pointers to DPMS functions. // Pointers to DPMS functions.
uint32 (*DPMSCapabilities)(void); uint32 (*DPMSCapabilities)(void);
uint32 (*DPMSMode)(void); uint32 (*GetDPMSMode)(void);
status_t (*SetDPMSMode)(uint32 dpms_flags); status_t (*SetDPMSMode)(uint32 dpms_flags);
// Pointers to cursor functions. // Pointers to cursor functions.
@@ -82,6 +77,10 @@ extern AccelerantInfo gInfo;
// chips will have no prefix. // chips will have no prefix.
//================================================================ //================================================================
#if defined(__cplusplus)
extern "C" {
#endif
// General // General
status_t InitAccelerant(int fd); status_t InitAccelerant(int fd);
ssize_t AccelerantCloneInfoSize(void); ssize_t AccelerantCloneInfoSize(void);
@@ -109,15 +108,15 @@ status_t GetEdidInfo(void* info, size_t size, uint32* _version);
// DPMS // DPMS
uint32 Savage_DPMSCapabilities(void); uint32 Savage_DPMSCapabilities(void);
uint32 Savage_DPMSMode(void); uint32 Savage_GetDPMSMode(void);
status_t Savage_SetDPMSMode(uint32 dpms_flags); status_t Savage_SetDPMSMode(uint32 dpms_flags);
uint32 Trio64_DPMSCapabilities(void); uint32 Trio64_DPMSCapabilities(void);
uint32 Trio64_DPMSMode(void); uint32 Trio64_GetDPMSMode(void);
status_t Trio64_SetDPMSMode(uint32 dpms_flags); status_t Trio64_SetDPMSMode(uint32 dpms_flags);
uint32 Virge_DPMSCapabilities(void); uint32 Virge_DPMSCapabilities(void);
uint32 Virge_DPMSMode(void); uint32 Virge_GetDPMSMode(void);
status_t Virge_SetDPMSMode(uint32 dpms_flags); status_t Virge_SetDPMSMode(uint32 dpms_flags);
// Cursor // Cursor
@@ -152,20 +151,25 @@ void Virge_FillSpan(engine_token* et, uint32 color, uint16* list, uint32 count)
void Virge_InvertRectangle(engine_token* et, fill_rect_params* list, uint32 count); void Virge_InvertRectangle(engine_token* et, fill_rect_params* list, uint32 count);
void Virge_ScreenToScreenBlit(engine_token* et, blit_params* list, uint32 count); void Virge_ScreenToScreenBlit(engine_token* et, blit_params* list, uint32 count);
#if defined(__cplusplus)
}
#endif
// Prototypes for other functions that are called from source files other than // Prototypes for other functions that are called from source files other than
// where they are defined. // where they are defined.
//============================================================================ //============================================================================
status_t CreateModeList(bool (*checkMode)(const display_mode* mode)); status_t CreateModeList(bool (*checkMode)(const display_mode* mode),
bool (*getEdid)(edid1_info& edidInfo));
void InitCrtcTimingValues(const DisplayModeEx& mode, int horzScaleFactor, uint8 crtc[], void InitCrtcTimingValues(const DisplayModeEx& mode, int horzScaleFactor, uint8 crtc[],
uint8& cr3b, uint8& cr3c, uint8& cr5d, uint8& cr5e); uint8& cr3b, uint8& cr3c, uint8& cr5d, uint8& cr5e);
bool IsModeUsable(const display_mode* mode); bool IsModeUsable(const display_mode* mode);
// Savage functions. // Savage functions.
bool Savage_GetEdidInfo(void); bool Savage_GetEdidInfo(edid1_info& edidInfo);
bool Savage_LoadCursorImage(int width, int height, uint8* and_mask, uint8* xor_mask); bool Savage_LoadCursorImage(int width, int height, uint8* and_mask, uint8* xor_mask);
void Savage_SetCursorPosition(int x, int y); void Savage_SetCursorPosition(int x, int y);
@@ -185,7 +189,7 @@ void Trio64_SetFunctionPointers(void);
// Virge functions. // Virge functions.
bool Virge_GetEdidInfo(void); bool Virge_GetEdidInfo(edid1_info& edidInfo);
bool Virge_LoadCursorImage(int width, int height, uint8* and_mask, uint8* xor_mask); bool Virge_LoadCursorImage(int width, int height, uint8* and_mask, uint8* xor_mask);
void Virge_SetCursorPosition(int x, int y); void Virge_SetCursorPosition(int x, int y);
@@ -195,8 +199,4 @@ bool Virge_SetDisplayMode(const DisplayModeEx& mode);
void Virge_SetFunctionPointers(void); void Virge_SetFunctionPointers(void);
#if defined(__cplusplus)
}
#endif
#endif // _ACCEL_H #endif // _ACCEL_H
+6 -6
View File
@@ -9,7 +9,7 @@
#include "accel.h" #include "accel.h"
status_t status_t
SetCursorShape(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y, SetCursorShape(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y,
uint8* andMask, uint8* xorMask) uint8* andMask, uint8* xorMask)
{ {
@@ -23,8 +23,8 @@ SetCursorShape(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y,
// Update cursor variables appropriately. // Update cursor variables appropriately.
SharedInfo& si = *gInfo.sharedInfo; SharedInfo& si = *gInfo.sharedInfo;
si.cursor.hot_x = hot_x; si.cursorHotX = hot_x;
si.cursor.hot_y = hot_y; si.cursorHotY = hot_y;
if ( ! gInfo.LoadCursorImage(width, height, andMask, xorMask)) if ( ! gInfo.LoadCursorImage(width, height, andMask, xorMask))
return B_ERROR; return B_ERROR;
@@ -34,7 +34,7 @@ SetCursorShape(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y,
} }
void void
MoveCursor(uint16 xPos, uint16 yPos) MoveCursor(uint16 xPos, uint16 yPos)
{ {
// Move the cursor to the specified position on the desktop. If we're // Move the cursor to the specified position on the desktop. If we're
@@ -72,8 +72,8 @@ MoveCursor(uint16 xPos, uint16 yPos)
MoveDisplay(hds, vds); MoveDisplay(hds, vds);
// Put cursor in correct physical position. // Put cursor in correct physical position.
x -= (hds + si.cursor.hot_x); x -= (hds + si.cursorHotX);
y -= (vds + si.cursor.hot_y); y -= (vds + si.cursorHotY);
// Position the cursor on the display. // Position the cursor on the display.
gInfo.SetCursorPosition(x, y); gInfo.SetCursorPosition(x, y);
+12 -13
View File
@@ -3,7 +3,7 @@
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
Other authors: Other authors:
Gerald Zajac 2007 Gerald Zajac 2007-2008
*/ */
#include "accel.h" #include "accel.h"
@@ -12,22 +12,23 @@
static engine_token engineToken = { 1, B_2D_ACCELERATION, NULL }; static engine_token engineToken = { 1, B_2D_ACCELERATION, NULL };
uint32 uint32
AccelerantEngineCount(void) AccelerantEngineCount(void)
{ {
return 1; return 1;
} }
status_t status_t
AcquireEngine(uint32 capabilities, uint32 max_wait, AcquireEngine(uint32 capabilities, uint32 max_wait,
sync_token* st, engine_token** et) sync_token* st, engine_token** et)
{ {
(void)capabilities; // avoid compiler warning for unused arg (void)capabilities; // avoid compiler warning for unused arg
(void)max_wait; // avoid compiler warning for unused arg (void)max_wait; // avoid compiler warning for unused arg
// Acquire the shared benaphore. if (gInfo.sharedInfo->engineLock.Acquire() != B_OK)
AQUIRE_BEN(gInfo.sharedInfo->engine.lock) return B_ERROR;
// Sync if required. // Sync if required.
if (st) if (st)
SyncToToken(st); SyncToToken(st);
@@ -38,37 +39,35 @@ AcquireEngine(uint32 capabilities, uint32 max_wait,
} }
status_t status_t
ReleaseEngine(engine_token* et, sync_token* st) ReleaseEngine(engine_token* et, sync_token* st)
{ {
// Update the sync token, if any. // Update the sync token, if any.
if (st) if (st)
GetSyncToken(et, st); GetSyncToken(et, st);
// Release the shared benaphore. gInfo.sharedInfo->engineLock.Release();
RELEASE_BEN(gInfo.sharedInfo->engine.lock)
return B_OK; return B_OK;
} }
void void
WaitEngineIdle(void) WaitEngineIdle(void)
{ {
gInfo.WaitIdleEmpty(); // wait until engine is completely idle gInfo.WaitIdleEmpty(); // wait until engine is completely idle
} }
status_t status_t
GetSyncToken(engine_token* et, sync_token* st) GetSyncToken(engine_token* et, sync_token* st)
{ {
// Engine count will always be zero: we don't support syncing to token (yet).
st->engine_id = et->engine_id; st->engine_id = et->engine_id;
st->counter = gInfo.sharedInfo->engine.count; st->counter = 0;
return B_OK; return B_OK;
} }
status_t status_t
SyncToToken(sync_token* st) SyncToToken(sync_token* st)
{ {
(void)st; // avoid compiler warning for unused arg (void)st; // avoid compiler warning for unused arg
+17 -8
View File
@@ -14,6 +14,8 @@ get_accelerant_hook(uint32 feature, void* data)
{ {
(void)data; // avoid compiler warning for unused arg (void)data; // avoid compiler warning for unused arg
SharedInfo& si = *gInfo.sharedInfo;
switch (feature) { switch (feature) {
// General // General
case B_INIT_ACCELERANT: return (void*)InitAccelerant; case B_INIT_ACCELERANT: return (void*)InitAccelerant;
@@ -42,13 +44,16 @@ get_accelerant_hook(uint32 feature, void* data)
// DPMS // DPMS
case B_DPMS_CAPABILITIES: return (void*)(gInfo.DPMSCapabilities); case B_DPMS_CAPABILITIES: return (void*)(gInfo.DPMSCapabilities);
case B_DPMS_MODE: return (void*)(gInfo.DPMSMode); case B_DPMS_MODE: return (void*)(gInfo.GetDPMSMode);
case B_SET_DPMS_MODE: return (void*)(gInfo.SetDPMSMode); case B_SET_DPMS_MODE: return (void*)(gInfo.SetDPMSMode);
// Cursor // Cursor
case B_SET_CURSOR_SHAPE: return (void*)SetCursorShape; case B_SET_CURSOR_SHAPE:
case B_MOVE_CURSOR: return (void*)MoveCursor; return (void*)(si.bDisableHdwCursor ? NULL : SetCursorShape);
case B_SHOW_CURSOR: return (void*)(gInfo.ShowCursor); case B_MOVE_CURSOR:
return (void*)(si.bDisableHdwCursor ? NULL : MoveCursor);
case B_SHOW_CURSOR:
return (void*)(si.bDisableHdwCursor ? NULL : gInfo.ShowCursor);
// Engine Management // Engine Management
case B_ACCELERANT_ENGINE_COUNT: return (void*)AccelerantEngineCount; case B_ACCELERANT_ENGINE_COUNT: return (void*)AccelerantEngineCount;
@@ -59,10 +64,14 @@ get_accelerant_hook(uint32 feature, void* data)
case B_SYNC_TO_TOKEN: return (void*)SyncToToken; case B_SYNC_TO_TOKEN: return (void*)SyncToToken;
// 2D acceleration // 2D acceleration
case B_SCREEN_TO_SCREEN_BLIT: return (void*)(gInfo.ScreenToScreenBlit); case B_SCREEN_TO_SCREEN_BLIT:
case B_FILL_RECTANGLE: return (void*)(gInfo.FillRectangle); return (void*)(si.bDisableAccelDraw ? NULL : gInfo.ScreenToScreenBlit);
case B_INVERT_RECTANGLE: return (void*)(gInfo.InvertRectangle); case B_FILL_RECTANGLE:
case B_FILL_SPAN: return (void*)(gInfo.FillSpan); return (void*)(si.bDisableAccelDraw ? NULL : gInfo.FillRectangle);
case B_INVERT_RECTANGLE:
return (void*)(si.bDisableAccelDraw ? NULL : gInfo.InvertRectangle);
case B_FILL_SPAN:
return (void*)(si.bDisableAccelDraw ? NULL : gInfo.FillSpan);
} }
return NULL; // Return null pointer for any feature not handled above return NULL; // Return null pointer for any feature not handled above
+112 -49
View File
@@ -8,8 +8,9 @@
#include "accel.h" #include "accel.h"
#include <create_display_modes.h> #include <create_display_modes.h> // common accelerant header file
#include <string.h> #include <string.h>
#include <unistd.h>
void void
@@ -29,7 +30,7 @@ InitCrtcTimingValues(const DisplayModeEx& mode, int horzScaleFactor, uint8 crtc[
int hDisp_e = (mode.timing.h_display * horzScaleFactor) / 8 - 1; int hDisp_e = (mode.timing.h_display * horzScaleFactor) / 8 - 1;
int hSync_s = (mode.timing.h_sync_start * horzScaleFactor) / 8; int hSync_s = (mode.timing.h_sync_start * horzScaleFactor) / 8;
int hSync_e = (mode.timing.h_sync_end * horzScaleFactor) / 8; int hSync_e = (mode.timing.h_sync_end * horzScaleFactor) / 8;
int hBlank_s = hDisp_e; // start of horizontal blanking int hBlank_s = hDisp_e + 1; // start of horizontal blanking
int hBlank_e = hTotal; // end of horizontal blanking int hBlank_e = hTotal; // end of horizontal blanking
int vTotal = mode.timing.v_total - 2; int vTotal = mode.timing.v_total - 2;
@@ -39,8 +40,6 @@ InitCrtcTimingValues(const DisplayModeEx& mode, int horzScaleFactor, uint8 crtc[
int vBlank_s = vDisp_e; // start of vertical blanking int vBlank_s = vDisp_e; // start of vertical blanking
int vBlank_e = vTotal; // end of vertical blanking int vBlank_e = vTotal; // end of vertical blanking
TRACE("InitCrtcTimingValues()\n");
// CRTC Controller values // CRTC Controller values
crtc[0x00] = hTotal; crtc[0x00] = hTotal;
@@ -146,6 +145,28 @@ FindDisplayMode(int width, int height, int refreshRate, uint32 colorDepth)
} }
static bool
IsThereEnoughFBMemory(const display_mode* mode, uint32 bitsPerPixel)
{
// Test if there is enough Frame Buffer memory for the mode and color depth
// specified by the caller, and return true if there is sufficient memory.
uint32 maxWidth = mode->virtual_width;
if (mode->timing.h_display > maxWidth)
maxWidth = mode->timing.h_display;
uint32 maxHeight = mode->virtual_height;
if (mode->timing.v_display > maxHeight)
maxHeight = mode->timing.v_display;
uint32 bytesPerPixel = (bitsPerPixel + 7) / 8;
return (maxWidth * maxHeight * bytesPerPixel < gInfo.sharedInfo->maxFrameBufferSize);
}
bool bool
IsModeUsable(const display_mode* mode) IsModeUsable(const display_mode* mode)
{ {
@@ -162,10 +183,9 @@ IsModeUsable(const display_mode* mode)
if ( ! gInfo.GetColorSpaceParams(mode->space, bitsPerPixel, maxPixelClock)) if ( ! gInfo.GetColorSpaceParams(mode->space, bitsPerPixel, maxPixelClock))
return false; return false;
// Is there enough memory to handle the mode? // Is there enough frame buffer memory to handle the mode?
if (mode->virtual_width * mode->virtual_height * ((bitsPerPixel + 7) / 8) if ( ! IsThereEnoughFBMemory(mode, bitsPerPixel))
> si.maxFrameBufferSize)
return false; return false;
if (mode->timing.pixel_clock > maxPixelClock) if (mode->timing.pixel_clock > maxPixelClock)
@@ -190,42 +210,65 @@ IsModeUsable(const display_mode* mode)
if (mode->timing.h_display == 640 && mode->timing.v_display < 480) if (mode->timing.h_display == 640 && mode->timing.v_display < 480)
return false; return false;
// In most mode lists, there are three entries for 640 x 480 which have a // If the video chip is connected directly to an LCD display (ie, laptop
// refresh rate of 60 Hz. The one with a pixel clock of 25175 works fine
// with the S3 chips; however, the other two with higher clock rates
// cause the display to be offset down and to the right; thus, reject them.
if (mode->timing.h_display == 640 && mode->timing.v_display == 480) {
int modeRefreshRate = int(((mode->timing.pixel_clock * 1000.0 /
mode->timing.h_total) / mode->timing.v_total) + 0.5);
if (modeRefreshRate == 60 && mode->timing.pixel_clock > 26000)
return false;
}
// If the video is connected directly to an LCD display (ie, laptop
// computer), restrict the display mode to resolutions where the width and // computer), restrict the display mode to resolutions where the width and
// height of the mode are less than or equal to the width and height of the // height of the mode are less than or equal to the width and height of the
// LCD display. Note that this code is not needed under Haiku since it can // LCD display.
// get the preferred mode which should be the resolution of the LCD display.
#ifndef __HAIKU__ if (si.displayType == MT_LCD && si.panelX > 0 && si.panelY > 0
&& (mode->timing.h_display > si.panelX
if (si.displayType == MT_LCD && si.panelX > 0 && si.panelY > 0 &&
(mode->timing.h_display > si.panelX
|| mode->timing.v_display > si.panelY)) { || mode->timing.v_display > si.panelY)) {
return false; return false;
} }
#endif // __HAIKU__
return true; return true;
} }
status_t status_t
CreateModeList(bool (*checkMode)(const display_mode* mode)) CreateModeList( bool (*checkMode)(const display_mode* mode),
bool (*getEdid)(edid1_info& edidInfo))
{ {
SharedInfo& si = *gInfo.sharedInfo; SharedInfo& si = *gInfo.sharedInfo;
// Obtain EDID info which is needed for for building the mode list.
// However, if a laptop's LCD display is active, bypass getting the EDID
// info since it is not needed, and if the external display supports only
// resolutions smaller than the size of the laptop LCD display, it would
// unnecessarily restrict size of the resolutions that could be set for
// laptop LCD display.
si.bHaveEDID = false;
if (si.displayType != MT_LCD) {
if (getEdid != NULL)
si.bHaveEDID = getEdid(si.edidInfo);
if ( ! si.bHaveEDID) {
S3GetEDID ged;
ged.magic = S3_PRIVATE_DATA_MAGIC;
if (ioctl(gInfo.deviceFileDesc, S3_GET_EDID, &ged, sizeof(ged)) == B_OK) {
if (ged.rawEdid.version.version != 1
|| ged.rawEdid.version.revision > 4) {
TRACE("CreateModeList(); EDID version %d.%d out of range\n",
ged.rawEdid.version.version, ged.rawEdid.version.revision);
} else {
edid_decode(&si.edidInfo, &ged.rawEdid); // decode & save EDID info
si.bHaveEDID = true;
}
}
}
if (si.bHaveEDID) {
#ifdef ENABLE_DEBUG_TRACE
edid_dump(&(si.edidInfo));
#endif
} else {
TRACE("CreateModeList(); Unable to get EDID info\n");
}
}
display_mode* list; display_mode* list;
uint32 count = 0; uint32 count = 0;
area_id listArea; area_id listArea;
@@ -254,9 +297,9 @@ ProposeDisplayMode(display_mode *target, const display_mode *low,
(void)low; // avoid compiler warning for unused arg (void)low; // avoid compiler warning for unused arg
(void)high; // avoid compiler warning for unused arg (void)high; // avoid compiler warning for unused arg
TRACE("ProposeDisplayMode() clock: %d, width: %d, height: %d, space: 0x%X\n", TRACE("ProposeDisplayMode() %dx%d, pixel clock: %d kHz, space: 0x%X\n",
target->timing.pixel_clock, target->virtual_width, target->virtual_height, target->timing.h_display, target->timing.v_display,
target->space); target->timing.pixel_clock, target->space);
// Search the mode list for the specified mode. // Search the mode list for the specified mode.
@@ -275,6 +318,7 @@ ProposeDisplayMode(display_mode *target, const display_mode *low,
} }
status_t status_t
SetDisplayMode(display_mode* pMode) SetDisplayMode(display_mode* pMode)
{ {
@@ -290,27 +334,50 @@ SetDisplayMode(display_mode* pMode)
if ( ! gInfo.GetColorSpaceParams(mode.space, mode.bpp, maxPixelClock)) if ( ! gInfo.GetColorSpaceParams(mode.space, mode.bpp, maxPixelClock))
return B_ERROR; return B_ERROR;
mode.bytesPerRow = mode.virtual_width * ((mode.bpp + 7) / 8); // use virtual width
if (ProposeDisplayMode(&mode, pMode, pMode) != B_OK) if (ProposeDisplayMode(&mode, pMode, pMode) != B_OK)
return B_ERROR; return B_ERROR;
// Test if there is sufficient memory for this mode. Use the virtual width // Note that for some Savage chips, accelerated drawing is badly messed up
// and height for this calculation since one or both might be greater than // when the display width is 1400 because 1400 is not evenly divisible by 32.
// the actual dimensions of the mode. // For those chips, set the width to 1408 so that accelerated drawing will
// draw properly.
if (mode.bytesPerRow * mode.virtual_height > si.maxFrameBufferSize) if (mode.timing.h_display == 1400 && (si.chipType == S3_PROSAVAGE
|| si.chipType == S3_PROSAVAGE_DDR
|| si.chipType == S3_TWISTER
|| si.chipType == S3_SUPERSAVAGE
|| si.chipType == S3_SAVAGE2000)) {
mode.timing.h_display = 1408;
mode.virtual_width = 1408;
}
int bytesPerPixel = (mode.bpp + 7) / 8;
mode.bytesPerRow = mode.timing.h_display * bytesPerPixel;
// Is there enough frame buffer memory for this mode?
if ( ! IsThereEnoughFBMemory(&mode, mode.bpp))
return B_ERROR; return B_ERROR;
TRACE("Display Mode: width = %d, height = %d, depth = %d\n", TRACE("Set display mode: %dx%d virtual size: %dx%d color depth: %d bpp\n",
mode.timing.h_display, mode.timing.v_display,
mode.virtual_width, mode.virtual_height, mode.bpp); mode.virtual_width, mode.virtual_height, mode.bpp);
TRACE("Mode Timing = { %d %d %d %d %d %d %d %d %d 0x%x }\n", TRACE(" mode timing: %d %d %d %d %d %d %d %d %d\n",
mode.timing.pixel_clock, mode.timing.pixel_clock,
mode.timing.h_display, mode.timing.h_sync_start, mode.timing.h_sync_end, mode.timing.h_display,
mode.timing.h_sync_start, mode.timing.h_sync_end,
mode.timing.h_total, mode.timing.h_total,
mode.timing.v_display, mode.timing.v_sync_start, mode.timing.v_sync_end, mode.timing.v_display,
mode.timing.v_total, mode.timing.flags); mode.timing.v_sync_start, mode.timing.v_sync_end,
mode.timing.v_total);
TRACE(" mode hFreq: %.1f kHz vFreq: %.1f Hz %chSync %cvSync\n",
double(mode.timing.pixel_clock) / mode.timing.h_total,
((double(mode.timing.pixel_clock) / mode.timing.h_total) * 1000.0)
/ mode.timing.v_total,
(mode.timing.flags & B_POSITIVE_HSYNC) ? '+' : '-',
(mode.timing.flags & B_POSITIVE_VSYNC) ? '+' : '-');
if ( ! gInfo.SetDisplayMode(mode)) if ( ! gInfo.SetDisplayMode(mode))
return B_ERROR; return B_ERROR;
@@ -379,7 +446,8 @@ GetFrameBufferConfig(frame_buffer_config* pFBC)
pFBC->frame_buffer = (void*)((addr_t)si.videoMemAddr + si.frameBufferOffset); pFBC->frame_buffer = (void*)((addr_t)si.videoMemAddr + si.frameBufferOffset);
pFBC->frame_buffer_dma = (void*)((addr_t)si.videoMemPCI + si.frameBufferOffset); pFBC->frame_buffer_dma = (void*)((addr_t)si.videoMemPCI + si.frameBufferOffset);
pFBC->bytes_per_row = si.displayMode.bytesPerRow; uint32 bytesPerPixel = (si.displayMode.bpp + 7) / 8;
pFBC->bytes_per_row = si.displayMode.virtual_width * bytesPerPixel;
return B_OK; return B_OK;
} }
@@ -418,7 +486,6 @@ GetTimingConstraints(display_timing_constraints *constraints)
{ {
(void)constraints; // avoid compiler warning for unused arg (void)constraints; // avoid compiler warning for unused arg
TRACE("GetTimingConstraints() called\n");
return B_ERROR; return B_ERROR;
} }
@@ -429,8 +496,6 @@ GetPreferredDisplayMode(display_mode* preferredMode)
// If the chip is connected to a laptop LCD panel, find the mode with // If the chip is connected to a laptop LCD panel, find the mode with
// matching width and height, 60 Hz refresh rate, and greatest color depth. // matching width and height, 60 Hz refresh rate, and greatest color depth.
TRACE("GetPreferredDisplayMode()\n");
SharedInfo& si = *gInfo.sharedInfo; SharedInfo& si = *gInfo.sharedInfo;
if (si.displayType == MT_LCD) { if (si.displayType == MT_LCD) {
@@ -452,8 +517,6 @@ GetPreferredDisplayMode(display_mode* preferredMode)
status_t status_t
GetEdidInfo(void* info, size_t size, uint32* _version) GetEdidInfo(void* info, size_t size, uint32* _version)
{ {
TRACE("GetEdidInfo()\n");
SharedInfo& si = *gInfo.sharedInfo; SharedInfo& si = *gInfo.sharedInfo;
if ( ! si.bHaveEDID) if ( ! si.bHaveEDID)
+3 -11
View File
@@ -40,17 +40,9 @@
// Primary Stream 2 Stride. // Primary Stream 2 Stride.
#define PRI_STREAM2_STRIDE 0x81b8 #define PRI_STREAM2_STRIDE 0x81b8
#define S3_GLOBAL_GBD_REG 0x816C // global bitmap descriptor register
#define MEMORY_CTRL0_REG 0xCA #define MEMORY_CTRL0_REG 0xCA
#define MEMORY_CONFIG_REG 0x31
// Bitmap descriptor register.
#define S3_GLB_BD_LOW 0x8168
#define S3_GLB_BD_HIGH 0x816C
#define S3_PRI_BD_LOW 0x8170
#define S3_PRI_BD_HIGH 0x8174
#define S3_SEC_BD_LOW 0x8178
#define S3_SEC_BD_HIGH 0x817c
#define MEM_PS1 0x10 // CRCA_4 :Primary stream 1 #define MEM_PS1 0x10 // CRCA_4 :Primary stream 1
#define MEM_PS2 0x20 // CRCA_5 :Primary stream 2 #define MEM_PS2 0x20 // CRCA_5 :Primary stream 2
@@ -73,7 +65,6 @@
#define TILE_FORMAT_LINEAR 0 #define TILE_FORMAT_LINEAR 0
// BD - BCI enable.
#define BCI_ENABLE 8 // savage4, MX, IX, 3D #define BCI_ENABLE 8 // savage4, MX, IX, 3D
#define BCI_ENABLE_TWISTER 0 // twister, prosavage, DDR, supersavage, 2000 #define BCI_ENABLE_TWISTER 0 // twister, prosavage, DDR, supersavage, 2000
@@ -81,6 +72,7 @@
#define S3_LITTLE_ENDIAN 0 #define S3_LITTLE_ENDIAN 0
#define S3_BD64 1 #define S3_BD64 1
#define BCI_BD_BW_DISABLE 0x10000000
#define BCI_BUFFER_OFFSET 0x10000 #define BCI_BUFFER_OFFSET 0x10000
#define BCI_GET_PTR vuint32* bci_ptr = ((uint32*)(gInfo.regs + BCI_BUFFER_OFFSET)) #define BCI_GET_PTR vuint32* bci_ptr = ((uint32*)(gInfo.regs + BCI_BUFFER_OFFSET))
+2 -2
View File
@@ -27,7 +27,7 @@ Savage_DPMSCapabilities(void)
uint32 uint32
Savage_DPMSMode(void) Savage_GetDPMSMode(void)
{ {
// Return the current DPMS mode. // Return the current DPMS mode.
@@ -59,7 +59,7 @@ Savage_DPMSMode(void)
mode = ((ReadSeqReg(0x31) & 0x10) ? B_DPMS_ON : B_DPMS_OFF); mode = ((ReadSeqReg(0x31) & 0x10) ? B_DPMS_ON : B_DPMS_OFF);
} }
TRACE("Savage_DPMSMode() mode: %d\n", mode); TRACE("Savage_GetDPMSMode() mode: %d\n", mode);
return mode; return mode;
} }
+13 -13
View File
@@ -25,7 +25,7 @@ Savage_FillRectangle(engine_token *et, uint32 color, fill_rect_params *pList, ui
(void)et; // avoid compiler warning for unused arg (void)et; // avoid compiler warning for unused arg
BCI_CMD_SET_ROP(cmd, 0xCC); // use GXcopy for rop BCI_CMD_SET_ROP(cmd, 0xF0); // use GXcopy for rop
while (count--) { while (count--) {
int x = pList->left; int x = pList->left;
@@ -38,8 +38,8 @@ Savage_FillRectangle(engine_token *et, uint32 color, fill_rect_params *pList, ui
gInfo.WaitQueue(7); gInfo.WaitQueue(7);
BCI_SEND(cmd); BCI_SEND(cmd);
BCI_SEND(gInfo.sharedInfo->GlobalBD.bd2.LoPart); BCI_SEND(gInfo.sharedInfo->frameBufferOffset);
BCI_SEND(gInfo.sharedInfo->GlobalBD.bd2.HiPart); BCI_SEND(gInfo.sharedInfo->globalBitmapDesc);
BCI_SEND(color); BCI_SEND(color);
BCI_SEND(BCI_X_Y(x, y)); BCI_SEND(BCI_X_Y(x, y));
@@ -58,7 +58,7 @@ Savage_FillSpan(engine_token *et, uint32 color, uint16 *pList, uint32 count)
(void)et; // avoid compiler warning for unused arg (void)et; // avoid compiler warning for unused arg
BCI_CMD_SET_ROP(cmd, 0xCC); // use GXcopy for rop BCI_CMD_SET_ROP(cmd, 0xF0); // use GXcopy for rop
while (count--) { while (count--) {
int y = *pList++; int y = *pList++;
@@ -78,8 +78,8 @@ Savage_FillSpan(engine_token *et, uint32 color, uint16 *pList, uint32 count)
gInfo.WaitQueue(7); gInfo.WaitQueue(7);
BCI_SEND(cmd); BCI_SEND(cmd);
BCI_SEND(gInfo.sharedInfo->GlobalBD.bd2.LoPart); BCI_SEND(gInfo.sharedInfo->frameBufferOffset);
BCI_SEND(gInfo.sharedInfo->GlobalBD.bd2.HiPart); BCI_SEND(gInfo.sharedInfo->globalBitmapDesc);
BCI_SEND(color); BCI_SEND(color);
BCI_SEND(BCI_X_Y(x, y)); BCI_SEND(BCI_X_Y(x, y));
@@ -109,8 +109,8 @@ Savage_InvertRectangle(engine_token *et, fill_rect_params *pList, uint32 count)
gInfo.WaitQueue(7); gInfo.WaitQueue(7);
BCI_SEND(cmd); BCI_SEND(cmd);
BCI_SEND(gInfo.sharedInfo->GlobalBD.bd2.LoPart); BCI_SEND(gInfo.sharedInfo->frameBufferOffset);
BCI_SEND(gInfo.sharedInfo->GlobalBD.bd2.HiPart); BCI_SEND(gInfo.sharedInfo->globalBitmapDesc);
BCI_SEND(BCI_X_Y(x, y)); BCI_SEND(BCI_X_Y(x, y));
BCI_SEND(BCI_W_H(w, h)); BCI_SEND(BCI_W_H(w, h));
@@ -157,17 +157,17 @@ Savage_ScreenToScreenBlit(engine_token *et, blit_params *pList, uint32 count)
BCI_SEND(cmd); BCI_SEND(cmd);
BCI_SEND(gInfo.sharedInfo->GlobalBD.bd2.LoPart); BCI_SEND(gInfo.sharedInfo->frameBufferOffset);
BCI_SEND(gInfo.sharedInfo->GlobalBD.bd2.HiPart); BCI_SEND(gInfo.sharedInfo->globalBitmapDesc);
BCI_SEND(gInfo.sharedInfo->GlobalBD.bd2.LoPart); BCI_SEND(gInfo.sharedInfo->frameBufferOffset);
BCI_SEND(gInfo.sharedInfo->GlobalBD.bd2.HiPart); BCI_SEND(gInfo.sharedInfo->globalBitmapDesc);
BCI_SEND(BCI_X_Y(src_x, src_y)); BCI_SEND(BCI_X_Y(src_x, src_y));
BCI_SEND(BCI_X_Y(dest_x, dest_y)); BCI_SEND(BCI_X_Y(dest_x, dest_y));
BCI_SEND(BCI_W_H(width + 1, height + 1)); BCI_SEND(BCI_W_H(width + 1, height + 1));
pList ++; pList++;
} }
} }
+3 -12
View File
@@ -50,7 +50,7 @@ SetI2CSignals(void* cookie, int _clock, int data)
bool bool
Savage_GetEdidInfo(void) Savage_GetEdidInfo(edid1_info& edidInfo)
{ {
// Get the EDID info and return true if successful. // Get the EDID info and return true if successful.
@@ -83,17 +83,8 @@ Savage_GetEdidInfo(void)
uint8 tmp = ReadCrtcReg(DDCPort); uint8 tmp = ReadCrtcReg(DDCPort);
WriteCrtcReg(DDCPort, tmp | 0x13); WriteCrtcReg(DDCPort, tmp | 0x13);
si.bHaveEDID = (ddc2_read_edid1(&bus, &(si.edidInfo), NULL, NULL) == B_OK); bool bResult = (ddc2_read_edid1(&bus, &edidInfo, NULL, NULL) == B_OK);
WriteCrtcReg(DDCPort, tmp); WriteCrtcReg(DDCPort, tmp);
if (si.bHaveEDID) { return bResult;
#ifdef ENABLE_DEBUG_TRACE
edid_dump(&(si.edidInfo));
#endif
} else {
TRACE("Savage_GetEdidInfo() failed!\n");
}
return si.bHaveEDID;
} }
+30 -76
View File
@@ -95,23 +95,6 @@ WaitIdleEmpty2K()
} }
static bool
IsLCDWidthValid(int width)
{
// Search the array of valid LCD widths to find a width that matches the
// width by the caller, and return true if a match is found.
const int lcdWidths[] = { 640, 800, 1024, 1152, 1280, 1400, 1440, 1600, 1680 };
for (int i = 0; i < NUM_ELEMENTS(lcdWidths); i++) {
if (lcdWidths[i] == width)
return true;
}
return false; // match not found
}
static void static void
Savage_GetPanelInfo() Savage_GetPanelInfo()
{ {
@@ -132,20 +115,12 @@ Savage_GetPanelInfo()
int panelX = (ReadSeqReg(0x61) + ((ReadSeqReg(0x66) & 0x02) << 7) + 1) * 8; int panelX = (ReadSeqReg(0x61) + ((ReadSeqReg(0x66) & 0x02) << 7) + 1) * 8;
int panelY = ReadSeqReg(0x69) + ((ReadSeqReg(0x6e) & 0x70) << 4) + 1; int panelY = ReadSeqReg(0x69) + ((ReadSeqReg(0x6e) & 0x70) << 4) + 1;
if ( ! IsLCDWidthValid(panelX)) { // A Savage IX/MV in a Thinkpad T22 or SuperSavage in a Thinkpad T23 with
// a 1400x1050 display will return a width of 1408; thus, in this case,
// set the width to the correct value of 1400.
// Some chips such as the Savage IX/MV in a Thinkpad T-22 will return if (panelX == 1408)
// a width that is 8 pixels too wide probably because reg SR61 is set panelX = 1400;
// to a value +1 higher than it should be. Subtract 8 from the width,
// and check if that is a valid width.
panelX -= 8;
if ( ! IsLCDWidthValid(panelX)) {
TRACE("%dx%d LCD panel width invalid.\n", panelX + 8, panelY);
si.displayType = MT_CRT;
return;
}
}
char* sTechnology; char* sTechnology;
@@ -199,7 +174,7 @@ Savage_Init(void)
static uint8 RamSavage4[] = { 2, 4, 8, 12, 16, 32, 64, 32 }; static uint8 RamSavage4[] = { 2, 4, 8, 12, 16, 32, 64, 32 };
static const uint8 RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 }; static const uint8 RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
static const uint8 RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 16, 2 }; static const uint8 RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 16, 2 };
int ramSizeMB = 0; // memory size in megabytes uint32 ramSizeMB = 0; // memory size in megabytes
uint8 cr36 = ReadCrtcReg(0x36); // get amount of video ram uint8 cr36 = ReadCrtcReg(0x36); // get amount of video ram
@@ -239,57 +214,37 @@ Savage_Init(void)
break; break;
} }
TRACE("Savage_Init() memory size: %d MB\n", ramSizeMB); uint32 usableMB = ramSizeMB;
if (ramSizeMB <= 0)
// If a Savage MX chip has > 8 MB, clamp it at 8 MB since memory for the
// hardware cursor above 8 MB is unusable.
if (si.chipType == S3_SAVAGE_MX && ramSizeMB > 8)
usableMB = 8;
TRACE("Savage_Init() memory size: %d MB, usable memory: %d MB\n", ramSizeMB, usableMB);
if (usableMB <= 0)
return B_ERROR; return B_ERROR;
si.videoMemSize = ramSizeMB * 1024 * 1024; si.videoMemSize = usableMB * 1024 * 1024;
// Certain Savage4 and ProSavage chips can have coherency problems
// with respect to the Command Overflow Buffer (COB); thus, to avoid
// problems with these chips, set bDisableCOB to true.
si.bDisableCOB = false;
// Compute the Command Overflow Buffer (COB) location. // Compute the Command Overflow Buffer (COB) location.
if ((S3_SAVAGE4_SERIES(si.chipType) || S3_SUPERSAVAGE == si.chipType) uint32 cobSize = 0x20000; // use 128kB for the COB
&& si.bDisableCOB) { si.cobSizeIndex = 7;
// The Savage4 and ProSavage have COB coherency bugs which render
// the buffer useless.
si.cobIndex = 0;
si.cobSize = 0;
si.bciThresholdHi = 32;
si.bciThresholdLo = 0;
} else {
// We use 128kB for the COB on all other chips.
si.cobSize = 0x20000;
if (S3_SAVAGE_3D_SERIES(si.chipType) || si.chipType == S3_SAVAGE2000)
si.cobIndex = 7; // rev.A savage4 apparently also uses 7
else
si.cobIndex = 2;
// Max command size: 2560 entries.
si.bciThresholdHi = si.cobSize / 4 + 32 - 2560;
si.bciThresholdLo = si.bciThresholdHi - 2560;
}
// Note that the X.org developers stated that the command overflow buffer // Note that the X.org developers stated that the command overflow buffer
// (COB) must END at a 4MB boundary which for all practical purposes means // (COB) must END at a 4MB boundary which for all practical purposes means
// the very end of the video memory. The cursor must be at the beginning // the very end of the video memory.
// of the video memory. It had been tried immediately preceding the COB,
// but the Savage MX chip screws up the cursor in that case.
si.cobOffset = (si.videoMemSize - si.cobSize) & ~0x1ffff; // align cob to 128k si.cobOffset = (si.videoMemSize - cobSize) & ~0x1ffff; // align cob to 128k
si.cursorOffset = 0; si.cursorOffset = (si.cobOffset - CURSOR_BYTES) & ~0xfff; // align to 4k boundary
si.frameBufferOffset = si.cursorOffset + CURSOR_BYTES; si.frameBufferOffset = 0;
si.maxFrameBufferSize = si.cobOffset - si.frameBufferOffset; si.maxFrameBufferSize = si.cursorOffset - si.frameBufferOffset;
TRACE("cobIndex: %d cobSize: %d cobOffset: 0x%x\n", si.cobIndex, si.cobSize, si.cobOffset); TRACE("cobSizeIndex: %d cobSize: %d cobOffset: 0x%x\n", si.cobSizeIndex, cobSize, si.cobOffset);
TRACE("cursorOffset: 0x%x frameBufferOffset: 0x%x\n", si.cursorOffset, si.frameBufferOffset); TRACE("cursorOffset: 0x%x frameBufferOffset: 0x%x\n", si.cursorOffset, si.frameBufferOffset);
// Reset graphics engine to avoid memory corruption. // Reset graphics engine to avoid memory corruption.
@@ -340,13 +295,12 @@ Savage_Init(void)
si.colorSpaces[2] = B_RGB32; si.colorSpaces[2] = B_RGB32;
si.colorSpaceCount = 3; si.colorSpaceCount = 3;
// Get info about the display capabilities (EDID). si.bDisableHdwCursor = false; // allow use of hardware cursor
si.bDisableAccelDraw = false; // allow use of accelerated drawing functions
Savage_GetEdidInfo();
// Setup the mode list. // Setup the mode list.
return CreateModeList(IsModeUsable); return CreateModeList(IsModeUsable, Savage_GetEdidInfo);
} }
@@ -379,7 +333,7 @@ Savage_SetFunctionPointers(void)
} }
gInfo.DPMSCapabilities = Savage_DPMSCapabilities; gInfo.DPMSCapabilities = Savage_DPMSCapabilities;
gInfo.DPMSMode = Savage_DPMSMode; gInfo.GetDPMSMode = Savage_GetDPMSMode;
gInfo.SetDPMSMode = Savage_SetDPMSMode; gInfo.SetDPMSMode = Savage_SetDPMSMode;
gInfo.LoadCursorImage = Savage_LoadCursorImage; gInfo.LoadCursorImage = Savage_LoadCursorImage;
+72 -314
View File
@@ -1,7 +1,8 @@
/* /*
Haiku S3 Savage driver adapted from the X.org Savage driver. Haiku S3 Savage driver adapted from the X.org Savage driver.
Copyright 1995-1997 The XFree86 Project, Inc. Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
Copyright (c) 2003-2006, X.Org Foundation
Copyright 2007-2008 Haiku, Inc. All rights reserved. Copyright 2007-2008 Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT license. Distributed under the terms of the MIT license.
@@ -21,9 +22,9 @@
struct SavageRegRec { struct SavageRegRec {
uint8 CRTC[25]; // Crtc Controller reg's uint8 CRTC[25]; // Crtc Controller reg's
uint8 SR12, SR13, SR15, SR18, SR1B, SR29; uint8 SR12, SR13, SR1B, SR29;
uint8 CR31, CR33, CR34, CR3A, CR3B, CR3C; uint8 CR33, CR34, CR3A, CR3B, CR3C;
uint8 CR40, CR42, CR43, CR45; uint8 CR42, CR43, CR45;
uint8 CR50, CR51, CR53, CR58, CR5D, CR5E; uint8 CR50, CR51, CR53, CR58, CR5D, CR5E;
uint8 CR65, CR66, CR67, CR69; uint8 CR65, CR66, CR67, CR69;
uint8 CR86, CR88; uint8 CR86, CR88;
@@ -32,15 +33,12 @@ struct SavageRegRec {
static void static void
Savage_SetGBD_Twister(const DisplayModeEx& mode) Savage_SetGBD_Twister(const DisplayModeEx& mode)
{ {
SharedInfo& si = *gInfo.sharedInfo; SharedInfo& si = *gInfo.sharedInfo;
int bci_enable; int bci_enable;
TRACE("Savage_SetGBD_Twister()\n");
if (si.chipType == S3_SAVAGE4) if (si.chipType == S3_SAVAGE4)
bci_enable = BCI_ENABLE; bci_enable = BCI_ENABLE;
else else
@@ -68,12 +66,7 @@ Savage_SetGBD_Twister(const DisplayModeEx& mode)
WriteCrtcReg(0x69, 0x80, 0x80); WriteCrtcReg(0x69, 0x80, 0x80);
WriteReg32(0x8128, 0xFFFFFFFFL); WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
WriteReg32(0x812C, 0xFFFFFFFFL);
WriteReg32(S3_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
WriteCrtcReg(0x50, 0xc1, 0xc1); // CR50, bit 7,6,0 = 111, Use GBD
// If MS1NB style linear tiling mode. // If MS1NB style linear tiling mode.
// bit MM850C[15] = 0 select NB linear tile mode. // bit MM850C[15] = 0 select NB linear tile mode.
@@ -82,45 +75,6 @@ Savage_SetGBD_Twister(const DisplayModeEx& mode)
uint32 ulTmp = ReadReg32(ADVANCED_FUNC_CTRL) | 0x8000; // use MS-s style tile mode uint32 ulTmp = ReadReg32(ADVANCED_FUNC_CTRL) | 0x8000; // use MS-s style tile mode
WriteReg32(ADVANCED_FUNC_CTRL, ulTmp); WriteReg32(ADVANCED_FUNC_CTRL, ulTmp);
// Set up Tiled Surface Registers
// Bit 25:20 - Surface width in tiles.
// Bit 29 - Y Range Flag.
// Bit 31:30 = 00, 4 bpp.
// = 01, 8 bpp.
// = 10, 16 bpp.
// = 11, 32 bpp.
// Global Bitmap Descriptor Register MM816C - twister/prosavage
// bit 24~25: tile format
// 00: linear
// 01: destination tiling format
// 10: texture tiling format
// 11: reserved
// bit 28: block write disble/enable
// 0: disable
// 1: enable
// Global Bitmap Descriptor Register MM816C - savage4
// bit 24~25: tile format
// 00: linear
// 01: reserved
// 10: 16 bpp tiles
// 11: 32 bpp tiles
// bit 28: block write disable/enable
// 0: enable
// 1: disable
// Do not enable block_write even for non-tiling modes, because
// the driver cannot determine if the memory type is the certain
// type of SGRAM for which block_write can be used.
si.GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; // linear
si.GlobalBD.bd1.HighPart.ResBWTile |= 0x10; // disable block write
// HW uses width.
si.GlobalBD.bd1.HighPart.Stride = (uint16)(mode.timing.h_display); // number of pixels per line
si.GlobalBD.bd1.HighPart.Bpp = (uint8)(mode.bpp);
si.GlobalBD.bd1.Offset = si.frameBufferOffset;
// CR88, bit 4 - Block write enabled/disabled. // CR88, bit 4 - Block write enabled/disabled.
// //
// Note: Block write must be disabled when writing to tiled // Note: Block write must be disabled when writing to tiled
@@ -128,28 +82,12 @@ Savage_SetGBD_Twister(const DisplayModeEx& mode)
// write should only be enabled for certain types of SGRAM. // write should only be enabled for certain types of SGRAM.
WriteCrtcReg(0x88, DISABLE_BLOCK_WRITE_2D, DISABLE_BLOCK_WRITE_2D); WriteCrtcReg(0x88, DISABLE_BLOCK_WRITE_2D, DISABLE_BLOCK_WRITE_2D);
// CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
// bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
// at A000:0.
WriteCrtcReg(MEMORY_CONFIG_REG, 0x00, 0x01);
// Program the GBD and SBD's.
WriteReg32(S3_GLB_BD_LOW, si.GlobalBD.bd2.LoPart);
WriteReg32(S3_GLB_BD_HIGH, si.GlobalBD.bd2.HiPart | bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
WriteReg32(S3_PRI_BD_LOW, si.GlobalBD.bd2.LoPart);
WriteReg32(S3_PRI_BD_HIGH, si.GlobalBD.bd2.HiPart);
} }
static void static void
Savage_SetGBD_3D(const DisplayModeEx& mode) Savage_SetGBD_3D(const DisplayModeEx& mode)
{ {
TRACE("Savage_SetGBD_3D()\n");
SharedInfo& si = *gInfo.sharedInfo;
int bci_enable = BCI_ENABLE; int bci_enable = BCI_ENABLE;
// MM81C0 and 81C4 are used to control primary stream. // MM81C0 and 81C4 are used to control primary stream.
@@ -174,12 +112,7 @@ Savage_SetGBD_3D(const DisplayModeEx& mode)
WriteCrtcReg(0x69, 0x80, 0x80); WriteCrtcReg(0x69, 0x80, 0x80);
WriteReg32(0x8128, 0xFFFFFFFFL); WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
WriteReg32(0x812C, 0xFFFFFFFFL);
WriteReg32(S3_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
WriteCrtcReg(0x50, 0xc1, 0xc1); // CR50, bit 7,6,0 = 111, Use GBD
// If MS1NB style linear tiling mode. // If MS1NB style linear tiling mode.
// bit MM850C[15] = 0 select NB linear tile mode. // bit MM850C[15] = 0 select NB linear tile mode.
@@ -188,36 +121,6 @@ Savage_SetGBD_3D(const DisplayModeEx& mode)
uint32 ulTmp = ReadReg32(ADVANCED_FUNC_CTRL) | 0x8000; // use MS-s style tile mode uint32 ulTmp = ReadReg32(ADVANCED_FUNC_CTRL) | 0x8000; // use MS-s style tile mode
WriteReg32(ADVANCED_FUNC_CTRL, ulTmp); WriteReg32(ADVANCED_FUNC_CTRL, ulTmp);
// Tiled Surface 0 Registers MM48C40:
// bit 0~23: tile surface 0 frame buffer offset
// bit 24~29:tile surface 0 width
// bit 30~31:tile surface 0 bits/pixel
// 00: reserved
// 01, 8 bits
// 10, 16 Bits.
// 11, 32 Bits.
// Global Bitmap Descriptor Register MM816C
// bit 24~25: tile format
// 00: linear
// 01: reserved
// 10: 16 bpp tiles
// 11: 32 bpp tiles
// bit 28: block write disable/enable
// 0: enable
// 1: disable
// Do not enable block_write even for non-tiling modes, because
// the driver cannot determine if the memory type is the certain
// type of SGRAM for which block_write can be used.
si.GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; // linear
si.GlobalBD.bd1.HighPart.ResBWTile |= 0x10; // disable block write
// HW uses width.
si.GlobalBD.bd1.HighPart.Stride = (uint16)(mode.timing.h_display); // number of pixels per line
si.GlobalBD.bd1.HighPart.Bpp = (uint8)(mode.bpp);
si.GlobalBD.bd1.Offset = si.frameBufferOffset;
// CR88, bit 4 - Block write enabled/disabled. // CR88, bit 4 - Block write enabled/disabled.
// //
// Note: Block write must be disabled when writing to tiled // Note: Block write must be disabled when writing to tiled
@@ -225,26 +128,12 @@ Savage_SetGBD_3D(const DisplayModeEx& mode)
// write should only be enabled for certain types of SGRAM. // write should only be enabled for certain types of SGRAM.
WriteCrtcReg(0x88, DISABLE_BLOCK_WRITE_2D, DISABLE_BLOCK_WRITE_2D); WriteCrtcReg(0x88, DISABLE_BLOCK_WRITE_2D, DISABLE_BLOCK_WRITE_2D);
// CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
// bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
// at A000:0.
WriteCrtcReg(MEMORY_CONFIG_REG, 0x00, 0x01);
// Program the GBD and SBD's.
WriteReg32(S3_GLB_BD_LOW, si.GlobalBD.bd2.LoPart);
WriteReg32(S3_GLB_BD_HIGH, si.GlobalBD.bd2.HiPart | bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
WriteReg32(S3_PRI_BD_LOW, si.GlobalBD.bd2.LoPart);
WriteReg32(S3_PRI_BD_HIGH, si.GlobalBD.bd2.HiPart);
} }
static void static void
Savage_SetGBD_MX(const DisplayModeEx& mode) Savage_SetGBD_MX(const DisplayModeEx& mode)
{ {
TRACE("Savage_SetGBD_MX()\n");
SharedInfo& si = *gInfo.sharedInfo; SharedInfo& si = *gInfo.sharedInfo;
int bci_enable = BCI_ENABLE; int bci_enable = BCI_ENABLE;
@@ -285,12 +174,7 @@ Savage_SetGBD_MX(const DisplayModeEx& mode)
(((mode.bytesPerRow * 2) << 16) & 0x3FFF0000) | (((mode.bytesPerRow * 2) << 16) & 0x3FFF0000) |
(mode.bytesPerRow & 0x00003fff)); (mode.bytesPerRow & 0x00003fff));
WriteReg32(0x8128, 0xFFFFFFFFL); WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
WriteReg32(0x812C, 0xFFFFFFFFL);
WriteReg32(S3_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
WriteCrtcReg(0x50, 0xc1, 0xc1); // CR50, bit 7,6,0 = 111, Use GBD
// CR78, bit 3 - Block write enabled(1)/disabled(0). // CR78, bit 3 - Block write enabled(1)/disabled(0).
// bit 2 - Block write cycle time(0:2 cycles,1: 1 cycle) // bit 2 - Block write cycle time(0:2 cycles,1: 1 cycle)
@@ -299,60 +183,12 @@ Savage_SetGBD_MX(const DisplayModeEx& mode)
// write should only be enabled for certain types of SGRAM. // write should only be enabled for certain types of SGRAM.
WriteCrtcReg(0x78, 0xfb, 0xfb); WriteCrtcReg(0x78, 0xfb, 0xfb);
// Tiled Surface 0 Registers MM48C40:
// bit 0~23: tile surface 0 frame buffer offset
// bit 24~29:tile surface 0 width
// bit 30~31:tile surface 0 bits/pixel
// 00: reserved
// 01, 8 bits
// 10, 16 Bits.
// 11, 32 Bits.
// Global Bitmap Descriptor Register MM816C
// bit 24~25: tile format
// 00: linear
// 01: reserved
// 10: 16 bit
// 11: 32 bit
// bit 28: block write disble/enable
// 0: enable
// 1: disable
// Do not enable block_write even for non-tiling modes, because
// the driver cannot determine if the memory type is the certain
// type of SGRAM for which block_write can be used.
si.GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; // linear
si.GlobalBD.bd1.HighPart.ResBWTile |= 0x10; // disable block write
// HW uses width.
si.GlobalBD.bd1.HighPart.Stride = (uint16)(mode.timing.h_display); // number of pixels per line
si.GlobalBD.bd1.HighPart.Bpp = (uint8)(mode.bpp);
si.GlobalBD.bd1.Offset = si.frameBufferOffset;
// CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
// bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
// at A000:0.
WriteCrtcReg(MEMORY_CONFIG_REG, 0x04, 0x05); // CR31
// Program the GBD and SBD's.
WriteReg32(S3_GLB_BD_LOW, si.GlobalBD.bd2.LoPart );
// 8: bci enable.
WriteReg32(S3_GLB_BD_HIGH, (si.GlobalBD.bd2.HiPart
| bci_enable | S3_LITTLE_ENDIAN | S3_BD64));
WriteReg32(S3_PRI_BD_LOW, si.GlobalBD.bd2.LoPart);
WriteReg32(S3_PRI_BD_HIGH, si.GlobalBD.bd2.HiPart);
WriteReg32(S3_SEC_BD_LOW, si.GlobalBD.bd2.LoPart);
WriteReg32(S3_SEC_BD_HIGH, si.GlobalBD.bd2.HiPart);
} }
static void static void
Savage_SetGBD_Super(const DisplayModeEx& mode) Savage_SetGBD_Super(const DisplayModeEx& mode)
{ {
TRACE("Savage_SetGBD_Super()\n");
SharedInfo& si = *gInfo.sharedInfo; SharedInfo& si = *gInfo.sharedInfo;
int bci_enable = BCI_ENABLE_TWISTER; int bci_enable = BCI_ENABLE_TWISTER;
@@ -395,47 +231,14 @@ Savage_SetGBD_Super(const DisplayModeEx& mode)
WriteReg32(PRI_STREAM2_FBUF_ADDR0, (si.frameBufferOffset & 0xfffffffc) | 0x80000000); WriteReg32(PRI_STREAM2_FBUF_ADDR0, (si.frameBufferOffset & 0xfffffffc) | 0x80000000);
WriteReg32(PRI_STREAM2_FBUF_ADDR1, si.frameBufferOffset & 0xfffffffc); WriteReg32(PRI_STREAM2_FBUF_ADDR1, si.frameBufferOffset & 0xfffffffc);
WriteReg32(0x8128, 0xFFFFFFFFL);
WriteReg32(0x812C, 0xFFFFFFFFL);
// Bit 28:block write disable. // Bit 28:block write disable.
WriteReg32(S3_GLB_BD_HIGH, bci_enable | S3_BD64 | 0x10000000); WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_BD64 | 0x10000000);
WriteCrtcReg(0x50, 0xc1, 0xc1); // CR50, bit 7,6,0 = 111, Use GBD
// Do not enable block_write even for non-tiling modes, because
// the driver cannot determine if the memory type is the certain
// type of SGRAM for which block_write can be used.
si.GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; // linear
si.GlobalBD.bd1.HighPart.ResBWTile |= 0x10; // disable block write
// HW uses width.
si.GlobalBD.bd1.HighPart.Stride = (uint16)(mode.timing.h_display); // number of pixels per line
si.GlobalBD.bd1.HighPart.Bpp = (uint8)(mode.bpp);
si.GlobalBD.bd1.Offset = si.frameBufferOffset;
// CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
// bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
// at A000:0.
WriteCrtcReg(MEMORY_CONFIG_REG, 0x00, 0x01);
// Program the GBD and SBDs.
WriteReg32(S3_GLB_BD_LOW, si.GlobalBD.bd2.LoPart );
WriteReg32(S3_GLB_BD_HIGH, (si.GlobalBD.bd2.HiPart
| bci_enable | S3_LITTLE_ENDIAN | S3_BD64));
WriteReg32(S3_PRI_BD_LOW, si.GlobalBD.bd2.LoPart);
WriteReg32(S3_PRI_BD_HIGH, si.GlobalBD.bd2.HiPart);
WriteReg32(S3_SEC_BD_LOW, si.GlobalBD.bd2.LoPart);
WriteReg32(S3_SEC_BD_HIGH, si.GlobalBD.bd2.HiPart);
} }
static void static void
Savage_SetGBD_2000(const DisplayModeEx& mode) Savage_SetGBD_2000(const DisplayModeEx& mode)
{ {
TRACE("Savage_SetGBD_2000()\n");
SharedInfo& si = *gInfo.sharedInfo; SharedInfo& si = *gInfo.sharedInfo;
int bci_enable = BCI_ENABLE_TWISTER; int bci_enable = BCI_ENABLE_TWISTER;
@@ -463,47 +266,18 @@ Savage_SetGBD_2000(const DisplayModeEx& mode)
WriteCrtcReg(0x67, 0x08, 0x08); WriteCrtcReg(0x67, 0x08, 0x08);
WriteReg32(0x8128, 0xFFFFFFFFL);
WriteReg32(0x812C, 0xFFFFFFFFL);
// Bit 28:block write disable. // Bit 28:block write disable.
WriteReg32(S3_GLB_BD_HIGH, bci_enable | S3_BD64 | 0x10000000); WriteReg32(S3_GLOBAL_GBD_REG, bci_enable | S3_BD64 | 0x10000000);
WriteCrtcReg(0x50, 0xc1, 0xc1); // CR50, bit 7,6,0 = 111, Use GBD
WriteCrtcReg(0x73, 0x00, 0x20); // CR73 bit 5 = 0 block write disable WriteCrtcReg(0x73, 0x00, 0x20); // CR73 bit 5 = 0 block write disable
// Do not enable block_write even for non-tiling modes, because
// the driver cannot determine if the memory type is the certain
// type of SGRAM for which block_write can be used.
si.GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR; // linear
si.GlobalBD.bd1.HighPart.ResBWTile |= 0x10; // disable block write
// HW uses width.
si.GlobalBD.bd1.HighPart.Stride = (uint16)(mode.timing.h_display); // number of pixels per line
si.GlobalBD.bd1.HighPart.Bpp = (uint8)(mode.bpp);
si.GlobalBD.bd1.Offset = si.frameBufferOffset;
// CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
// bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
// at A000:0.
WriteCrtcReg(MEMORY_CONFIG_REG, 0x00, 0x01);
// Program the GBD and SBDs.
WriteReg32(S3_GLB_BD_LOW, si.GlobalBD.bd2.LoPart );
WriteReg32(S3_GLB_BD_HIGH, (si.GlobalBD.bd2.HiPart
| bci_enable | S3_LITTLE_ENDIAN | S3_BD64));
WriteReg32(S3_PRI_BD_LOW, si.GlobalBD.bd2.LoPart);
WriteReg32(S3_PRI_BD_HIGH, si.GlobalBD.bd2.HiPart);
WriteReg32(S3_SEC_BD_LOW, si.GlobalBD.bd2.LoPart);
WriteReg32(S3_SEC_BD_HIGH, si.GlobalBD.bd2.HiPart);
} }
static void static void
Savage_SetGBD(const DisplayModeEx& mode) Savage_SetGBD(const DisplayModeEx& mode)
{ {
TRACE("Savage_SetGBD()\n"); SharedInfo& si = *gInfo.sharedInfo;
VerticalRetraceWait(); VerticalRetraceWait();
@@ -531,19 +305,27 @@ Savage_SetGBD(const DisplayModeEx& mode)
Savage_SetGBD_2000(mode); Savage_SetGBD_2000(mode);
break; break;
} }
WriteCrtcReg(0x50, 0xc1, 0xc1); // CR50, bit 7,6,0 = 111, Use GBD
// Set up the Global Bitmap Descriptor used for BCI.
// Do not enable block_write because we can't determine if the memory
// type is a certain type of SGRAM for which block write can be used.
// bit 24~25: tile format, 00 = linear
// bit 28: block write disble/enable, 0 = disable, 1 = enable
si.globalBitmapDesc = mode.timing.h_display | (mode.bpp << 16)
| TILE_FORMAT_LINEAR | BCI_BD_BW_DISABLE | S3_BD64; // disable block write
} }
static void static void
Savage_Initialize2DEngine(const DisplayModeEx& mode) Savage_Initialize2DEngine(const DisplayModeEx& mode)
{ {
TRACE("Savage_Initialize2DEngine()\n");
SharedInfo& si = *gInfo.sharedInfo; SharedInfo& si = *gInfo.sharedInfo;
uint32 thresholds;
WriteCrtcReg(0x40, 0x01); WriteCrtcReg(0x40, 0x01); // enable graphics engine
WriteCrtcReg(0x31, 0x0c); WriteCrtcReg(0x31, 0x0c); // turn on 16-bit register access
// Setup plane masks. // Setup plane masks.
WriteReg32(0x8128, ~0); // enable all write planes WriteReg32(0x8128, ~0); // enable all write planes
@@ -555,14 +337,16 @@ Savage_Initialize2DEngine(const DisplayModeEx& mode)
case S3_SAVAGE_3D: case S3_SAVAGE_3D:
case S3_SAVAGE_MX: case S3_SAVAGE_MX:
// Disable BCI. WriteReg32(0x48C18, ReadReg32(0x48C18) & 0x3FF0); // Disable BCI
WriteReg32(0x48C18, ReadReg32(0x48C18) & 0x3FF0);
// Setup BCI command overflow buffer. // Setup BCI command overflow buffer. 0x48c14
WriteReg32(0x48C14, (si.cobOffset >> 11) | (si.cobIndex << 29)); // tim // Bits 0-11 = Bits 22-11 of the Command Buffer Offset.
// Bits 12-28 = Total number of entries in the command buffer(Read only).
// Bits 29-31 = COB size index, 111 = 32K entries or 128K bytes
WriteReg32(0x48C14, (si.cobOffset >> 11) | (si.cobSizeIndex << 29));
// Program shadow status update. // Program shadow status update.
thresholds = ((si.bciThresholdLo & 0xffff) << 16) | WriteReg32(0x48C10, 0x78207220);
(si.bciThresholdHi & 0xffff);
WriteReg32(0x48C10, thresholds);
WriteReg32(0x48C0C, 0); WriteReg32(0x48C0C, 0);
// Enable BCI and command overflow buffer. // Enable BCI and command overflow buffer.
@@ -575,23 +359,14 @@ Savage_Initialize2DEngine(const DisplayModeEx& mode)
case S3_PROSAVAGE_DDR: case S3_PROSAVAGE_DDR:
case S3_SUPERSAVAGE: case S3_SUPERSAVAGE:
// Disable BCI. // Some Savage4 and ProSavage chips have coherency problems with
WriteReg32(0x48C18, ReadReg32(0x48C18) & 0x3FF0); // respect to the Command Overflow Buffer (COB); thus, do not
// enable the COB.
if ( ! si.bDisableCOB) {
// Setup BCI command overflow buffer.
WriteReg32(0x48C14, (si.cobOffset >> 11) | (si.cobIndex << 29));
}
// Program shadow status update; AGD: what should this be?
thresholds = ((si.bciThresholdLo & 0x1fffe0) << 11)
| ((si.bciThresholdHi & 0x1fffe0) >> 5);
WriteReg32(0x48C10, thresholds);
WriteReg32(0x48C18, ReadReg32(0x48C18) & 0x3FF0); // Disable BCI
WriteReg32(0x48C10, 0x00700040);
WriteReg32(0x48C0C, 0); WriteReg32(0x48C0C, 0);
if (si.bDisableCOB) WriteReg32(0x48C18, ReadReg32(0x48C18) | 0x08); // enable BCI without COB
WriteReg32(0x48C18, ReadReg32(0x48C18) | 0x08); // enable BCI without COB
else
WriteReg32(0x48C18, ReadReg32(0x48C18) | 0x0C); // enable BCI with COB
break; break;
@@ -600,23 +375,17 @@ Savage_Initialize2DEngine(const DisplayModeEx& mode)
// Disable BCI. // Disable BCI.
WriteReg32(0x48C18, 0); WriteReg32(0x48C18, 0);
// Setup BCI command overflow buffer. // Setup BCI command overflow buffer.
WriteReg32(0x48C18, (si.cobOffset >> 7) | (si.cobIndex)); WriteReg32(0x48C18, (si.cobOffset >> 7) | (si.cobSizeIndex));
// Disable shadow status update. // Disable shadow status update.
WriteReg32(0x48A30, 0); WriteReg32(0x48A30, 0);
// Enable BCI and command overflow buffer. // Enable BCI and command overflow buffer.
WriteReg32(0x48C18, ReadReg32(0x48C18) | 0x00280000 ); WriteReg32(0x48C18, ReadReg32(0x48C18) | 0x00280000);
break; break;
} }
// Use and set global bitmap descriptor. // Use and set global bitmap descriptor.
// For reasons I do not fully understand yet, on the Savage4, the
// write to the GBD register, MM816C, does not "take" at this time.
// Only the low-order byte is acknowledged, resulting in an incorrect
// stride. Writing the register later, after the mode switch, works
// correctly. This needs to get resolved.
Savage_SetGBD(mode); Savage_SetGBD(mode);
} }
@@ -624,8 +393,6 @@ Savage_Initialize2DEngine(const DisplayModeEx& mode)
static void static void
Savage_GEReset(const DisplayModeEx& mode) Savage_GEReset(const DisplayModeEx& mode)
{ {
TRACE("Savage_GEReset() begin\n");
gInfo.WaitIdleEmpty(); gInfo.WaitIdleEmpty();
snooze(10000); snooze(10000);
@@ -665,7 +432,7 @@ Savage_GEReset(const DisplayModeEx& mode)
break; break;
snooze(10000); snooze(10000);
TRACE("Restarting S3 graphics engine reset %2d ...\n", r); TRACE("Savage_GEReset(), restarting S3 graphics engine reset %2d ...\n", r);
} }
// At this point, the FIFO is empty and the engine is idle. // At this point, the FIFO is empty and the engine is idle.
@@ -678,8 +445,6 @@ Savage_GEReset(const DisplayModeEx& mode)
WriteReg32(MONO_PAT_1, ~0); WriteReg32(MONO_PAT_1, ~0);
Savage_SetGBD(mode); Savage_SetGBD(mode);
TRACE("Savage_GEReset() end\n");
} }
@@ -739,7 +504,7 @@ Savage_CalcClock(long freq, int min_m,
static void static void
Savage_WriteMode(const DisplayModeEx& mode, const SavageRegRec& regRec) Savage_WriteMode(const DisplayModeEx& mode, const SavageRegRec& regRec)
{ {
TRACE("Savage_WriteMode() enter\n"); TRACE("Savage_WriteMode() begin\n");
SharedInfo& si = *gInfo.sharedInfo; SharedInfo& si = *gInfo.sharedInfo;
@@ -756,7 +521,7 @@ Savage_WriteMode(const DisplayModeEx& mode, const SavageRegRec& regRec)
if (ReadCrtcReg(0x66) & 0x01) { if (ReadCrtcReg(0x66) & 0x01) {
Savage_GEReset(mode); // reset GE to make sure nothing is going on Savage_GEReset(mode); // reset GE to make sure nothing is going on
} }
WriteCrtcReg(0x67, regRec.CR67 & ~0x0e); // no STREAMS yet old and new WriteCrtcReg(0x67, regRec.CR67 & ~0x0e); // no STREAMS yet old and new
// Set register SR19 to zero so that the ProSavage chips will start up // Set register SR19 to zero so that the ProSavage chips will start up
@@ -769,7 +534,7 @@ Savage_WriteMode(const DisplayModeEx& mode, const SavageRegRec& regRec)
// not cleared, it will startup only if booting under BeOS using the // not cleared, it will startup only if booting under BeOS using the
// default boot screen or the boot screen resolution matches the resolution // default boot screen or the boot screen resolution matches the resolution
// of the mode currently being set. // of the mode currently being set.
if (si.chipType == S3_SAVAGE_MX) if (si.chipType == S3_SAVAGE_MX)
WriteSeqReg(0x30, 0x00, 0x08); WriteSeqReg(0x30, 0x00, 0x08);
@@ -777,14 +542,20 @@ Savage_WriteMode(const DisplayModeEx& mode, const SavageRegRec& regRec)
WriteCrtcReg(0x66, regRec.CR66); WriteCrtcReg(0x66, regRec.CR66);
WriteCrtcReg(0x3a, regRec.CR3A); WriteCrtcReg(0x3a, regRec.CR3A);
WriteCrtcReg(0x31, regRec.CR31);
WriteCrtcReg(0x58, regRec.CR58); WriteCrtcReg(0x58, regRec.CR58);
WriteCrtcReg(0x53, regRec.CR53 & 0x7f); WriteCrtcReg(0x53, regRec.CR53 & 0x7f);
// Set DCLK registers. // If Savage IX/MX or SuperSavage, set SR54 & SR56 to 0x10 so that when
// resolutions are set where the width and/or height is less than the
// native resolution of the attached LCD display, the chip will not expand
// the display to fill the screen. That is, if a resolution is set to
// 640x480, it will use only 640x480 pixels for the display. When the chip
// expands the display, text is much less readable.
WriteSeqReg(0x29, regRec.SR29); if (S3_SAVAGE_MOBILE_SERIES(si.chipType)) {
WriteSeqReg(0x15, regRec.SR15); WriteSeqReg(0x54, 0x10);
WriteSeqReg(0x56, 0x10);
}
// Set the standard CRTC vga regs. // Set the standard CRTC vga regs.
@@ -818,7 +589,6 @@ Savage_WriteMode(const DisplayModeEx& mode, const SavageRegRec& regRec)
// Other mode timing and extended regs. // Other mode timing and extended regs.
WriteCrtcReg(0x34, regRec.CR34); WriteCrtcReg(0x34, regRec.CR34);
WriteCrtcReg(0x40, regRec.CR40);
WriteCrtcReg(0x42, regRec.CR42); WriteCrtcReg(0x42, regRec.CR42);
WriteCrtcReg(0x45, regRec.CR45); WriteCrtcReg(0x45, regRec.CR45);
WriteCrtcReg(0x50, regRec.CR50); WriteCrtcReg(0x50, regRec.CR50);
@@ -837,22 +607,21 @@ Savage_WriteMode(const DisplayModeEx& mode, const SavageRegRec& regRec)
if (si.chipType == S3_SAVAGE4) if (si.chipType == S3_SAVAGE4)
WriteCrtcReg(0xb0, regRec.CRB0); WriteCrtcReg(0xb0, regRec.CRB0);
// Set extended seq regs for dclk.
WriteSeqReg(0x12, regRec.SR12);
WriteSeqReg(0x13, regRec.SR13);
WriteSeqReg(0x29, regRec.SR29);
WriteSeqReg(0x18, regRec.SR18);
WriteSeqReg(0x1b, regRec.SR1B); WriteSeqReg(0x1b, regRec.SR1B);
// Load new m, n pll values for dclk & mclk. if ( ! (S3_SAVAGE_MOBILE_SERIES(si.chipType) && si.displayType == MT_LCD)) {
temp = ReadSeqReg(0x15) & ~0x21; // Set extended seq regs for dclk.
WriteSeqReg(0x12, regRec.SR12);
WriteSeqReg(0x13, regRec.SR13);
WriteSeqReg(0x29, regRec.SR29);
WriteSeqReg(0x15, temp | 0x03); // Load new m, n pll values for dclk & mclk.
WriteSeqReg(0x15, temp | 0x23); temp = ReadSeqReg(0x15) & ~0x20;
WriteSeqReg(0x15, temp | 0x03); WriteSeqReg(0x15, temp);
WriteSeqReg(0x15, regRec.SR15); WriteSeqReg(0x15, temp | 0x20);
snooze( 100 ); WriteSeqReg(0x15, temp);
snooze(100);
}
// Now write out cr67 in full, possibly starting STREAMS. // Now write out cr67 in full, possibly starting STREAMS.
VerticalRetraceWait(); VerticalRetraceWait();
@@ -874,7 +643,7 @@ Savage_WriteMode(const DisplayModeEx& mode, const SavageRegRec& regRec)
Savage_SetGBD(mode); Savage_SetGBD(mode);
TRACE("Savage_WriteMode() end\n"); TRACE("Savage_WriteMode() done\n");
return; return;
} }
@@ -883,7 +652,7 @@ Savage_WriteMode(const DisplayModeEx& mode, const SavageRegRec& regRec)
static bool static bool
Savage_ModeInit(const DisplayModeEx& mode) Savage_ModeInit(const DisplayModeEx& mode)
{ {
TRACE("Savage_ModeInit(%dx%d, %dHz)\n", TRACE("Savage_ModeInit(%dx%d, %d kHz)\n",
mode.timing.h_display, mode.timing.v_display, mode.timing.pixel_clock); mode.timing.h_display, mode.timing.v_display, mode.timing.pixel_clock);
SharedInfo& si = *gInfo.sharedInfo; SharedInfo& si = *gInfo.sharedInfo;
@@ -896,7 +665,7 @@ Savage_ModeInit(const DisplayModeEx& mode)
InitCrtcTimingValues(mode, horizScaleFactor, regRec.CRTC, InitCrtcTimingValues(mode, horizScaleFactor, regRec.CRTC,
regRec.CR3B, regRec.CR3C, regRec.CR5D, regRec.CR5E); regRec.CR3B, regRec.CR3C, regRec.CR5D, regRec.CR5E);
regRec.CRTC[23] = 0xEB; regRec.CRTC[0x17] = 0xEB;
int dclk = mode.timing.pixel_clock; int dclk = mode.timing.pixel_clock;
regRec.CR67 = 0x00; regRec.CR67 = 0x00;
@@ -930,25 +699,14 @@ Savage_ModeInit(const DisplayModeEx& mode)
break; break;
} }
// Use traditional register-crunching to set mode.
regRec.CR3A = (ReadCrtcReg(0x3a) & 0x7f) | 0x15; regRec.CR3A = (ReadCrtcReg(0x3a) & 0x7f) | 0x15;
regRec.CR53 = 0x00; regRec.CR53 = 0x00;
regRec.CR31 = 0x8c;
regRec.CR66 = 0x89; regRec.CR66 = 0x89;
regRec.CR58 = (ReadCrtcReg(0x58) & 0x80) | 0x13; regRec.CR58 = (ReadCrtcReg(0x58) & 0x80) | 0x13;
if (si.chipType == S3_SAVAGE2000)
regRec.SR15 = 0x02;
else
regRec.SR15 = 0x83;
regRec.SR18 = 0x00;
regRec.SR1B = ReadSeqReg(0x1b) | 0x10; // enable 8-bit Color Lookup Table regRec.SR1B = ReadSeqReg(0x1b) | 0x10; // enable 8-bit Color Lookup Table
regRec.CR43 = regRec.CR45 = regRec.CR65 = 0x00; regRec.CR43 = regRec.CR45 = regRec.CR65 = 0x00;
regRec.CR40 = ReadCrtcReg(0x40) & ~0x01;
unsigned int m, n, r; unsigned int m, n, r;
Savage_CalcClock(dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r); Savage_CalcClock(dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r);
@@ -997,7 +755,6 @@ Savage_ModeInit(const DisplayModeEx& mode)
else else
regRec.CR33 = 0x08; regRec.CR33 = 0x08;
regRec.CR67 |= 1;
regRec.CR69 = 0; regRec.CR69 = 0;
regRec.CR86 = ReadCrtcReg(0x86) | 0x08; regRec.CR86 = ReadCrtcReg(0x86) | 0x08;
regRec.CR88 = ReadCrtcReg(0x88) | DISABLE_BLOCK_WRITE_2D; regRec.CR88 = ReadCrtcReg(0x88) | DISABLE_BLOCK_WRITE_2D;
@@ -1027,6 +784,7 @@ Savage_SetDisplayMode(const DisplayModeEx& mode)
Savage_AdjustFrame(mode); Savage_AdjustFrame(mode);
WriteSeqReg(0x01, 0x00, 0x20); // unblank the screen WriteSeqReg(0x01, 0x00, 0x20); // unblank the screen
return true; return true;
} }
+2 -2
View File
@@ -26,7 +26,7 @@ Trio64_DPMSCapabilities(void)
uint32 uint32
Trio64_DPMSMode(void) Trio64_GetDPMSMode(void)
{ {
// Return the current DPMS mode. // Return the current DPMS mode.
@@ -53,7 +53,7 @@ Trio64_DPMSMode(void)
TRACE("Unknown DPMS mode, reg sr0D: 0x%X\n", ReadSeqReg(0x0d)); TRACE("Unknown DPMS mode, reg sr0D: 0x%X\n", ReadSeqReg(0x0d));
} }
TRACE("Trio64_DPMSMode() mode: %d\n", mode); TRACE("Trio64_GetDPMSMode() mode: %d\n", mode);
return mode; return mode;
} }
+5 -2
View File
@@ -136,9 +136,12 @@ Trio64_Init(void)
si.colorSpaces[1] = B_RGB16; si.colorSpaces[1] = B_RGB16;
si.colorSpaceCount = 2; si.colorSpaceCount = 2;
si.bDisableHdwCursor = false; // allow use of hardware cursor
si.bDisableAccelDraw = false; // allow use of accelerated drawing functions
// Setup the mode list. // Setup the mode list.
return CreateModeList(Trio64_IsModeUsable); return CreateModeList(Trio64_IsModeUsable, NULL);
} }
@@ -152,7 +155,7 @@ Trio64_SetFunctionPointers(void)
gInfo.WaitIdleEmpty = WaitIdle; gInfo.WaitIdleEmpty = WaitIdle;
gInfo.DPMSCapabilities = Trio64_DPMSCapabilities; gInfo.DPMSCapabilities = Trio64_DPMSCapabilities;
gInfo.DPMSMode = Trio64_DPMSMode; gInfo.GetDPMSMode = Trio64_GetDPMSMode;
gInfo.SetDPMSMode = Trio64_SetDPMSMode; gInfo.SetDPMSMode = Trio64_SetDPMSMode;
gInfo.LoadCursorImage = Trio64_LoadCursorImage; gInfo.LoadCursorImage = Trio64_LoadCursorImage;
+3 -16
View File
@@ -130,7 +130,7 @@ Trio64_ModeInit(const DisplayModeEx& mode)
break; break;
} }
bool bEnableAccelFuncs = true; bool bDisableAccelFuncs = false;
switch (mode.timing.h_display) { switch (mode.timing.h_display) {
case 640: case 640:
@@ -152,7 +152,7 @@ Trio64_ModeInit(const DisplayModeEx& mode)
cr50 |= 0x81; cr50 |= 0x81;
break; break;
default: default:
bEnableAccelFuncs = false; // use app_server default accel functions bDisableAccelFuncs = true; // use app_server default accel functions
break; break;
} }
@@ -167,20 +167,7 @@ Trio64_ModeInit(const DisplayModeEx& mode)
// only with the display widths defined in the above switch statement. For // only with the display widths defined in the above switch statement. For
// the other widths, the default functions in the app_server will be used. // the other widths, the default functions in the app_server will be used.
if (bEnableAccelFuncs) si.bDisableAccelDraw = bDisableAccelFuncs;
{
gInfo.FillRectangle = Trio64_FillRectangle;
gInfo.FillSpan = Trio64_FillSpan;
gInfo.InvertRectangle = Trio64_InvertRectangle;
gInfo.ScreenToScreenBlit = Trio64_ScreenToScreenBlit;
}
else
{
gInfo.FillRectangle = NULL;
gInfo.FillSpan = NULL;
gInfo.InvertRectangle = NULL;
gInfo.ScreenToScreenBlit = NULL;
}
// Set the standard CRTC vga regs. // Set the standard CRTC vga regs.
+2 -2
View File
@@ -26,7 +26,7 @@ Virge_DPMSCapabilities(void)
uint32 uint32
Virge_DPMSMode(void) Virge_GetDPMSMode(void)
{ {
// Return the current DPMS mode. // Return the current DPMS mode.
@@ -53,7 +53,7 @@ Virge_DPMSMode(void)
TRACE("Unknown DPMS mode, reg sr0D: 0x%X\n", ReadSeqReg(0x0d)); TRACE("Unknown DPMS mode, reg sr0D: 0x%X\n", ReadSeqReg(0x0d));
} }
TRACE("Virge_DPMSMode() mode: %d\n", mode); TRACE("Virge_GetDPMSMode() mode: %d\n", mode);
return mode; return mode;
} }
+5 -13
View File
@@ -80,13 +80,13 @@ SetI2CSignals(void* cookie, int _clock, int data)
bool bool
Virge_GetEdidInfo(void) Virge_GetEdidInfo(edid1_info& edidInfo)
{ {
// Get the EDID info and return true if successful. // Get the EDID info and return true if successful.
SharedInfo& si = *gInfo.sharedInfo; SharedInfo& si = *gInfo.sharedInfo;
si.bHaveEDID = false; bool bResult = false;
if (si.chipType == S3_TRIO_3D_2X) { if (si.chipType == S3_TRIO_3D_2X) {
uint32 DDCPort = 0xAA; uint32 DDCPort = 0xAA;
@@ -100,7 +100,7 @@ Virge_GetEdidInfo(void)
uint8 tmp = ReadCrtcReg(DDCPort); uint8 tmp = ReadCrtcReg(DDCPort);
WriteCrtcReg(DDCPort, tmp | 0x13); WriteCrtcReg(DDCPort, tmp | 0x13);
si.bHaveEDID = (ddc2_read_edid1(&bus, &(si.edidInfo), NULL, NULL) == B_OK); bResult = (ddc2_read_edid1(&bus, &edidInfo, NULL, NULL) == B_OK);
WriteCrtcReg(DDCPort, tmp); WriteCrtcReg(DDCPort, tmp);
} else { } else {
@@ -113,18 +113,10 @@ Virge_GetEdidInfo(void)
uint8 tmp = ReadReg8(DDC_REG); uint8 tmp = ReadReg8(DDC_REG);
WriteReg8(DDC_REG, tmp | 0x13); WriteReg8(DDC_REG, tmp | 0x13);
si.bHaveEDID = (ddc2_read_edid1(&bus, &(si.edidInfo), NULL, NULL) == B_OK); bResult = (ddc2_read_edid1(&bus, &edidInfo, NULL, NULL) == B_OK);
WriteReg8(DDC_REG, tmp); WriteReg8(DDC_REG, tmp);
} }
if (si.bHaveEDID) { return bResult;
#ifdef ENABLE_DEBUG_TRACE
edid_dump(&(si.edidInfo));
#endif
} else {
TRACE("Virge_GetEdidInfo() failed!\n");
}
return si.bHaveEDID;
} }
+4 -5
View File
@@ -226,13 +226,12 @@ Virge_Init(void)
si.colorSpaces[1] = B_RGB16; si.colorSpaces[1] = B_RGB16;
si.colorSpaceCount = 2; si.colorSpaceCount = 2;
// Get info about the display capabilities (EDID). si.bDisableHdwCursor = false; // allow use of hardware cursor
si.bDisableAccelDraw = false; // allow use of accelerated drawing functions
Virge_GetEdidInfo();
// Setup the mode list. // Setup the mode list.
return CreateModeList(IsModeUsable); return CreateModeList(IsModeUsable, Virge_GetEdidInfo);
} }
@@ -251,7 +250,7 @@ Virge_SetFunctionPointers(void)
gInfo.WaitIdleEmpty = VirgeWaitIdleEmpty; gInfo.WaitIdleEmpty = VirgeWaitIdleEmpty;
gInfo.DPMSCapabilities = Virge_DPMSCapabilities; gInfo.DPMSCapabilities = Virge_DPMSCapabilities;
gInfo.DPMSMode = Virge_DPMSMode; gInfo.GetDPMSMode = Virge_GetDPMSMode;
gInfo.SetDPMSMode = Virge_SetDPMSMode; gInfo.SetDPMSMode = Virge_SetDPMSMode;
gInfo.LoadCursorImage = Virge_LoadCursorImage; gInfo.LoadCursorImage = Virge_LoadCursorImage;
+8 -1
View File
@@ -623,7 +623,7 @@ Virge_ModeInit(const DisplayModeEx& mode)
} }
int width = mode.bytesPerRow >> 3; int width = mode.bytesPerRow >> 3;
regRec.CRTC[19] = 0xFF & width; regRec.CRTC[0x13] = 0xFF & width;
regRec.CR51 = (0x300 & width) >> 4; // Extension bits regRec.CR51 = (0x300 & width) >> 4; // Extension bits
regRec.CR33 = 0x20; regRec.CR33 = 0x20;
@@ -694,6 +694,13 @@ Virge_ModeInit(const DisplayModeEx& mode)
Virge_WriteMode(mode, regRec); // write mode registers to hardware Virge_WriteMode(mode, regRec); // write mode registers to hardware
// Note that the Virge VX chip does not display the hardware cursor when the
// mode is set to 640x480; thus, in this case the hardware cursor functions
// will be disabled so that a software cursor will be used.
si.bDisableHdwCursor = (si.chipType == S3_VIRGE_VX
&& mode.timing.h_display == 640 && mode.timing.v_display == 480);
return true; return true;
} }
File diff suppressed because it is too large Load Diff