removed all pre-NV40refs, removed all overlay code (no info on the current engine known). Driver cleanup mostly done now I hope.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25999 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -73,16 +73,7 @@ enum {
|
|||||||
|
|
||||||
/* card_type in order of date of NV chip design */
|
/* card_type in order of date of NV chip design */
|
||||||
enum {
|
enum {
|
||||||
NV20,
|
NV40 = 0,
|
||||||
NV25,
|
|
||||||
NV28,
|
|
||||||
NV30,
|
|
||||||
NV31,
|
|
||||||
NV34,
|
|
||||||
NV35,
|
|
||||||
NV36,
|
|
||||||
NV38,
|
|
||||||
NV40,
|
|
||||||
NV41,
|
NV41,
|
||||||
NV43,
|
NV43,
|
||||||
NV44,
|
NV44,
|
||||||
@@ -98,11 +89,7 @@ enum {
|
|||||||
|
|
||||||
/* card_arch in order of date of NV chip design */
|
/* card_arch in order of date of NV chip design */
|
||||||
enum {
|
enum {
|
||||||
NV04A = 0,
|
NV40A = 0,
|
||||||
NV10A,
|
|
||||||
NV20A,
|
|
||||||
NV30A,
|
|
||||||
NV40A,
|
|
||||||
NV50A
|
NV50A
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -124,28 +111,13 @@ enum {
|
|||||||
*/
|
*/
|
||||||
//#define NV3_GDI_RECTANGLE_TEXT 0x00000012 /* 2D */
|
//#define NV3_GDI_RECTANGLE_TEXT 0x00000012 /* 2D */
|
||||||
#define NV4_GDI_RECTANGLE_TEXT 0x00000012 /* 2D */
|
#define NV4_GDI_RECTANGLE_TEXT 0x00000012 /* 2D */
|
||||||
#define NV4_CONTEXT_SURFACES_ARGB_ZS 0x00000013 /* 3D */
|
|
||||||
#define NV10_CONTEXT_SURFACES_ARGB_ZS 0x00000013 /* 3D */
|
|
||||||
#define NV4_DX5_TEXTURE_TRIANGLE 0x00000014 /* 3D */
|
|
||||||
#define NV10_DX5_TEXTURE_TRIANGLE 0x00000014 /* 3D */
|
|
||||||
#define NV4_DX6_MULTI_TEXTURE_TRIANGLE 0x00000015 /* unused (yet?) */
|
|
||||||
#define NV10_DX6_MULTI_TEXTURE_TRIANGLE 0x00000015 /* unused (yet?) */
|
|
||||||
#define NV1_RENDER_SOLID_LIN 0x00000016 /* 2D: unused */
|
#define NV1_RENDER_SOLID_LIN 0x00000016 /* 2D: unused */
|
||||||
|
|
||||||
/* max. number of overlay buffers */
|
|
||||||
#define MAXBUFFERS 3
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
/* safety byte-offset from end of cardRAM for preventing acceleration engine crashes
|
/* safety byte-offset from end of cardRAM for preventing acceleration engine crashes
|
||||||
* caused by the existance of DMA engine command buffers in cardRAM and/or fifo
|
* caused by the existance of DMA engine command buffers in cardRAM and/or fifo
|
||||||
* channel engine command re-assigning on-the-fly */
|
* channel engine command re-assigning on-the-fly */
|
||||||
|
|
||||||
/* pre-NV40 notes:
|
|
||||||
* - we need at least 70kB distance from the end of RAM for fifo-reassigning 'bug'
|
|
||||||
* (confirmed on a TNT1);
|
|
||||||
* - keep extra failsafe room to prevent malfunctioning apps from crashing engine. */
|
|
||||||
#define PRE_NV40_OFFSET 80 * 1024
|
|
||||||
|
|
||||||
/* NV40 and higher notes:
|
/* NV40 and higher notes:
|
||||||
* - we need at least 416kB distance from the DMA command buffer:
|
* - we need at least 416kB distance from the DMA command buffer:
|
||||||
* If you get too close to the DMA command buffer on NV40 and NV43 at least (both
|
* If you get too close to the DMA command buffer on NV40 and NV43 at least (both
|
||||||
@@ -346,22 +318,6 @@ typedef struct {
|
|||||||
/* some configuration settings from ~/config/settings/kernel/drivers/nv.settings if exists */
|
/* some configuration settings from ~/config/settings/kernel/drivers/nv.settings if exists */
|
||||||
nv_settings settings;
|
nv_settings settings;
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
overlay_buffer myBuffer[MAXBUFFERS];/* scaler input buffers */
|
|
||||||
int_buf_info myBufInfo[MAXBUFFERS]; /* extra info on scaler input buffers */
|
|
||||||
overlay_token myToken; /* scaler is free/in use */
|
|
||||||
benaphore lock; /* for creating buffers and aquiring overlay unit routines */
|
|
||||||
bool crtc; /* location of overlay unit */
|
|
||||||
/* variables needed for virtualscreens (move_overlay()): */
|
|
||||||
bool active; /* true is overlay currently in use */
|
|
||||||
overlay_window ow; /* current position of overlay output window */
|
|
||||||
overlay_buffer ob; /* current inputbuffer in use */
|
|
||||||
overlay_view my_ov; /* current corrected view in inputbuffer */
|
|
||||||
uint32 h_ifactor; /* current 'unclipped' horizontal inverse scaling factor */
|
|
||||||
uint32 v_ifactor; /* current 'unclipped' vertical inverse scaling factor */
|
|
||||||
} overlay;
|
|
||||||
|
|
||||||
} shared_info;
|
} shared_info;
|
||||||
|
|
||||||
/* Read or write a value in PCI configuration space */
|
/* Read or write a value in PCI configuration space */
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
Other authors:
|
Other authors:
|
||||||
Mark Watson,
|
Mark Watson,
|
||||||
Rudolf Cornelissen 4/2003-5/2004
|
Rudolf Cornelissen 4/2003-6/2008
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MODULE_BIT 0x20000000
|
#define MODULE_BIT 0x20000000
|
||||||
@@ -96,7 +96,6 @@ void MOVE_CURSOR(uint16 x, uint16 y)
|
|||||||
if ((hds!=si->dm.h_display_start) || (vds!=si->dm.v_display_start))
|
if ((hds!=si->dm.h_display_start) || (vds!=si->dm.v_display_start))
|
||||||
{
|
{
|
||||||
MOVE_DISPLAY(hds,vds);
|
MOVE_DISPLAY(hds,vds);
|
||||||
nv_bes_move_overlay();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* put cursor in correct physical position, so stay onscreen (rel. to CRTC) */
|
/* put cursor in correct physical position, so stay onscreen (rel. to CRTC) */
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ noted on a case by case below.
|
|||||||
/*
|
/*
|
||||||
These definitions are out of pure lazyness.
|
These definitions are out of pure lazyness.
|
||||||
*/
|
*/
|
||||||
#define CHKO(x) case B_##x: \
|
|
||||||
if (check_overlay_capability(B_##x) == B_OK) return (void *)x; else return (void *)0
|
|
||||||
#define CHKA(x) case B_##x: \
|
#define CHKA(x) case B_##x: \
|
||||||
if (check_acc_capability(B_##x) == B_OK) \
|
if (check_acc_capability(B_##x) == B_OK) \
|
||||||
return (void *)x##_DMA; \
|
return (void *)x##_DMA; \
|
||||||
@@ -93,16 +91,7 @@ void * get_accelerant_hook(uint32 feature, void *data)
|
|||||||
Note: These hooks are re-acquired by the app_server after each mode switch.
|
Note: These hooks are re-acquired by the app_server after each mode switch.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* only export video overlay functions if card is capable of it */
|
/* video overlay functions are not supported */
|
||||||
//CHKO(OVERLAY_COUNT);
|
|
||||||
//CHKO(OVERLAY_SUPPORTED_SPACES);
|
|
||||||
//CHKO(OVERLAY_SUPPORTED_FEATURES);
|
|
||||||
//CHKO(ALLOCATE_OVERLAY_BUFFER);
|
|
||||||
//CHKO(RELEASE_OVERLAY_BUFFER);
|
|
||||||
//CHKO(GET_OVERLAY_CONSTRAINTS);
|
|
||||||
//CHKO(ALLOCATE_OVERLAY);
|
|
||||||
//CHKO(RELEASE_OVERLAY);
|
|
||||||
//CHKO(CONFIGURE_OVERLAY);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
When requesting an acceleration hook, the calling application provides a
|
When requesting an acceleration hook, the calling application provides a
|
||||||
@@ -129,65 +118,12 @@ void * get_accelerant_hook(uint32 feature, void *data)
|
|||||||
/* Return a null pointer for any feature we don't understand. */
|
/* Return a null pointer for any feature we don't understand. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#undef CHKO
|
|
||||||
#undef CHKA
|
#undef CHKA
|
||||||
#undef CHKD
|
#undef CHKD
|
||||||
#undef HOOK
|
#undef HOOK
|
||||||
#undef ZERO
|
#undef ZERO
|
||||||
#undef HRDC
|
#undef HRDC
|
||||||
|
|
||||||
status_t check_overlay_capability(uint32 feature)
|
|
||||||
{
|
|
||||||
char *msg = "";
|
|
||||||
|
|
||||||
/* setup logmessage text */
|
|
||||||
switch (feature)
|
|
||||||
{
|
|
||||||
case B_OVERLAY_COUNT:
|
|
||||||
msg = "B_OVERLAY_COUNT";
|
|
||||||
break;
|
|
||||||
case B_OVERLAY_SUPPORTED_SPACES:
|
|
||||||
msg = "B_OVERLAY_SUPPORTED_SPACES";
|
|
||||||
break;
|
|
||||||
case B_OVERLAY_SUPPORTED_FEATURES:
|
|
||||||
msg = "B_OVERLAY_SUPPORTED_FEATURES";
|
|
||||||
break;
|
|
||||||
case B_ALLOCATE_OVERLAY_BUFFER:
|
|
||||||
msg = "B_ALLOCATE_OVERLAY_BUFFER";
|
|
||||||
break;
|
|
||||||
case B_RELEASE_OVERLAY_BUFFER:
|
|
||||||
msg = "B_RELEASE_OVERLAY_BUFFER";
|
|
||||||
break;
|
|
||||||
case B_GET_OVERLAY_CONSTRAINTS:
|
|
||||||
msg = "B_GET_OVERLAY_CONSTRAINTS";
|
|
||||||
break;
|
|
||||||
case B_ALLOCATE_OVERLAY:
|
|
||||||
msg = "B_ALLOCATE_OVERLAY";
|
|
||||||
break;
|
|
||||||
case B_RELEASE_OVERLAY:
|
|
||||||
msg = "B_RELEASE_OVERLAY";
|
|
||||||
break;
|
|
||||||
case B_CONFIGURE_OVERLAY:
|
|
||||||
msg = "B_CONFIGURE_OVERLAY";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
msg = "UNKNOWN";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* all older cards have a supported bes */
|
|
||||||
if ((si->ps.card_type <= NV40) || (si->ps.card_type == NV45))
|
|
||||||
{
|
|
||||||
LOG(4, ("Overlay: Exporting hook %s.\n", msg));
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* all newer NV40 architecture cards have a new HDTV capable bes except for
|
|
||||||
* GeForce 6800's. Unfortunately we have no info about the new bes yet. */
|
|
||||||
LOG(4, ("Overlay: Not exporting hook %s.\n", msg));
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t check_acc_capability(uint32 feature)
|
status_t check_acc_capability(uint32 feature)
|
||||||
{
|
{
|
||||||
char *msg = "";
|
char *msg = "";
|
||||||
|
|||||||
@@ -97,7 +97,6 @@ status_t INIT_ACCELERANT(int the_fd)
|
|||||||
{
|
{
|
||||||
status_t result;
|
status_t result;
|
||||||
int pointer_reservation; //mem reserved for pointer
|
int pointer_reservation; //mem reserved for pointer
|
||||||
int cnt; //used for iteration through the overlay buffers
|
|
||||||
|
|
||||||
if (0) {
|
if (0) {
|
||||||
time_t now = time (NULL);
|
time_t now = time (NULL);
|
||||||
@@ -174,20 +173,6 @@ status_t INIT_ACCELERANT(int the_fd)
|
|||||||
si->engine.threeD.reload = 0xffffffff;
|
si->engine.threeD.reload = 0xffffffff;
|
||||||
INIT_BEN(si->engine.lock);
|
INIT_BEN(si->engine.lock);
|
||||||
|
|
||||||
INIT_BEN(si->overlay.lock);
|
|
||||||
for (cnt = 0; cnt < MAXBUFFERS; cnt++)
|
|
||||||
{
|
|
||||||
/* make sure overlay buffers are 'marked' as being free */
|
|
||||||
si->overlay.myBuffer[cnt].buffer = NULL;
|
|
||||||
si->overlay.myBuffer[cnt].buffer_dma = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make sure overlay unit is 'marked' as being free */
|
|
||||||
si->overlay.myToken = NULL;
|
|
||||||
|
|
||||||
/* note that overlay is not in use (for nv_bes_move_overlay()) */
|
|
||||||
si->overlay.active = false;
|
|
||||||
|
|
||||||
/* bail out if something failed */
|
/* bail out if something failed */
|
||||||
if (result != B_OK) goto error1;
|
if (result != B_OK) goto error1;
|
||||||
|
|
||||||
@@ -347,7 +332,6 @@ void UNINIT_ACCELERANT(void)
|
|||||||
|
|
||||||
/* delete benaphores ONLY if we are the primary accelerant */
|
/* delete benaphores ONLY if we are the primary accelerant */
|
||||||
DELETE_BEN(si->engine.lock);
|
DELETE_BEN(si->engine.lock);
|
||||||
DELETE_BEN(si->overlay.lock);
|
|
||||||
|
|
||||||
/* ensure that INIT_ACCELERANT can be executed again */
|
/* ensure that INIT_ACCELERANT can be executed again */
|
||||||
si->accelerant_in_use = false;
|
si->accelerant_in_use = false;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ Addon nvidia_gpgpu.accelerant :
|
|||||||
GetModeInfo.c
|
GetModeInfo.c
|
||||||
GetTimingConstraints.c
|
GetTimingConstraints.c
|
||||||
InitAccelerant.c
|
InitAccelerant.c
|
||||||
Overlay.c
|
|
||||||
ProposeDisplayMode.c
|
ProposeDisplayMode.c
|
||||||
SetDisplayMode.c
|
SetDisplayMode.c
|
||||||
: libnvidia_gpgpu_engine.a
|
: libnvidia_gpgpu_engine.a
|
||||||
|
|||||||
@@ -1,626 +0,0 @@
|
|||||||
/* Written by Rudolf Cornelissen 05/2002-4/2006 */
|
|
||||||
|
|
||||||
/* Note on 'missing features' in BeOS 5.0.3 and DANO:
|
|
||||||
* BeOS needs to define more colorspaces! It would be nice if BeOS would support the FourCC 'definitions'
|
|
||||||
* of colorspaces. These colorspaces are 32bit words, so it could be simply done (or is it already so?)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MODULE_BIT 0x00000400
|
|
||||||
|
|
||||||
#include "acc_std.h"
|
|
||||||
|
|
||||||
/* define the supported overlay input colorspaces */
|
|
||||||
/* It would be nice to have the YUV4:2:0 2-plane mode implemented also later on, but the Be colorspace
|
|
||||||
* definitions (in GraphicsDefs.h, R5.0.3 and DANO5.1d0) do not include this one... */
|
|
||||||
static uint32 overlay_colorspaces [] = { (uint32)B_YCbCr422, (uint32)B_NO_COLOR_SPACE };
|
|
||||||
|
|
||||||
uint32 OVERLAY_COUNT(const display_mode *dm)
|
|
||||||
// This method is never used AFAIK though it *is* exported on R5.0.3 and DANO.
|
|
||||||
// Does someone know howto invoke it?
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: count called\n"));
|
|
||||||
|
|
||||||
/* check for NULL pointer */
|
|
||||||
if (dm == NULL)
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: No display mode specified!\n"));
|
|
||||||
}
|
|
||||||
/* apparantly overlay count should report the number of 'overlay units' on the card */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint32 *OVERLAY_SUPPORTED_SPACES(const display_mode *dm)
|
|
||||||
// This method is never used AFAIK though it *is* exported on R5.0.3 and DANO.
|
|
||||||
// Does someone know howto invoke it?
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: supported_spaces called.\n"));
|
|
||||||
|
|
||||||
/* check for NULL pointer */
|
|
||||||
if (dm == NULL)
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: No display mode specified!\n"));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* assuming interlaced VGA is not supported */
|
|
||||||
if (dm->timing.flags & B_TIMING_INTERLACED)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
/* return a B_NO_COLOR_SPACE terminated list */
|
|
||||||
return &overlay_colorspaces[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 OVERLAY_SUPPORTED_FEATURES(uint32 a_color_space)
|
|
||||||
// This method is never used AFAIK. On R5.0.3 and DANO it is not even exported!
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: supported_features: color_space $%08x\n",a_color_space));
|
|
||||||
|
|
||||||
/* check what features are supported for the current overlaybitmap colorspace */
|
|
||||||
switch (a_color_space)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
return
|
|
||||||
( B_OVERLAY_KEYING_USES_ALPHA |
|
|
||||||
B_OVERLAY_COLOR_KEY |
|
|
||||||
B_OVERLAY_HORIZONTAL_FILTERING |
|
|
||||||
B_OVERLAY_VERTICAL_FILTERING );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const overlay_buffer *ALLOCATE_OVERLAY_BUFFER(color_space cs, uint16 width, uint16 height)
|
|
||||||
{
|
|
||||||
int offset = 0; /* used to determine next buffer to create */
|
|
||||||
uint32 adress, adress2, temp32; /* used to calculate buffer adresses */
|
|
||||||
uint32 oldsize = 0; /* used to 'squeeze' new buffers between already existing ones */
|
|
||||||
int cnt; /* loopcounter */
|
|
||||||
|
|
||||||
/* acquire the shared benaphore */
|
|
||||||
AQUIRE_BEN(si->overlay.lock)
|
|
||||||
|
|
||||||
LOG(4,("Overlay: cardRAM_start = $%08x\n",(uint32)((uint8*)si->framebuffer)));
|
|
||||||
LOG(4,("Overlay: cardRAM_start_DMA = $%08x\n",(uint32)((uint8*)si->framebuffer_pci)));
|
|
||||||
LOG(4,("Overlay: cardRAM_size = %3.3fMb\n",(si->ps.memory_size / (1024.0 * 1024.0))));
|
|
||||||
|
|
||||||
/* find first empty slot (room for another buffer?) */
|
|
||||||
for (offset = 0; offset < MAXBUFFERS; offset++)
|
|
||||||
{
|
|
||||||
if (si->overlay.myBuffer[offset].buffer == NULL) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(4,("Overlay: Allocate_buffer offset = %d\n",offset));
|
|
||||||
|
|
||||||
if (offset < MAXBUFFERS)
|
|
||||||
/* setup new scaler input buffer */
|
|
||||||
{
|
|
||||||
switch (cs)
|
|
||||||
{
|
|
||||||
case B_YCbCr422:
|
|
||||||
if (si->ps.card_arch < NV10A)
|
|
||||||
{
|
|
||||||
/* check if slopspace is needed: RIVA128 and TNT need ~0x000f. */
|
|
||||||
si->overlay.myBuffer[offset].width = ((width + 0x000f) & ~0x000f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* check if slopspace is needed: GeForce need ~0x001f. */
|
|
||||||
/* fixme:
|
|
||||||
* update needed for GF DVDmax support to adhere to CRTC2 constraints?? */
|
|
||||||
si->overlay.myBuffer[offset].width = ((width + 0x001f) & ~0x001f);
|
|
||||||
}
|
|
||||||
si->overlay.myBuffer[offset].bytes_per_row = 2 * si->overlay.myBuffer[offset].width;
|
|
||||||
|
|
||||||
/* check if the requested horizontal pitch is supported: */
|
|
||||||
//fixme: tune for GF and TNT...
|
|
||||||
if (si->overlay.myBuffer[offset].width > 4088)
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: Sorry, requested buffer pitch not supported, aborted\n"));
|
|
||||||
|
|
||||||
/* release the shared benaphore */
|
|
||||||
RELEASE_BEN(si->overlay.lock)
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* unsupported colorspace! */
|
|
||||||
LOG(4,("Overlay: Sorry, colorspace $%08x not supported, aborted\n",cs));
|
|
||||||
|
|
||||||
/* release the shared benaphore */
|
|
||||||
RELEASE_BEN(si->overlay.lock)
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if the requested buffer width is supported */
|
|
||||||
if (si->overlay.myBuffer[offset].width > 1024)
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: Sorry, requested buffer width not supported, aborted\n"));
|
|
||||||
|
|
||||||
/* release the shared benaphore */
|
|
||||||
RELEASE_BEN(si->overlay.lock)
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
/* check if the requested buffer height is supported */
|
|
||||||
if (height > 1024)
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: Sorry, requested buffer height not supported, aborted\n"));
|
|
||||||
|
|
||||||
/* release the shared benaphore */
|
|
||||||
RELEASE_BEN(si->overlay.lock)
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* store slopspace (in pixels) for each bitmap for use by 'overlay unit' (BES) */
|
|
||||||
si->overlay.myBufInfo[offset].slopspace = si->overlay.myBuffer[offset].width - width;
|
|
||||||
|
|
||||||
si->overlay.myBuffer[offset].space = cs;
|
|
||||||
si->overlay.myBuffer[offset].height = height;
|
|
||||||
|
|
||||||
/* we define the overlay buffers to reside 'in the back' of the cards RAM */
|
|
||||||
/* NOTE to app programmers:
|
|
||||||
* Beware that an app using overlay needs to track workspace switches and screenprefs
|
|
||||||
* changes. If such an action is detected, the app needs to reset it's pointers to the
|
|
||||||
* newly created overlay bitmaps, which will be assigned by BeOS automatically after such
|
|
||||||
* an event. (Also the app needs to respect the new overlay_constraints that will be applicable!)
|
|
||||||
*
|
|
||||||
* It is entirely possible that new bitmaps may *not* be re-setup at all, or less of them
|
|
||||||
* than previously setup by the app might be re-setup. This is due to cardRAM restraints then.
|
|
||||||
* This means that the app should also check for NULL pointers returned by the bitmaps,
|
|
||||||
* and if this happens, it needs to fallback to single buffered overlay or even fallback to
|
|
||||||
* bitmap output for the new situation. */
|
|
||||||
|
|
||||||
/* Another NOTE for app programmers:
|
|
||||||
* A *positive* side-effect of assigning the first overlay buffer exactly at the end of the
|
|
||||||
* cardRAM is that apps that try to write beyond the buffer's space get a segfault immediately.
|
|
||||||
* This *greatly* simplifies tracking such errors!
|
|
||||||
* Of course such errors may lead to strange effects in the app or driver behaviour if they are
|
|
||||||
* not hunted down and removed.. */
|
|
||||||
|
|
||||||
/* calculate first free RAM adress in card:
|
|
||||||
* Driver setup is as follows:
|
|
||||||
* card base: - hardware cursor bitmap (if used),
|
|
||||||
* directly above - screen memory for both heads */
|
|
||||||
adress2 = (((uint32)((uint8*)si->fbc.frame_buffer)) + /* cursor already included here */
|
|
||||||
(si->fbc.bytes_per_row * si->dm.virtual_height)); /* size in bytes of screen(s) */
|
|
||||||
LOG(4,("Overlay: first free cardRAM virtual adress $%08x\n", adress2));
|
|
||||||
|
|
||||||
/* calculate 'preliminary' buffer size including slopspace */
|
|
||||||
oldsize = si->overlay.myBufInfo[offset].size;
|
|
||||||
si->overlay.myBufInfo[offset].size =
|
|
||||||
si->overlay.myBuffer[offset].bytes_per_row * si->overlay.myBuffer[offset].height;
|
|
||||||
|
|
||||||
/* calculate virtual memory adress that would be needed for a new bitmap */
|
|
||||||
/* NOTE to app programmers:
|
|
||||||
* For testing app behaviour regarding workspace switches or screen prefs changes to settings
|
|
||||||
* that do not have enough cardRAM left for allocation of overlay bitmaps, you need a card with
|
|
||||||
* a low amount of RAM. Or you can set in the file nv.settings for example:
|
|
||||||
* memory 8 #8Mb RAM on card
|
|
||||||
* and reboot (this simulates 8Mb RAM on the card).
|
|
||||||
*
|
|
||||||
* If you switch now to settings: 1600x1200x32bit (single head) the app needs to fallback to
|
|
||||||
* bitmap output or maybe single buffered overlay output if small bitmaps are used. */
|
|
||||||
|
|
||||||
adress = (((uint32)((uint8*)si->framebuffer)) + si->ps.memory_size);
|
|
||||||
/* Keep some extra distance as a workaround for certain bugs (see
|
|
||||||
* DriverInterface.h for an explanation). */
|
|
||||||
if (si->ps.card_arch < NV40A)
|
|
||||||
adress -= PRE_NV40_OFFSET;
|
|
||||||
else
|
|
||||||
adress -= NV40_PLUS_OFFSET;
|
|
||||||
|
|
||||||
for (cnt = 0; cnt <= offset; cnt++)
|
|
||||||
{
|
|
||||||
adress -= si->overlay.myBufInfo[cnt].size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the > G200 scalers require buffers to be aligned to 16 byte pages cardRAM offset, G200 can do with
|
|
||||||
* 8 byte pages cardRAM offset. Compatible settings used, has no real downside consequences here */
|
|
||||||
|
|
||||||
/* Check if we need to modify the buffers starting adress and thus the size */
|
|
||||||
/* calculate 'would be' cardRAM offset */
|
|
||||||
temp32 = (adress - ((uint32)((vuint32 *)si->framebuffer)));
|
|
||||||
/* check if it is aligned */
|
|
||||||
if (temp32 != (temp32 & 0xfffffff0))
|
|
||||||
{
|
|
||||||
/* update the (already calculated) buffersize to get it aligned */
|
|
||||||
si->overlay.myBufInfo[offset].size += (temp32 - (temp32 & 0xfffffff0));
|
|
||||||
/* update the (already calculated) adress to get it aligned */
|
|
||||||
adress -= (temp32 - (temp32 & 0xfffffff0));
|
|
||||||
}
|
|
||||||
LOG(4,("Overlay: new buffer needs virtual adress $%08x\n", adress));
|
|
||||||
|
|
||||||
/* First check now if buffer to be defined is 'last one' in memory (speaking backwards):
|
|
||||||
* this is done to prevent a large buffer getting created in the space a small buffer
|
|
||||||
* occupied earlier, if not all buffers created were deleted.
|
|
||||||
* Note also that the app can delete the buffers in any order desired. */
|
|
||||||
|
|
||||||
/* NOTE to app programmers:
|
|
||||||
* If you are going to delete a overlay buffer you created, you should delete them *all* and
|
|
||||||
* then re-create only the new ones needed. This way you are sure not to get unused memory-
|
|
||||||
* space in between your overlay buffers for instance, so cardRAM is used 'to the max'.
|
|
||||||
* If you don't, you might not get a buffer at all if you are trying to set up a larger one
|
|
||||||
* than before.
|
|
||||||
* (Indeed: not all buffers *have* to be of the same type and size...) */
|
|
||||||
|
|
||||||
for (cnt = offset; cnt < MAXBUFFERS; cnt++)
|
|
||||||
{
|
|
||||||
if (si->overlay.myBuffer[cnt].buffer != NULL)
|
|
||||||
{
|
|
||||||
/* Check if the new buffer would fit into the space the single old one used here */
|
|
||||||
if (si->overlay.myBufInfo[offset].size <= oldsize)
|
|
||||||
{
|
|
||||||
/* It does, so we reset to the old size and adresses to prevent the space from shrinking
|
|
||||||
* if we get here again... */
|
|
||||||
adress -= (oldsize - si->overlay.myBufInfo[offset].size);
|
|
||||||
si->overlay.myBufInfo[offset].size = oldsize;
|
|
||||||
LOG(4,("Overlay: 'squeezing' in buffer:\n"
|
|
||||||
"Overlay: resetting it to virtual adress $%08x and size $%08x\n", adress,oldsize));
|
|
||||||
/* force exiting the FOR loop */
|
|
||||||
cnt = MAXBUFFERS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* nogo, sorry */
|
|
||||||
LOG(4,("Overlay: Other buffer(s) exist after this one:\n"
|
|
||||||
"Overlay: not enough space to 'squeeze' this one in, aborted\n"));
|
|
||||||
|
|
||||||
/* Reset to the old size to prevent the space from 'growing' if we get here again... */
|
|
||||||
si->overlay.myBufInfo[offset].size = oldsize;
|
|
||||||
|
|
||||||
/* release the shared benaphore */
|
|
||||||
RELEASE_BEN(si->overlay.lock)
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if we have enough space to setup this new bitmap
|
|
||||||
* (preventing overlap of desktop RAMspace & overlay bitmap RAMspace here) */
|
|
||||||
if (adress < adress2)
|
|
||||||
/* nope, sorry */
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: Sorry, no more space for buffers: aborted\n"));
|
|
||||||
|
|
||||||
/* release the shared benaphore */
|
|
||||||
RELEASE_BEN(si->overlay.lock)
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
/* continue buffer setup */
|
|
||||||
si->overlay.myBuffer[offset].buffer = (void *) adress;
|
|
||||||
|
|
||||||
/* calculate physical memory adress (for dma use) */
|
|
||||||
adress = (((uint32)((uint8*)si->framebuffer_pci)) + si->ps.memory_size);
|
|
||||||
/* Keep some extra distance as a workaround for certain bugs (see
|
|
||||||
* DriverInterface.h for an explanation). */
|
|
||||||
if (si->ps.card_arch < NV40A)
|
|
||||||
adress -= PRE_NV40_OFFSET;
|
|
||||||
else
|
|
||||||
adress -= NV40_PLUS_OFFSET;
|
|
||||||
|
|
||||||
for (cnt = 0; cnt <= offset; cnt++)
|
|
||||||
{
|
|
||||||
adress -= si->overlay.myBufInfo[cnt].size;
|
|
||||||
}
|
|
||||||
/* this adress is already aligned to the scaler's requirements (via the already modified sizes) */
|
|
||||||
si->overlay.myBuffer[offset].buffer_dma = (void *) adress;
|
|
||||||
|
|
||||||
LOG(4,("Overlay: New buffer: addr $%08x, dma_addr $%08x, color space $%08x\n",
|
|
||||||
(uint32)((uint8*)si->overlay.myBuffer[offset].buffer),
|
|
||||||
(uint32)((uint8*)si->overlay.myBuffer[offset].buffer_dma), cs));
|
|
||||||
LOG(4,("Overlay: New buffer's size is $%08x\n", si->overlay.myBufInfo[offset].size));
|
|
||||||
|
|
||||||
/* release the shared benaphore */
|
|
||||||
RELEASE_BEN(si->overlay.lock)
|
|
||||||
|
|
||||||
return &si->overlay.myBuffer[offset];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* sorry, no more room for buffers */
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: Sorry, no more space for buffers: aborted\n"));
|
|
||||||
|
|
||||||
/* release the shared benaphore */
|
|
||||||
RELEASE_BEN(si->overlay.lock)
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t RELEASE_OVERLAY_BUFFER(const overlay_buffer *ob)
|
|
||||||
/* Note that the user can delete the buffers in any order desired! */
|
|
||||||
{
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
if (ob != NULL)
|
|
||||||
{
|
|
||||||
/* find the buffer */
|
|
||||||
for (offset = 0; offset < MAXBUFFERS; offset++)
|
|
||||||
{
|
|
||||||
if (si->overlay.myBuffer[offset].buffer == ob->buffer) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset < MAXBUFFERS)
|
|
||||||
/* delete current buffer */
|
|
||||||
{
|
|
||||||
si->overlay.myBuffer[offset].buffer = NULL;
|
|
||||||
si->overlay.myBuffer[offset].buffer_dma = NULL;
|
|
||||||
|
|
||||||
LOG(4,("Overlay: Release_buffer offset = %d, buffer released\n",offset));
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* this is no buffer of ours! */
|
|
||||||
LOG(4,("Overlay: Release_overlay_buffer: not ours, aborted!\n"));
|
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* no buffer specified! */
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: Release_overlay_buffer: no buffer specified, aborted!\n"));
|
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t GET_OVERLAY_CONSTRAINTS
|
|
||||||
(const display_mode *dm, const overlay_buffer *ob, overlay_constraints *oc)
|
|
||||||
{
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
LOG(4,("Overlay: Get_overlay_constraints called\n"));
|
|
||||||
|
|
||||||
/* check for NULL pointers */
|
|
||||||
if ((dm == NULL) || (ob == NULL) || (oc == NULL))
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: Get_overlay_constraints: Null pointer(s) detected!\n"));
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find the buffer */
|
|
||||||
for (offset = 0; offset < MAXBUFFERS; offset++)
|
|
||||||
{
|
|
||||||
if (si->overlay.myBuffer[offset].buffer == ob->buffer) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset < MAXBUFFERS)
|
|
||||||
{
|
|
||||||
/* scaler input (values are in pixels) */
|
|
||||||
oc->view.h_alignment = 0;
|
|
||||||
oc->view.v_alignment = 0;
|
|
||||||
|
|
||||||
switch (ob->space)
|
|
||||||
{
|
|
||||||
case B_YCbCr422:
|
|
||||||
if (si->ps.card_arch < NV10A)
|
|
||||||
{
|
|
||||||
/* RIVA128 and TNT need 15.
|
|
||||||
* Note: this has to be in sync with the slopspace setup during buffer allocation.. */
|
|
||||||
oc->view.width_alignment = 15;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* GeForce need 31.
|
|
||||||
* Note: this has to be in sync with the slopspace setup during buffer allocation.. */
|
|
||||||
oc->view.width_alignment = 31;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* we should not be here, but set the worst-case value just to be safe anyway */
|
|
||||||
oc->view.width_alignment = 31;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
oc->view.height_alignment = 0;
|
|
||||||
oc->view.width.min = 1;
|
|
||||||
oc->view.height.min = 2; /* two fields */
|
|
||||||
oc->view.width.max = ob->width;
|
|
||||||
oc->view.height.max = ob->height;
|
|
||||||
|
|
||||||
/* scaler output restrictions */
|
|
||||||
oc->window.h_alignment = 0;
|
|
||||||
oc->window.v_alignment = 0;
|
|
||||||
oc->window.width_alignment = 0;
|
|
||||||
oc->window.height_alignment = 0;
|
|
||||||
oc->window.width.min = 2;
|
|
||||||
/* GeForce cards can output upto and including 2046 pixels in width */
|
|
||||||
//fixme: how about TNT?
|
|
||||||
if (dm->virtual_width > 2046)
|
|
||||||
{
|
|
||||||
oc->window.width.max = 2046;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oc->window.width.max = dm->virtual_width;
|
|
||||||
}
|
|
||||||
oc->window.height.min = 2;
|
|
||||||
/* GeForce cards can output upto and including 2046 pixels in height */
|
|
||||||
//fixme: how about TNT?
|
|
||||||
if (dm->virtual_height > 2046)
|
|
||||||
{
|
|
||||||
oc->window.height.max = 2046;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oc->window.height.max = dm->virtual_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* GeForce scaling restrictions */
|
|
||||||
switch (si->ps.card_arch)
|
|
||||||
{
|
|
||||||
case NV04A:
|
|
||||||
/* Riva128-TNT2 series have an old BES engine... */
|
|
||||||
oc->h_scale.min = 1.0;
|
|
||||||
oc->v_scale.min = 1.0;
|
|
||||||
break;
|
|
||||||
case NV30A:
|
|
||||||
case NV40A:
|
|
||||||
/* GeForceFX series and up have a new BES engine... */
|
|
||||||
oc->h_scale.min = 0.5;
|
|
||||||
oc->v_scale.min = 0.5;
|
|
||||||
/* NV31 (confirmed GeForceFX 5600) has NV20A scaling limits!
|
|
||||||
* So let it fall through... */
|
|
||||||
if (si->ps.card_type != NV31) break;
|
|
||||||
default:
|
|
||||||
/* the rest in between... */
|
|
||||||
oc->h_scale.min = 0.125;
|
|
||||||
oc->v_scale.min = 0.125;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* all cards have a upscaling limit of 8.0 (see official nVidia specsheets) */
|
|
||||||
oc->h_scale.max = 8.0;
|
|
||||||
oc->v_scale.max = 8.0;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* this is no buffer of ours! */
|
|
||||||
LOG(4,("Overlay: Get_overlay_constraints: buffer is not ours, aborted!\n"));
|
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
overlay_token ALLOCATE_OVERLAY(void)
|
|
||||||
{
|
|
||||||
uint32 tmpToken;
|
|
||||||
LOG(4,("Overlay: Allocate_overlay called: "));
|
|
||||||
|
|
||||||
/* come up with a token */
|
|
||||||
tmpToken = 0x12345678;
|
|
||||||
|
|
||||||
/* acquire the shared benaphore */
|
|
||||||
AQUIRE_BEN(si->overlay.lock)
|
|
||||||
|
|
||||||
/* overlay unit already in use? */
|
|
||||||
if (si->overlay.myToken == NULL)
|
|
||||||
/* overlay unit is available */
|
|
||||||
{
|
|
||||||
LOG(4,("succesfull\n"));
|
|
||||||
|
|
||||||
si->overlay.myToken = &tmpToken;
|
|
||||||
|
|
||||||
/* release the shared benaphore */
|
|
||||||
RELEASE_BEN(si->overlay.lock)
|
|
||||||
|
|
||||||
return si->overlay.myToken;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* sorry, overlay unit is occupied */
|
|
||||||
{
|
|
||||||
LOG(4,("failed: already in use!\n"));
|
|
||||||
|
|
||||||
/* release the shared benaphore */
|
|
||||||
RELEASE_BEN(si->overlay.lock)
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t RELEASE_OVERLAY(overlay_token ot)
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: Release_overlay called: "));
|
|
||||||
|
|
||||||
/* is this call for real? */
|
|
||||||
if ((ot == NULL) || (si->overlay.myToken == NULL) || (ot != si->overlay.myToken))
|
|
||||||
/* nope, abort */
|
|
||||||
{
|
|
||||||
LOG(4,("failed, not in use!\n"));
|
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* call is for real */
|
|
||||||
{
|
|
||||||
|
|
||||||
nv_release_bes();
|
|
||||||
|
|
||||||
LOG(4,("succesfull\n"));
|
|
||||||
|
|
||||||
si->overlay.myToken = NULL;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t CONFIGURE_OVERLAY
|
|
||||||
(overlay_token ot, const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov)
|
|
||||||
{
|
|
||||||
int offset = 0; /* used for buffer index */
|
|
||||||
|
|
||||||
LOG(4,("Overlay: Configure_overlay called: "));
|
|
||||||
|
|
||||||
/* Note:
|
|
||||||
* When a Workspace switch, screen prefs change, or overlay app shutdown occurs, BeOS will
|
|
||||||
* release all overlay buffers. The buffer currently displayed at that moment, may need some
|
|
||||||
* 'hardware releasing' in the CONFIGURE_OVERLAY routine. This is why CONFIGURE_OVERLAY gets
|
|
||||||
* called one more time then, with a null pointer for overlay_window and overlay_view, while
|
|
||||||
* the currently displayed overlay_buffer is given.
|
|
||||||
* The G200-G550 do not need to do anything on such an occasion, so we simply return if we
|
|
||||||
* get called then. */
|
|
||||||
if ((ow == NULL) || (ov == NULL))
|
|
||||||
{
|
|
||||||
LOG(4,("output properties changed\n"));
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note:
|
|
||||||
* If during overlay use the screen prefs are changed, or the workspace has changed, it
|
|
||||||
* may be that we were not able to re-allocate the requested overlay buffers (or only partly)
|
|
||||||
* due to lack of cardRAM. If the app does not respond properly to this, we might end up
|
|
||||||
* with a NULL pointer instead of a overlay_buffer to work with here.
|
|
||||||
* Of course, we need to abort then to prevent the system from 'going down'.
|
|
||||||
* The app will probably crash because it will want to write into this non-existant buffer
|
|
||||||
* at some point. */
|
|
||||||
if (ob == NULL)
|
|
||||||
{
|
|
||||||
LOG(4,("no overlay buffer specified\n"));
|
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* is this call done by the app that owns us? */
|
|
||||||
if ((ot == NULL) || (si->overlay.myToken == NULL) || (ot != si->overlay.myToken))
|
|
||||||
/* nope, abort */
|
|
||||||
{
|
|
||||||
LOG(4,("failed\n"));
|
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* call is for real */
|
|
||||||
{
|
|
||||||
/* find the buffer's offset */
|
|
||||||
for (offset = 0; offset < MAXBUFFERS; offset++)
|
|
||||||
{
|
|
||||||
if (si->overlay.myBuffer[offset].buffer == ob->buffer) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset < MAXBUFFERS)
|
|
||||||
{
|
|
||||||
LOG(4,("succesfull, switching to buffer %d\n", offset));
|
|
||||||
|
|
||||||
/* program overlay hardware */
|
|
||||||
nv_configure_bes(ob, ow, ov, offset);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* this is no buffer of ours! */
|
|
||||||
LOG(4,("buffer is not ours, aborted!\n"));
|
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -343,10 +343,7 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const displa
|
|||||||
|
|
||||||
/* Reserve extra space as a workaround for certain bugs (see DriverInterface.h
|
/* Reserve extra space as a workaround for certain bugs (see DriverInterface.h
|
||||||
* for an explanation). */
|
* for an explanation). */
|
||||||
if (si->ps.card_arch < NV40A)
|
mem_reservation += NV40_PLUS_OFFSET;
|
||||||
mem_reservation += PRE_NV40_OFFSET;
|
|
||||||
else
|
|
||||||
mem_reservation += NV40_PLUS_OFFSET;
|
|
||||||
|
|
||||||
/* memory requirement for frame buffer */
|
/* memory requirement for frame buffer */
|
||||||
if (row_bytes * target->virtual_height > si->ps.memory_size - mem_reservation) {
|
if (row_bytes * target->virtual_height > si->ps.memory_size - mem_reservation) {
|
||||||
|
|||||||
@@ -288,12 +288,7 @@ if (si->ps.card_arch < NV50A)
|
|||||||
si->engine.threeD.mem_high = si->ps.memory_size - 1;
|
si->engine.threeD.mem_high = si->ps.memory_size - 1;
|
||||||
/* Keep some extra distance as a workaround for certain bugs (see
|
/* Keep some extra distance as a workaround for certain bugs (see
|
||||||
* DriverInterface.h for an explanation). */
|
* DriverInterface.h for an explanation). */
|
||||||
if (si->ps.card_arch < NV40A)
|
si->engine.threeD.mem_high -= NV40_PLUS_OFFSET;
|
||||||
si->engine.threeD.mem_high -= PRE_NV40_OFFSET;
|
|
||||||
else
|
|
||||||
si->engine.threeD.mem_high -= NV40_PLUS_OFFSET;
|
|
||||||
|
|
||||||
si->engine.threeD.mem_high -= (MAXBUFFERS * 1024 * 1024 * 2); /* see overlay.c file */
|
|
||||||
|
|
||||||
/* restore screen(s) output state(s) */
|
/* restore screen(s) output state(s) */
|
||||||
// SET_DPMS_MODE(si->dpms_flags);
|
// SET_DPMS_MODE(si->dpms_flags);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ UsePrivateHeaders [ FDirName graphics nvidia_gpgpu ] ;
|
|||||||
|
|
||||||
StaticLibrary libnvidia_gpgpu_engine.a :
|
StaticLibrary libnvidia_gpgpu_engine.a :
|
||||||
nv_acc_dma.c
|
nv_acc_dma.c
|
||||||
nv_bes.c
|
|
||||||
nv_crtc.c
|
nv_crtc.c
|
||||||
nv_crtc2.c
|
nv_crtc2.c
|
||||||
nv_dac.c
|
nv_dac.c
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,876 +0,0 @@
|
|||||||
/* Nvidia TNT and GeForce Back End Scaler functions */
|
|
||||||
/* Written by Rudolf Cornelissen 05/2002-12/2005 */
|
|
||||||
|
|
||||||
#define MODULE_BIT 0x00000200
|
|
||||||
|
|
||||||
#include "nv_std.h"
|
|
||||||
|
|
||||||
typedef struct move_overlay_info move_overlay_info;
|
|
||||||
|
|
||||||
struct move_overlay_info
|
|
||||||
{
|
|
||||||
uint32 hcoordv; /* left and right edges of video output window */
|
|
||||||
uint32 vcoordv; /* top and bottom edges of video output window */
|
|
||||||
uint32 hsrcstv; /* horizontal source start in source buffer (clipping) */
|
|
||||||
uint32 v1srcstv; /* vertical source start in source buffer (clipping) */
|
|
||||||
uint32 a1orgv; /* alternate source clipping via startadress of source buffer */
|
|
||||||
};
|
|
||||||
|
|
||||||
static void nv_bes_calc_move_overlay(move_overlay_info *moi);
|
|
||||||
static void nv_bes_program_move_overlay(move_overlay_info moi);
|
|
||||||
|
|
||||||
/* move the overlay output window in virtualscreens */
|
|
||||||
/* Note:
|
|
||||||
* si->dm.h_display_start and si->dm.v_display_start determine where the new
|
|
||||||
* output window is located! */
|
|
||||||
void nv_bes_move_overlay()
|
|
||||||
{
|
|
||||||
move_overlay_info moi;
|
|
||||||
|
|
||||||
/* abort if overlay is not active */
|
|
||||||
if (!si->overlay.active) return;
|
|
||||||
|
|
||||||
nv_bes_calc_move_overlay(&moi);
|
|
||||||
nv_bes_program_move_overlay(moi);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nv_bes_calc_move_overlay(move_overlay_info *moi)
|
|
||||||
{
|
|
||||||
/* misc used variables */
|
|
||||||
uint16 temp1, temp2;
|
|
||||||
/* visible screen window in virtual workspaces */
|
|
||||||
uint16 crtc_hstart, crtc_vstart, crtc_hend, crtc_vend;
|
|
||||||
|
|
||||||
/* do 'overlay follow head' in dualhead modes on dualhead cards */
|
|
||||||
if (si->ps.secondary_head)
|
|
||||||
{
|
|
||||||
switch (si->dm.flags & DUALHEAD_BITS)
|
|
||||||
{
|
|
||||||
case DUALHEAD_ON:
|
|
||||||
case DUALHEAD_SWITCH:
|
|
||||||
if ((si->overlay.ow.h_start + (si->overlay.ow.width / 2)) <
|
|
||||||
(si->dm.h_display_start + si->dm.timing.h_display))
|
|
||||||
nv_bes_to_crtc(si->crtc_switch_mode);
|
|
||||||
else
|
|
||||||
nv_bes_to_crtc(!si->crtc_switch_mode);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
nv_bes_to_crtc(si->crtc_switch_mode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the BES does not respect virtual_workspaces, but adheres to CRTC
|
|
||||||
* constraints only */
|
|
||||||
crtc_hstart = si->dm.h_display_start;
|
|
||||||
/* make dualhead stretch and switch mode work while we're at it.. */
|
|
||||||
if (si->overlay.crtc)
|
|
||||||
{
|
|
||||||
crtc_hstart += si->dm.timing.h_display;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* horizontal end is the first position beyond the displayed range on the CRTC */
|
|
||||||
crtc_hend = crtc_hstart + si->dm.timing.h_display;
|
|
||||||
crtc_vstart = si->dm.v_display_start;
|
|
||||||
/* vertical end is the first position beyond the displayed range on the CRTC */
|
|
||||||
crtc_vend = crtc_vstart + si->dm.timing.v_display;
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************
|
|
||||||
*** setup all edges of output window ***
|
|
||||||
****************************************/
|
|
||||||
|
|
||||||
/* setup left and right edges of output window */
|
|
||||||
moi->hcoordv = 0;
|
|
||||||
/* left edge coordinate of output window, must be inside desktop */
|
|
||||||
/* clipping on the left side */
|
|
||||||
if (si->overlay.ow.h_start < crtc_hstart)
|
|
||||||
{
|
|
||||||
temp1 = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* clipping on the right side */
|
|
||||||
if (si->overlay.ow.h_start >= (crtc_hend - 1))
|
|
||||||
{
|
|
||||||
/* width < 2 is not allowed */
|
|
||||||
temp1 = (crtc_hend - crtc_hstart - 2) & 0x7ff;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* no clipping here */
|
|
||||||
{
|
|
||||||
temp1 = (si->overlay.ow.h_start - crtc_hstart) & 0x7ff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
moi->hcoordv |= temp1 << 16;
|
|
||||||
/* right edge coordinate of output window, must be inside desktop */
|
|
||||||
/* width < 2 is not allowed */
|
|
||||||
if (si->overlay.ow.width < 2)
|
|
||||||
{
|
|
||||||
temp2 = (temp1 + 1) & 0x7ff;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* clipping on the right side */
|
|
||||||
if ((si->overlay.ow.h_start + si->overlay.ow.width - 1) > (crtc_hend - 1))
|
|
||||||
{
|
|
||||||
temp2 = (crtc_hend - crtc_hstart - 1) & 0x7ff;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* clipping on the left side */
|
|
||||||
if ((si->overlay.ow.h_start + si->overlay.ow.width - 1) < (crtc_hstart + 1))
|
|
||||||
{
|
|
||||||
/* width < 2 is not allowed */
|
|
||||||
temp2 = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* no clipping here */
|
|
||||||
{
|
|
||||||
temp2 = ((uint16)(si->overlay.ow.h_start + si->overlay.ow.width - crtc_hstart - 1)) & 0x7ff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
moi->hcoordv |= temp2 << 0;
|
|
||||||
LOG(4,("Overlay: CRTC left-edge output %d, right-edge output %d\n",temp1, temp2));
|
|
||||||
|
|
||||||
/* setup top and bottom edges of output window */
|
|
||||||
moi->vcoordv = 0;
|
|
||||||
/* top edge coordinate of output window, must be inside desktop */
|
|
||||||
/* clipping on the top side */
|
|
||||||
if (si->overlay.ow.v_start < crtc_vstart)
|
|
||||||
{
|
|
||||||
temp1 = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* clipping on the bottom side */
|
|
||||||
if (si->overlay.ow.v_start >= (crtc_vend - 1))
|
|
||||||
{
|
|
||||||
/* height < 2 is not allowed */
|
|
||||||
temp1 = (crtc_vend - crtc_vstart - 2) & 0x7ff;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* no clipping here */
|
|
||||||
{
|
|
||||||
temp1 = (si->overlay.ow.v_start - crtc_vstart) & 0x7ff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
moi->vcoordv |= temp1 << 16;
|
|
||||||
/* bottom edge coordinate of output window, must be inside desktop */
|
|
||||||
/* height < 2 is not allowed */
|
|
||||||
if (si->overlay.ow.height < 2)
|
|
||||||
{
|
|
||||||
temp2 = (temp1 + 1) & 0x7ff;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* clipping on the bottom side */
|
|
||||||
if ((si->overlay.ow.v_start + si->overlay.ow.height - 1) > (crtc_vend - 1))
|
|
||||||
{
|
|
||||||
temp2 = (crtc_vend - crtc_vstart - 1) & 0x7ff;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* clipping on the top side */
|
|
||||||
if ((si->overlay.ow.v_start + si->overlay.ow.height - 1) < (crtc_vstart + 1))
|
|
||||||
{
|
|
||||||
/* height < 2 is not allowed */
|
|
||||||
temp2 = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* no clipping here */
|
|
||||||
{
|
|
||||||
temp2 = ((uint16)(si->overlay.ow.v_start + si->overlay.ow.height - crtc_vstart - 1)) & 0x7ff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
moi->vcoordv |= temp2 << 0;
|
|
||||||
LOG(4,("Overlay: CRTC top-edge output %d, bottom-edge output %d\n",temp1, temp2));
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************
|
|
||||||
*** setup horizontal clipping ***
|
|
||||||
*********************************/
|
|
||||||
|
|
||||||
/* Setup horizontal source start: first (sub)pixel contributing to output picture */
|
|
||||||
/* Note:
|
|
||||||
* The method is to calculate, based on 1:1 scaling, based on the output window.
|
|
||||||
* After this is done, include the scaling factor so you get a value based on the input bitmap.
|
|
||||||
* Then add the left starting position of the bitmap's view (zoom function) to get the final value needed.
|
|
||||||
* Note: The input bitmaps slopspace is automatically excluded from the calculations this way! */
|
|
||||||
/* Note also:
|
|
||||||
* Even if the scaling factor is clamping we instruct the BES to use the correct source start pos.! */
|
|
||||||
moi->hsrcstv = 0;
|
|
||||||
/* check for destination horizontal clipping at left side */
|
|
||||||
if (si->overlay.ow.h_start < crtc_hstart)
|
|
||||||
{
|
|
||||||
/* check if entire destination picture is clipping left:
|
|
||||||
* (2 pixels will be clamped onscreen at least) */
|
|
||||||
if ((si->overlay.ow.h_start + si->overlay.ow.width - 1) < (crtc_hstart + 1))
|
|
||||||
{
|
|
||||||
/* increase 'first contributing pixel' with 'fixed value': (total dest. width - 2) */
|
|
||||||
moi->hsrcstv += (si->overlay.ow.width - 2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* increase 'first contributing pixel' with actual number of dest. clipping pixels */
|
|
||||||
moi->hsrcstv += (crtc_hstart - si->overlay.ow.h_start);
|
|
||||||
}
|
|
||||||
LOG(4,("Overlay: clipping left...\n"));
|
|
||||||
|
|
||||||
/* The calculated value is based on scaling = 1x. So we now compensate for scaling.
|
|
||||||
* Note that this also already takes care of aligning the value to the BES register! */
|
|
||||||
moi->hsrcstv *= si->overlay.h_ifactor;
|
|
||||||
}
|
|
||||||
/* take zoom into account */
|
|
||||||
moi->hsrcstv += ((uint32)si->overlay.my_ov.h_start) << 16;
|
|
||||||
/* AND below required by hardware */
|
|
||||||
moi->hsrcstv &= 0x03fffffc;
|
|
||||||
LOG(4,("Overlay: first hor. (sub)pixel of input bitmap contributing %f\n", moi->hsrcstv / (float)65536));
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************
|
|
||||||
*** setup vertical clipping ***
|
|
||||||
*******************************/
|
|
||||||
|
|
||||||
/* calculate inputbitmap origin adress */
|
|
||||||
moi->a1orgv = (uint32)((vuint32 *)si->overlay.ob.buffer);
|
|
||||||
moi->a1orgv -= (uint32)((vuint32 *)si->framebuffer);
|
|
||||||
LOG(4,("Overlay: topleft corner of input bitmap (cardRAM offset) $%08x\n", moi->a1orgv));
|
|
||||||
|
|
||||||
/* Setup vertical source start: first (sub)pixel contributing to output picture. */
|
|
||||||
/* Note:
|
|
||||||
* The method is to calculate, based on 1:1 scaling, based on the output window.
|
|
||||||
* 'After' this is done, include the scaling factor so you get a value based on the input bitmap.
|
|
||||||
* Then add the top starting position of the bitmap's view (zoom function) to get the final value needed. */
|
|
||||||
/* Note also:
|
|
||||||
* Even if the scaling factor is clamping we instruct the BES to use the correct source start pos.! */
|
|
||||||
|
|
||||||
moi->v1srcstv = 0;
|
|
||||||
/* check for destination vertical clipping at top side */
|
|
||||||
if (si->overlay.ow.v_start < crtc_vstart)
|
|
||||||
{
|
|
||||||
/* check if entire destination picture is clipping at top:
|
|
||||||
* (2 pixels will be clamped onscreen at least) */
|
|
||||||
if ((si->overlay.ow.v_start + si->overlay.ow.height - 1) < (crtc_vstart + 1))
|
|
||||||
{
|
|
||||||
/* increase 'number of clipping pixels' with 'fixed value':
|
|
||||||
* 'total height - 2' of dest. picture in pixels * inverse scaling factor */
|
|
||||||
moi->v1srcstv = (si->overlay.ow.height - 2) * si->overlay.v_ifactor;
|
|
||||||
/* on pre-NV10 we need to do clipping in the source
|
|
||||||
* bitmap because no seperate clipping registers exist... */
|
|
||||||
if (si->ps.card_arch < NV10A)
|
|
||||||
moi->a1orgv += ((moi->v1srcstv >> 16) * si->overlay.ob.bytes_per_row);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* increase 'first contributing pixel' with:
|
|
||||||
* number of destination picture clipping pixels * inverse scaling factor */
|
|
||||||
moi->v1srcstv = (crtc_vstart - si->overlay.ow.v_start) * si->overlay.v_ifactor;
|
|
||||||
/* on pre-NV10 we need to do clipping in the source
|
|
||||||
* bitmap because no seperate clipping registers exist... */
|
|
||||||
if (si->ps.card_arch < NV10A)
|
|
||||||
moi->a1orgv += ((moi->v1srcstv >> 16) * si->overlay.ob.bytes_per_row);
|
|
||||||
}
|
|
||||||
LOG(4,("Overlay: clipping at top...\n"));
|
|
||||||
}
|
|
||||||
/* take zoom into account */
|
|
||||||
moi->v1srcstv += (((uint32)si->overlay.my_ov.v_start) << 16);
|
|
||||||
if (si->ps.card_arch < NV10A)
|
|
||||||
{
|
|
||||||
moi->a1orgv += (si->overlay.my_ov.v_start * si->overlay.ob.bytes_per_row);
|
|
||||||
LOG(4,("Overlay: 'contributing part of buffer' origin is (cardRAM offset) $%08x\n", moi->a1orgv));
|
|
||||||
}
|
|
||||||
LOG(4,("Overlay: first vert. (sub)pixel of input bitmap contributing %f\n", moi->v1srcstv / (float)65536));
|
|
||||||
|
|
||||||
/* AND below is probably required by hardware. */
|
|
||||||
/* Buffer A topleft corner of field 1 (origin)(field 1 contains our full frames) */
|
|
||||||
moi->a1orgv &= 0xfffffff0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nv_bes_program_move_overlay(move_overlay_info moi)
|
|
||||||
{
|
|
||||||
/*************************************
|
|
||||||
*** sync to BES (Back End Scaler) ***
|
|
||||||
*************************************/
|
|
||||||
|
|
||||||
/* Done in card hardware:
|
|
||||||
* double buffered registers + trigger if programming complete feature. */
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************
|
|
||||||
*** actually program the registers ***
|
|
||||||
**************************************/
|
|
||||||
|
|
||||||
if (si->ps.card_arch < NV10A)
|
|
||||||
{
|
|
||||||
/* unknown, but needed (otherwise high-res distortions and only half the frames */
|
|
||||||
BESW(NV04_OE_STATE, 0x00000000);
|
|
||||||
/* select buffer 0 as active (b16) */
|
|
||||||
BESW(NV04_SU_STATE, 0x00000000);
|
|
||||||
/* unknown (no effect?) */
|
|
||||||
BESW(NV04_RM_STATE, 0x00000000);
|
|
||||||
/* setup clipped(!) buffer startadress in RAM */
|
|
||||||
/* RIVA128 - TNT bes doesn't have clipping registers, so no subpixelprecise clipping
|
|
||||||
* either. We do pixelprecise vertical and 'two pixel' precise horizontal clipping here. */
|
|
||||||
/* (program both buffers to prevent sync distortions) */
|
|
||||||
/* first include 'pixel precise' left clipping... (top clipping was already included) */
|
|
||||||
moi.a1orgv += ((moi.hsrcstv >> 16) * 2);
|
|
||||||
/* we need to step in 4-byte (2 pixel) granularity due to the nature of yuy2 */
|
|
||||||
BESW(NV04_0BUFADR, (moi.a1orgv & ~0x03));
|
|
||||||
BESW(NV04_1BUFADR, (moi.a1orgv & ~0x03));
|
|
||||||
/* setup output window position */
|
|
||||||
BESW(NV04_DSTREF, ((moi.vcoordv & 0xffff0000) | ((moi.hcoordv & 0xffff0000) >> 16)));
|
|
||||||
/* setup output window size */
|
|
||||||
BESW(NV04_DSTSIZE, (
|
|
||||||
(((moi.vcoordv & 0x0000ffff) - ((moi.vcoordv & 0xffff0000) >> 16) + 1) << 16) |
|
|
||||||
((moi.hcoordv & 0x0000ffff) - ((moi.hcoordv & 0xffff0000) >> 16) + 1)
|
|
||||||
));
|
|
||||||
/* select buffer 1 as active (b16) */
|
|
||||||
BESW(NV04_SU_STATE, 0x00010000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* >= NV10A */
|
|
||||||
|
|
||||||
/* setup buffer origin: GeForce uses subpixel precise clipping on left and top! (12.4 values) */
|
|
||||||
BESW(NV10_0SRCREF, ((moi.v1srcstv << 4) & 0xffff0000) | ((moi.hsrcstv >> 12) & 0x0000ffff));
|
|
||||||
/* setup output window position */
|
|
||||||
BESW(NV10_0DSTREF, ((moi.vcoordv & 0xffff0000) | ((moi.hcoordv & 0xffff0000) >> 16)));
|
|
||||||
/* setup output window size */
|
|
||||||
BESW(NV10_0DSTSIZE, (
|
|
||||||
(((moi.vcoordv & 0x0000ffff) - ((moi.vcoordv & 0xffff0000) >> 16) + 1) << 16) |
|
|
||||||
((moi.hcoordv & 0x0000ffff) - ((moi.hcoordv & 0xffff0000) >> 16) + 1)
|
|
||||||
));
|
|
||||||
/* We only use buffer buffer 0: select it. (0x01 = buffer 0, 0x10 = buffer 1) */
|
|
||||||
/* This also triggers activation of programmed values (double buffered registers feature) */
|
|
||||||
BESW(NV10_BUFSEL, 0x00000001);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t nv_bes_to_crtc(bool crtc)
|
|
||||||
{
|
|
||||||
if (si->ps.secondary_head)
|
|
||||||
{
|
|
||||||
if (crtc)
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: switching overlay to CRTC2\n"));
|
|
||||||
/* switch overlay engine to CRTC2 */
|
|
||||||
NV_REG32(NV32_FUNCSEL) &= ~0x00001000;
|
|
||||||
NV_REG32(NV32_2FUNCSEL) |= 0x00001000;
|
|
||||||
si->overlay.crtc = !si->crtc_switch_mode;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(4,("Overlay: switching overlay to CRTC1\n"));
|
|
||||||
/* switch overlay engine to CRTC1 */
|
|
||||||
NV_REG32(NV32_2FUNCSEL) &= ~0x00001000;
|
|
||||||
NV_REG32(NV32_FUNCSEL) |= 0x00001000;
|
|
||||||
si->overlay.crtc = si->crtc_switch_mode;
|
|
||||||
}
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t nv_bes_init()
|
|
||||||
{
|
|
||||||
if (si->ps.card_arch < NV10A)
|
|
||||||
{
|
|
||||||
/* disable overlay ints (b0 = buffer 0, b4 = buffer 1) */
|
|
||||||
BESW(NV04_INTE, 0x00000000);
|
|
||||||
|
|
||||||
/* setup saturation to be 'neutral' */
|
|
||||||
BESW(NV04_SAT, 0x00000000);
|
|
||||||
/* setup RGB brightness to be 'neutral' */
|
|
||||||
BESW(NV04_RED_AMP, 0x00000069);
|
|
||||||
BESW(NV04_GRN_AMP, 0x0000003e);
|
|
||||||
BESW(NV04_BLU_AMP, 0x00000089);
|
|
||||||
|
|
||||||
/* setup fifo for fetching data */
|
|
||||||
BESW(NV04_FIFOBURL, 0x00000003);
|
|
||||||
BESW(NV04_FIFOTHRS, 0x00000038);
|
|
||||||
|
|
||||||
/* unknown, but needed (registers only have b0 implemented) */
|
|
||||||
/* (program both buffers to prevent sync distortions) */
|
|
||||||
BESW(NV04_0OFFSET, 0x00000000);
|
|
||||||
BESW(NV04_1OFFSET, 0x00000000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* >= NV10A */
|
|
||||||
|
|
||||||
/* disable overlay ints (b0 = buffer 0, b4 = buffer 1) */
|
|
||||||
BESW(NV10_INTE, 0x00000000);
|
|
||||||
/* shut off GeForce4MX MPEG2 decoder */
|
|
||||||
BESW(DEC_GENCTRL, 0x00000000);
|
|
||||||
/* setup BES memory-range mask */
|
|
||||||
BESW(NV10_0MEMMASK, (si->ps.memory_size - 1));
|
|
||||||
/* unknown, but needed */
|
|
||||||
BESW(NV10_0OFFSET, 0x00000000);
|
|
||||||
|
|
||||||
/* setup brightness, contrast and saturation to be 'neutral' */
|
|
||||||
BESW(NV10_0BRICON, ((0x1000 << 16) | 0x1000));
|
|
||||||
BESW(NV10_0SAT, ((0x0000 << 16) | 0x1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make sure the engine is disabled. */
|
|
||||||
nv_release_bes();
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t nv_configure_bes
|
|
||||||
(const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov, int offset)
|
|
||||||
{
|
|
||||||
/* yuy2 (4:2:2) colorspace calculations */
|
|
||||||
|
|
||||||
/* Note:
|
|
||||||
* in BeOS R5.0.3 and DANO:
|
|
||||||
* 'ow->offset_xxx' is always 0, so not used;
|
|
||||||
* 'ow->width' and 'ow->height' are the output window size: does not change
|
|
||||||
* if window is clipping;
|
|
||||||
* 'ow->h_start' and 'ow->v_start' are the left-top position of the output
|
|
||||||
* window. These values can be negative: this means the window is clipping
|
|
||||||
* at the left or the top of the display, respectively. */
|
|
||||||
|
|
||||||
/* 'ov' is the view in the source bitmap, so which part of the bitmap is actually
|
|
||||||
* displayed on screen. This is used for the 'hardware zoom' function. */
|
|
||||||
|
|
||||||
/* output window position and clipping info for source buffer */
|
|
||||||
move_overlay_info moi;
|
|
||||||
/* calculated BES register values */
|
|
||||||
uint32 hiscalv, viscalv;
|
|
||||||
/* interval representation, used for scaling calculations */
|
|
||||||
uint16 intrep;
|
|
||||||
/* inverse scaling factor, used for source positioning */
|
|
||||||
uint32 ifactor;
|
|
||||||
/* copy of overlay view which has checked valid values */
|
|
||||||
overlay_view my_ov;
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************************
|
|
||||||
*** copy, check and limit if needed the user-specified view into the intput bitmap ***
|
|
||||||
**************************************************************************************/
|
|
||||||
my_ov = *ov;
|
|
||||||
/* check for valid 'coordinates' */
|
|
||||||
if (my_ov.width == 0) my_ov.width++;
|
|
||||||
if (my_ov.height == 0) my_ov.height++;
|
|
||||||
if (my_ov.h_start > ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1))
|
|
||||||
my_ov.h_start = ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1);
|
|
||||||
if (((my_ov.h_start + my_ov.width) - 1) > ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1))
|
|
||||||
my_ov.width = ((((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1) - my_ov.h_start) + 1);
|
|
||||||
if (my_ov.v_start > (ob->height - 1))
|
|
||||||
my_ov.v_start = (ob->height - 1);
|
|
||||||
if (((my_ov.v_start + my_ov.height) - 1) > (ob->height - 1))
|
|
||||||
my_ov.height = (((ob->height - 1) - my_ov.v_start) + 1);
|
|
||||||
|
|
||||||
LOG(4,("Overlay: inputbuffer view (zoom) left %d, top %d, width %d, height %d\n",
|
|
||||||
my_ov.h_start, my_ov.v_start, my_ov.width, my_ov.height));
|
|
||||||
|
|
||||||
/* save for nv_bes_calc_move_overlay() */
|
|
||||||
si->overlay.ow = *ow;
|
|
||||||
si->overlay.ob = *ob;
|
|
||||||
si->overlay.my_ov = my_ov;
|
|
||||||
|
|
||||||
|
|
||||||
/********************************
|
|
||||||
*** setup horizontal scaling ***
|
|
||||||
********************************/
|
|
||||||
LOG(4,("Overlay: total input picture width = %d, height = %d\n",
|
|
||||||
(ob->width - si->overlay.myBufInfo[offset].slopspace), ob->height));
|
|
||||||
LOG(4,("Overlay: output picture width = %d, height = %d\n", ow->width, ow->height));
|
|
||||||
|
|
||||||
/* determine interval representation value, taking zoom into account */
|
|
||||||
if (ow->flags & B_OVERLAY_HORIZONTAL_FILTERING)
|
|
||||||
{
|
|
||||||
/* horizontal filtering is ON */
|
|
||||||
if ((my_ov.width == ow->width) | (ow->width < 2))
|
|
||||||
{
|
|
||||||
/* no horizontal scaling used, OR destination width < 2 */
|
|
||||||
intrep = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
intrep = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* horizontal filtering is OFF */
|
|
||||||
if ((ow->width < my_ov.width) & (ow->width >= 2))
|
|
||||||
{
|
|
||||||
/* horizontal downscaling used AND destination width >= 2 */
|
|
||||||
intrep = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
intrep = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG(4,("Overlay: horizontal interval representation value is %d\n",intrep));
|
|
||||||
|
|
||||||
/* calculate inverse horizontal scaling factor, taking zoom into account */
|
|
||||||
/* standard scaling formula: */
|
|
||||||
ifactor = (((uint32)(my_ov.width - intrep)) << 16) / (ow->width - intrep);
|
|
||||||
|
|
||||||
/* correct factor to prevent most-right visible 'line' from distorting */
|
|
||||||
ifactor -= (1 << 2);
|
|
||||||
hiscalv = ifactor;
|
|
||||||
/* save for nv_bes_calc_move_overlay() */
|
|
||||||
si->overlay.h_ifactor = ifactor;
|
|
||||||
LOG(4,("Overlay: horizontal scaling factor is %f\n", (float)65536 / ifactor));
|
|
||||||
|
|
||||||
/* check scaling factor (and modify if needed) to be within scaling limits */
|
|
||||||
/* all cards have a upscaling limit of 8.0 (see official nVidia specsheets) */
|
|
||||||
if (hiscalv < 0x00002000)
|
|
||||||
{
|
|
||||||
/* (non-inverse) factor too large, set factor to max. valid value */
|
|
||||||
hiscalv = 0x00002000;
|
|
||||||
LOG(4,("Overlay: horizontal scaling factor too large, clamping at %f\n", (float)65536 / hiscalv));
|
|
||||||
}
|
|
||||||
switch (si->ps.card_arch)
|
|
||||||
{
|
|
||||||
case NV04A:
|
|
||||||
/* Riva128-TNT2 series have a 'downscaling' limit of 1.000489
|
|
||||||
* (16bit register with 0.11 format value) */
|
|
||||||
if (hiscalv > 0x0000ffff)
|
|
||||||
{
|
|
||||||
/* (non-inverse) factor too small, set factor to min. valid value */
|
|
||||||
hiscalv = 0x0000ffff;
|
|
||||||
LOG(4,("Overlay: horizontal scaling factor too small, clamping at %f\n", (float)2048 / (hiscalv >> 5)));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NV30A:
|
|
||||||
case NV40A:
|
|
||||||
/* GeForceFX series and up have a downscaling limit of 0.5 (except NV31!) */
|
|
||||||
if ((hiscalv > (2 << 16)) && (si->ps.card_type != NV31))
|
|
||||||
{
|
|
||||||
/* (non-inverse) factor too small, set factor to min. valid value */
|
|
||||||
hiscalv = (2 << 16);
|
|
||||||
LOG(4,("Overlay: horizontal scaling factor too small, clamping at %f\n", (float)65536 / hiscalv));
|
|
||||||
}
|
|
||||||
/* NV31 (confirmed GeForceFX 5600) has NV20A scaling limits!
|
|
||||||
* So let it fall through... */
|
|
||||||
if (si->ps.card_type != NV31) break;
|
|
||||||
default:
|
|
||||||
/* the rest has a downscaling limit of 0.125 */
|
|
||||||
if (hiscalv > (8 << 16))
|
|
||||||
{
|
|
||||||
/* (non-inverse) factor too small, set factor to min. valid value */
|
|
||||||
hiscalv = (8 << 16);
|
|
||||||
LOG(4,("Overlay: horizontal scaling factor too small, clamping at %f\n", (float)65536 / hiscalv));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* AND below is required by hardware */
|
|
||||||
hiscalv &= 0x001ffffc;
|
|
||||||
|
|
||||||
|
|
||||||
/******************************
|
|
||||||
*** setup vertical scaling ***
|
|
||||||
******************************/
|
|
||||||
|
|
||||||
/* determine interval representation value, taking zoom into account */
|
|
||||||
if (ow->flags & B_OVERLAY_VERTICAL_FILTERING)
|
|
||||||
{
|
|
||||||
/* vertical filtering is ON */
|
|
||||||
if ((my_ov.height == ow->height) | (ow->height < 2))
|
|
||||||
{
|
|
||||||
/* no vertical scaling used, OR destination height < 2 */
|
|
||||||
intrep = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
intrep = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* vertical filtering is OFF */
|
|
||||||
if ((ow->height < my_ov.height) & (ow->height >= 2))
|
|
||||||
{
|
|
||||||
/* vertical downscaling used AND destination height >= 2 */
|
|
||||||
intrep = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
intrep = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG(4,("Overlay: vertical interval representation value is %d\n",intrep));
|
|
||||||
|
|
||||||
/* calculate inverse vertical scaling factor, taking zoom into account */
|
|
||||||
/* standard scaling formula: */
|
|
||||||
ifactor = (((uint32)(my_ov.height - intrep)) << 16) / (ow->height - intrep);
|
|
||||||
|
|
||||||
/* correct factor to prevent lowest visible line from distorting */
|
|
||||||
ifactor -= (1 << 2);
|
|
||||||
LOG(4,("Overlay: vertical scaling factor is %f\n", (float)65536 / ifactor));
|
|
||||||
|
|
||||||
/* preserve ifactor for source positioning calculations later on */
|
|
||||||
viscalv = ifactor;
|
|
||||||
/* save for nv_bes_calc_move_overlay() */
|
|
||||||
si->overlay.v_ifactor = ifactor;
|
|
||||||
|
|
||||||
/* check scaling factor (and modify if needed) to be within scaling limits */
|
|
||||||
/* all cards have a upscaling limit of 8.0 (see official nVidia specsheets) */
|
|
||||||
if (viscalv < 0x00002000)
|
|
||||||
{
|
|
||||||
/* (non-inverse) factor too large, set factor to max. valid value */
|
|
||||||
viscalv = 0x00002000;
|
|
||||||
LOG(4,("Overlay: vertical scaling factor too large, clamping at %f\n", (float)65536 / viscalv));
|
|
||||||
}
|
|
||||||
switch (si->ps.card_arch)
|
|
||||||
{
|
|
||||||
case NV04A:
|
|
||||||
/* Riva128-TNT2 series have a 'downscaling' limit of 1.000489
|
|
||||||
* (16bit register with 0.11 format value) */
|
|
||||||
if (viscalv > 0x0000ffff)
|
|
||||||
{
|
|
||||||
/* (non-inverse) factor too small, set factor to min. valid value */
|
|
||||||
viscalv = 0x0000ffff;
|
|
||||||
LOG(4,("Overlay: vertical scaling factor too small, clamping at %f\n", (float)2048 / (viscalv >> 5)));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NV30A:
|
|
||||||
case NV40A:
|
|
||||||
/* GeForceFX series and up have a downscaling limit of 0.5 (except NV31!) */
|
|
||||||
if ((viscalv > (2 << 16)) && (si->ps.card_type != NV31))
|
|
||||||
{
|
|
||||||
/* (non-inverse) factor too small, set factor to min. valid value */
|
|
||||||
viscalv = (2 << 16);
|
|
||||||
LOG(4,("Overlay: vertical scaling factor too small, clamping at %f\n", (float)65536 / viscalv));
|
|
||||||
}
|
|
||||||
/* NV31 (confirmed GeForceFX 5600) has NV20A scaling limits!
|
|
||||||
* So let it fall through... */
|
|
||||||
if (si->ps.card_type != NV31) break;
|
|
||||||
default:
|
|
||||||
/* the rest has a downscaling limit of 0.125 */
|
|
||||||
if (viscalv > (8 << 16))
|
|
||||||
{
|
|
||||||
/* (non-inverse) factor too small, set factor to min. valid value */
|
|
||||||
viscalv = (8 << 16);
|
|
||||||
LOG(4,("Overlay: vertical scaling factor too small, clamping at %f\n", (float)65536 / viscalv));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* AND below is required by hardware */
|
|
||||||
viscalv &= 0x001ffffc;
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************************
|
|
||||||
*** setup all edges of output window, setup horizontal and vertical clipping ***
|
|
||||||
********************************************************************************/
|
|
||||||
nv_bes_calc_move_overlay(&moi);
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************
|
|
||||||
*** log color keying info ***
|
|
||||||
*****************************/
|
|
||||||
|
|
||||||
LOG(4,("Overlay: key_red %d, key_green %d, key_blue %d, key_alpha %d\n",
|
|
||||||
ow->red.value, ow->green.value, ow->blue.value, ow->alpha.value));
|
|
||||||
LOG(4,("Overlay: mask_red %d, mask_green %d, mask_blue %d, mask_alpha %d\n",
|
|
||||||
ow->red.mask, ow->green.mask, ow->blue.mask, ow->alpha.mask));
|
|
||||||
|
|
||||||
|
|
||||||
/*****************
|
|
||||||
*** log flags ***
|
|
||||||
*****************/
|
|
||||||
|
|
||||||
LOG(4,("Overlay: ow->flags is $%08x\n",ow->flags));
|
|
||||||
/* BTW: horizontal and vertical filtering are fixed and turned on for GeForce overlay. */
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************
|
|
||||||
*** sync to BES (Back End Scaler) ***
|
|
||||||
*************************************/
|
|
||||||
|
|
||||||
/* Done in card hardware:
|
|
||||||
* double buffered registers + trigger if programming complete feature. */
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************
|
|
||||||
*** actually program the registers ***
|
|
||||||
**************************************/
|
|
||||||
|
|
||||||
if (si->ps.card_arch < NV10A)
|
|
||||||
{
|
|
||||||
/* unknown, but needed (otherwise high-res distortions and only half the frames */
|
|
||||||
BESW(NV04_OE_STATE, 0x00000000);
|
|
||||||
/* select buffer 0 as active (b16) */
|
|
||||||
BESW(NV04_SU_STATE, 0x00000000);
|
|
||||||
/* unknown (no effect?) */
|
|
||||||
BESW(NV04_RM_STATE, 0x00000000);
|
|
||||||
/* setup clipped(!) buffer startadress in RAM */
|
|
||||||
/* RIVA128 - TNT bes doesn't have clipping registers, so no subpixelprecise clipping
|
|
||||||
* either. We do pixelprecise vertical and 'two pixel' precise horizontal clipping here. */
|
|
||||||
/* (program both buffers to prevent sync distortions) */
|
|
||||||
/* first include 'pixel precise' left clipping... (top clipping was already included) */
|
|
||||||
moi.a1orgv += ((moi.hsrcstv >> 16) * 2);
|
|
||||||
/* we need to step in 4-byte (2 pixel) granularity due to the nature of yuy2 */
|
|
||||||
BESW(NV04_0BUFADR, (moi.a1orgv & ~0x03));
|
|
||||||
BESW(NV04_1BUFADR, (moi.a1orgv & ~0x03));
|
|
||||||
/* setup buffer source pitch including slopspace (in bytes).
|
|
||||||
* Note:
|
|
||||||
* source pitch granularity = 16 pixels on the RIVA128 - TNT (so pre-NV10) bes */
|
|
||||||
/* (program both buffers to prevent sync distortions) */
|
|
||||||
BESW(NV04_0SRCPTCH, (ob->width * 2));
|
|
||||||
BESW(NV04_1SRCPTCH, (ob->width * 2));
|
|
||||||
/* setup output window position */
|
|
||||||
BESW(NV04_DSTREF, ((moi.vcoordv & 0xffff0000) | ((moi.hcoordv & 0xffff0000) >> 16)));
|
|
||||||
/* setup output window size */
|
|
||||||
BESW(NV04_DSTSIZE, (
|
|
||||||
(((moi.vcoordv & 0x0000ffff) - ((moi.vcoordv & 0xffff0000) >> 16) + 1) << 16) |
|
|
||||||
((moi.hcoordv & 0x0000ffff) - ((moi.hcoordv & 0xffff0000) >> 16) + 1)
|
|
||||||
));
|
|
||||||
/* setup horizontal and vertical scaling */
|
|
||||||
BESW(NV04_ISCALVH, (((viscalv << 16) >> 5) | (hiscalv >> 5)));
|
|
||||||
/* enable vertical filtering (b0) */
|
|
||||||
BESW(NV04_CTRL_V, 0x00000001);
|
|
||||||
/* enable horizontal filtering (no effect?) */
|
|
||||||
BESW(NV04_CTRL_H, 0x00000111);
|
|
||||||
/* enable BES (b0), set colorkeying (b4), format yuy2 (b8: 0 = ccir) */
|
|
||||||
if (ow->flags & B_OVERLAY_COLOR_KEY)
|
|
||||||
BESW(NV04_GENCTRL, 0x00000111);
|
|
||||||
else
|
|
||||||
BESW(NV04_GENCTRL, 0x00000101);
|
|
||||||
/* select buffer 1 as active (b16) */
|
|
||||||
BESW(NV04_SU_STATE, 0x00010000);
|
|
||||||
|
|
||||||
/**************************
|
|
||||||
*** setup color keying ***
|
|
||||||
**************************/
|
|
||||||
|
|
||||||
/* setup colorkeying */
|
|
||||||
switch(si->dm.space)
|
|
||||||
{
|
|
||||||
case B_RGB15_LITTLE:
|
|
||||||
BESW(NV04_COLKEY, (
|
|
||||||
((ow->blue.value & ow->blue.mask) << 0) |
|
|
||||||
((ow->green.value & ow->green.mask) << 5) |
|
|
||||||
((ow->red.value & ow->red.mask) << 10) |
|
|
||||||
((ow->alpha.value & ow->alpha.mask) << 15)
|
|
||||||
));
|
|
||||||
break;
|
|
||||||
case B_RGB16_LITTLE:
|
|
||||||
BESW(NV04_COLKEY, (
|
|
||||||
((ow->blue.value & ow->blue.mask) << 0) |
|
|
||||||
((ow->green.value & ow->green.mask) << 5) |
|
|
||||||
((ow->red.value & ow->red.mask) << 11)
|
|
||||||
/* this space has no alpha bits */
|
|
||||||
));
|
|
||||||
break;
|
|
||||||
case B_CMAP8:
|
|
||||||
case B_RGB32_LITTLE:
|
|
||||||
default:
|
|
||||||
BESW(NV04_COLKEY, (
|
|
||||||
((ow->blue.value & ow->blue.mask) << 0) |
|
|
||||||
((ow->green.value & ow->green.mask) << 8) |
|
|
||||||
((ow->red.value & ow->red.mask) << 16) |
|
|
||||||
((ow->alpha.value & ow->alpha.mask) << 24)
|
|
||||||
));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* >= NV10A */
|
|
||||||
|
|
||||||
/* setup buffer origin: GeForce uses subpixel precise clipping on left and top! (12.4 values) */
|
|
||||||
BESW(NV10_0SRCREF, ((moi.v1srcstv << 4) & 0xffff0000) | ((moi.hsrcstv >> 12) & 0x0000ffff));
|
|
||||||
/* setup buffersize */
|
|
||||||
//fixme if needed: width must be even officially...
|
|
||||||
BESW(NV10_0SRCSIZE, ((ob->height << 16) | ob->width));
|
|
||||||
/* setup source pitch including slopspace (in bytes),
|
|
||||||
* b16: select YUY2 (0 = YV12), b20: set colorkeying, b24: no iturbt_709 (do iturbt_601) */
|
|
||||||
/* Note:
|
|
||||||
* source pitch granularity = 32 pixels on GeForce cards!! */
|
|
||||||
if (ow->flags & B_OVERLAY_COLOR_KEY)
|
|
||||||
BESW(NV10_0SRCPTCH, (((ob->width * 2) & 0x0000ffff) | (1 << 16) | (1 << 20) | (0 << 24)));
|
|
||||||
else
|
|
||||||
BESW(NV10_0SRCPTCH, (((ob->width * 2) & 0x0000ffff) | (1 << 16) | (0 << 20) | (0 << 24)));
|
|
||||||
/* setup output window position */
|
|
||||||
BESW(NV10_0DSTREF, ((moi.vcoordv & 0xffff0000) | ((moi.hcoordv & 0xffff0000) >> 16)));
|
|
||||||
/* setup output window size */
|
|
||||||
BESW(NV10_0DSTSIZE, (
|
|
||||||
(((moi.vcoordv & 0x0000ffff) - ((moi.vcoordv & 0xffff0000) >> 16) + 1) << 16) |
|
|
||||||
((moi.hcoordv & 0x0000ffff) - ((moi.hcoordv & 0xffff0000) >> 16) + 1)
|
|
||||||
));
|
|
||||||
/* setup horizontal scaling */
|
|
||||||
BESW(NV10_0ISCALH, (hiscalv << 4));
|
|
||||||
/* setup vertical scaling */
|
|
||||||
BESW(NV10_0ISCALV, (viscalv << 4));
|
|
||||||
/* setup (unclipped!) buffer startadress in RAM */
|
|
||||||
BESW(NV10_0BUFADR, moi.a1orgv);
|
|
||||||
/* enable BES (b0 = 0) */
|
|
||||||
BESW(NV10_GENCTRL, 0x00000000);
|
|
||||||
/* We only use buffer buffer 0: select it. (0x01 = buffer 0, 0x10 = buffer 1) */
|
|
||||||
/* This also triggers activation of programmed values (double buffered registers feature) */
|
|
||||||
BESW(NV10_BUFSEL, 0x00000001);
|
|
||||||
|
|
||||||
/**************************
|
|
||||||
*** setup color keying ***
|
|
||||||
**************************/
|
|
||||||
|
|
||||||
/* setup colorkeying */
|
|
||||||
switch(si->dm.space)
|
|
||||||
{
|
|
||||||
case B_RGB15_LITTLE:
|
|
||||||
BESW(NV10_COLKEY, (
|
|
||||||
((ow->blue.value & ow->blue.mask) << 0) |
|
|
||||||
((ow->green.value & ow->green.mask) << 5) |
|
|
||||||
((ow->red.value & ow->red.mask) << 10) |
|
|
||||||
((ow->alpha.value & ow->alpha.mask) << 15)
|
|
||||||
));
|
|
||||||
break;
|
|
||||||
case B_RGB16_LITTLE:
|
|
||||||
BESW(NV10_COLKEY, (
|
|
||||||
((ow->blue.value & ow->blue.mask) << 0) |
|
|
||||||
((ow->green.value & ow->green.mask) << 5) |
|
|
||||||
((ow->red.value & ow->red.mask) << 11)
|
|
||||||
/* this space has no alpha bits */
|
|
||||||
));
|
|
||||||
break;
|
|
||||||
case B_CMAP8:
|
|
||||||
case B_RGB32_LITTLE:
|
|
||||||
default:
|
|
||||||
BESW(NV10_COLKEY, (
|
|
||||||
((ow->blue.value & ow->blue.mask) << 0) |
|
|
||||||
((ow->green.value & ow->green.mask) << 8) |
|
|
||||||
((ow->red.value & ow->red.mask) << 16) |
|
|
||||||
((ow->alpha.value & ow->alpha.mask) << 24)
|
|
||||||
));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* note that overlay is in use (for nv_bes_move_overlay()) */
|
|
||||||
si->overlay.active = true;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t nv_release_bes()
|
|
||||||
{
|
|
||||||
if (si->ps.card_arch < NV10A)
|
|
||||||
{
|
|
||||||
/* setup BES control: disable scaler (b0 = 0) */
|
|
||||||
BESW(NV04_GENCTRL, 0x00000000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* setup BES control: disable scaler (b0 = 1) */
|
|
||||||
BESW(NV10_GENCTRL, 0x00000001);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* note that overlay is not in use (for nv_bes_move_overlay()) */
|
|
||||||
si->overlay.active = false;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
@@ -268,18 +268,15 @@ status_t nv_crtc_set_timing(display_mode target)
|
|||||||
//| ((linecomp & 0x400) >> 3)
|
//| ((linecomp & 0x400) >> 3)
|
||||||
));
|
));
|
||||||
|
|
||||||
/* more vertical extended regs (on GeForce cards only) */
|
/* more vertical extended regs */
|
||||||
if (si->ps.card_arch >= NV10A)
|
CRTCW(EXTRA,
|
||||||
{
|
(
|
||||||
CRTCW(EXTRA,
|
((vtotal & 0x800) >> (11 - 0)) |
|
||||||
(
|
((vdisp_e & 0x800) >> (11 - 2)) |
|
||||||
((vtotal & 0x800) >> (11 - 0)) |
|
((vsync_s & 0x800) >> (11 - 4)) |
|
||||||
((vdisp_e & 0x800) >> (11 - 2)) |
|
((vblnk_s & 0x800) >> (11 - 6))
|
||||||
((vsync_s & 0x800) >> (11 - 4)) |
|
//fixme: do we miss another linecomp bit!?!
|
||||||
((vblnk_s & 0x800) >> (11 - 6))
|
));
|
||||||
//fixme: do we miss another linecomp bit!?!
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setup 'large screen' mode */
|
/* setup 'large screen' mode */
|
||||||
if (target.timing.h_display >= 1280)
|
if (target.timing.h_display >= 1280)
|
||||||
@@ -638,7 +635,6 @@ status_t nv_crtc_set_display_pitch()
|
|||||||
|
|
||||||
status_t nv_crtc_set_display_start(uint32 startadd,uint8 bpp)
|
status_t nv_crtc_set_display_start(uint32 startadd,uint8 bpp)
|
||||||
{
|
{
|
||||||
uint8 temp;
|
|
||||||
uint32 timeout = 0;
|
uint32 timeout = 0;
|
||||||
|
|
||||||
LOG(4,("CRTC: setting card RAM to be displayed bpp %d\n", bpp));
|
LOG(4,("CRTC: setting card RAM to be displayed bpp %d\n", bpp));
|
||||||
@@ -660,33 +656,13 @@ status_t nv_crtc_set_display_start(uint32 startadd,uint8 bpp)
|
|||||||
/* enable access to primary head */
|
/* enable access to primary head */
|
||||||
set_crtc_owner(0);
|
set_crtc_owner(0);
|
||||||
|
|
||||||
if (si->ps.card_arch == NV04A)
|
/* upto 4Gb RAM adressing: must be used on NV10 and later! */
|
||||||
{
|
/* NOTE:
|
||||||
/* upto 32Mb RAM adressing: must be used this way on pre-NV10! */
|
* While this register also exists on pre-NV10 cards, it will
|
||||||
|
* wrap-around at 16Mb boundaries!! */
|
||||||
|
|
||||||
/* set standard registers */
|
/* 30bit adress in 32bit words */
|
||||||
/* (NVidia: startadress in 32bit words (b2 - b17) */
|
NV_REG32(NV32_NV10FBSTADD32) = (startadd & 0xfffffffc);
|
||||||
CRTCW(FBSTADDL, ((startadd & 0x000003fc) >> 2));
|
|
||||||
CRTCW(FBSTADDH, ((startadd & 0x0003fc00) >> 10));
|
|
||||||
|
|
||||||
/* set extended registers */
|
|
||||||
/* NV4 extended bits: (b18-22) */
|
|
||||||
temp = (CRTCR(REPAINT0) & 0xe0);
|
|
||||||
CRTCW(REPAINT0, (temp | ((startadd & 0x007c0000) >> 18)));
|
|
||||||
/* NV4 extended bits: (b23-24) */
|
|
||||||
temp = (CRTCR(HEB) & 0x9f);
|
|
||||||
CRTCW(HEB, (temp | ((startadd & 0x01800000) >> 18)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* upto 4Gb RAM adressing: must be used on NV10 and later! */
|
|
||||||
/* NOTE:
|
|
||||||
* While this register also exists on pre-NV10 cards, it will
|
|
||||||
* wrap-around at 16Mb boundaries!! */
|
|
||||||
|
|
||||||
/* 30bit adress in 32bit words */
|
|
||||||
NV_REG32(NV32_NV10FBSTADD32) = (startadd & 0xfffffffc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set NV4/NV10 byte adress: (b0 - 1) */
|
/* set NV4/NV10 byte adress: (b0 - 1) */
|
||||||
ATBW(HORPIXPAN, ((startadd & 0x00000003) << 1));
|
ATBW(HORPIXPAN, ((startadd & 0x00000003) << 1));
|
||||||
@@ -705,9 +681,9 @@ status_t nv_crtc_cursor_init()
|
|||||||
set_crtc_owner(0);
|
set_crtc_owner(0);
|
||||||
|
|
||||||
/* set cursor bitmap adress ... */
|
/* set cursor bitmap adress ... */
|
||||||
if ((si->ps.card_arch == NV04A) || (si->ps.laptop))
|
if (si->ps.laptop)
|
||||||
{
|
{
|
||||||
/* must be used this way on pre-NV10 and on all 'Go' cards! */
|
/* must be used this way on all 'Go' cards! */
|
||||||
|
|
||||||
/* cursorbitmap must start on 2Kbyte boundary: */
|
/* cursorbitmap must start on 2Kbyte boundary: */
|
||||||
/* set adress bit11-16, and set 'no doublescan' (registerbit 1 = 0) */
|
/* set adress bit11-16, and set 'no doublescan' (registerbit 1 = 0) */
|
||||||
@@ -740,10 +716,8 @@ status_t nv_crtc_cursor_init()
|
|||||||
/* select 32x32 pixel, 16bit color cursorbitmap, no doublescan */
|
/* select 32x32 pixel, 16bit color cursorbitmap, no doublescan */
|
||||||
NV_REG32(NV32_CURCONF) = 0x02000100;
|
NV_REG32(NV32_CURCONF) = 0x02000100;
|
||||||
|
|
||||||
/* activate hardware-sync between cursor updates and vertical retrace where
|
/* activate hardware-sync between cursor updates and vertical retrace */
|
||||||
* available */
|
DACW(NV10_CURSYNC, (DACR(NV10_CURSYNC) | 0x02000000));
|
||||||
if (si->ps.card_arch >= NV10A)
|
|
||||||
DACW(NV10_CURSYNC, (DACR(NV10_CURSYNC) | 0x02000000));
|
|
||||||
|
|
||||||
/* activate hardware cursor */
|
/* activate hardware cursor */
|
||||||
nv_crtc_cursor_show();
|
nv_crtc_cursor_show();
|
||||||
@@ -844,51 +818,7 @@ status_t nv_crtc_cursor_define(uint8* andMask,uint8* xorMask)
|
|||||||
/* position the cursor */
|
/* position the cursor */
|
||||||
status_t nv_crtc_cursor_position(uint16 x, uint16 y)
|
status_t nv_crtc_cursor_position(uint16 x, uint16 y)
|
||||||
{
|
{
|
||||||
/* the cursor position is updated during retrace by card hardware except for
|
/* the cursor position is updated during retrace by card hardware */
|
||||||
* pre-GeForce cards */
|
|
||||||
if (si->ps.card_arch < NV10A)
|
|
||||||
{
|
|
||||||
uint16 yhigh;
|
|
||||||
uint32 timeout = 0;
|
|
||||||
|
|
||||||
/* make sure we are beyond the first line of the cursorbitmap being drawn during
|
|
||||||
* updating the position to prevent distortions: no double buffering feature */
|
|
||||||
/* Note:
|
|
||||||
* we need to return as quick as possible or some apps will exhibit lagging.. */
|
|
||||||
|
|
||||||
/* read the old cursor Y position */
|
|
||||||
yhigh = ((DACR(CURPOS) & 0x0fff0000) >> 16);
|
|
||||||
/* make sure we will wait until we are below both the old and new Y position:
|
|
||||||
* visible cursorbitmap drawing needs to be done at least... */
|
|
||||||
if (y > yhigh) yhigh = y;
|
|
||||||
|
|
||||||
if (yhigh < (si->dm.timing.v_display - 16))
|
|
||||||
{
|
|
||||||
/* we have vertical lines below old and new cursorposition to spare. So we
|
|
||||||
* update the cursor postion 'mid-screen', but below that area. */
|
|
||||||
/* wait 25mS max. (refresh > 40Hz) */
|
|
||||||
while ((((uint16)(NV_REG32(NV32_RASTER) & 0x000007ff)) < (yhigh + 16)) &&
|
|
||||||
(timeout < (25000/10)))
|
|
||||||
{
|
|
||||||
snooze(10);
|
|
||||||
timeout++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
timeout = 0;
|
|
||||||
/* no room to spare, just wait for retrace (is relatively slow) */
|
|
||||||
/* wait 25mS max. (refresh > 40Hz) */
|
|
||||||
while (((NV_REG32(NV32_RASTER) & 0x000007ff) < si->dm.timing.v_display) &&
|
|
||||||
(timeout < (25000/10)))
|
|
||||||
{
|
|
||||||
/* don't snooze much longer or retrace might get missed! */
|
|
||||||
snooze(10);
|
|
||||||
timeout++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update cursorposition */
|
/* update cursorposition */
|
||||||
DACW(CURPOS, ((x & 0x0fff) | ((y & 0x0fff) << 16)));
|
DACW(CURPOS, ((x & 0x0fff) | ((y & 0x0fff) << 16)));
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* program the DAC */
|
/* program the DAC */
|
||||||
/* Author:
|
/* Author:
|
||||||
Rudolf Cornelissen 12/2003-10/2004
|
Rudolf Cornelissen 12/2003-6/2008
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MODULE_BIT 0x00010000
|
#define MODULE_BIT 0x00010000
|
||||||
@@ -315,15 +315,7 @@ static status_t nv4_nv10_nv20_dac_pix_pll_find(
|
|||||||
for (m = 7; m <= 14; m++)
|
for (m = 7; m <= 14; m++)
|
||||||
{
|
{
|
||||||
/* check if phase-discriminator will be within operational limits */
|
/* check if phase-discriminator will be within operational limits */
|
||||||
//fixme: PLL calcs will be resetup/splitup/updated...
|
if (((si->ps.f_ref / m) < 1.0) || ((si->ps.f_ref / m) > 2.0)) continue;
|
||||||
if (si->ps.card_type == NV36)
|
|
||||||
{
|
|
||||||
if (((si->ps.f_ref / m) < 3.2) || ((si->ps.f_ref / m) > 6.4)) continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (((si->ps.f_ref / m) < 1.0) || ((si->ps.f_ref / m) > 2.0)) continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* calculate VCO postscaler setting for current setup.. */
|
/* calculate VCO postscaler setting for current setup.. */
|
||||||
n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5);
|
n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5);
|
||||||
@@ -406,58 +398,20 @@ status_t nv_dac_sys_pll_find(
|
|||||||
|
|
||||||
/* determine the max. reference-frequency postscaler setting for the
|
/* determine the max. reference-frequency postscaler setting for the
|
||||||
* current requested clock */
|
* current requested clock */
|
||||||
switch (si->ps.card_arch)
|
LOG(4,("DAC: NV10/NV20/NV30 restrictions apply\n"));
|
||||||
{
|
/* set max. useable reference frequency postscaler divider factor;
|
||||||
case NV04A:
|
* apparantly we would get distortions on high PLL output frequencies if
|
||||||
LOG(4,("DAC: NV04 restrictions apply\n"));
|
* we use the phase-discriminator at low frequencies */
|
||||||
/* set phase-discriminator frequency range (Mhz) (verified) */
|
if (req_sclk > 340.0) m_max = 2; /* Fpll > 340Mhz */
|
||||||
discr_low = 1.0;
|
else if (req_sclk > 250.0) m_max = 6; /* 250Mhz < Fpll <= 340Mhz */
|
||||||
discr_high = 2.0;
|
else m_max = 14; /* Fpll < 250Mhz */
|
||||||
/* set max. useable reference frequency postscaler divider factor */
|
|
||||||
m_max = 14;
|
|
||||||
/* set max. useable VCO output postscaler divider factor */
|
|
||||||
p_max = 16;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
switch (si->ps.card_type)
|
|
||||||
{
|
|
||||||
case NV28:
|
|
||||||
//fixme: how about some other cards???
|
|
||||||
LOG(4,("DAC: NV28 restrictions apply\n"));
|
|
||||||
/* set max. useable reference frequency postscaler divider factor;
|
|
||||||
* apparantly we would get distortions on high PLL output frequencies if
|
|
||||||
* we use the phase-discriminator at low frequencies */
|
|
||||||
if (req_sclk > 340.0) m_max = 2; /* Fpll > 340Mhz */
|
|
||||||
else if (req_sclk > 200.0) m_max = 4; /* 200Mhz < Fpll <= 340Mhz */
|
|
||||||
else if (req_sclk > 150.0) m_max = 6; /* 150Mhz < Fpll <= 200Mhz */
|
|
||||||
else m_max = 14; /* Fpll < 150Mhz */
|
|
||||||
|
|
||||||
/* set max. useable VCO output postscaler divider factor */
|
/* set max. useable VCO output postscaler divider factor */
|
||||||
p_max = 32;
|
p_max = 16;
|
||||||
/* set phase-discriminator frequency range (Mhz) (verified) */
|
/* set phase-discriminator frequency range (Mhz) (verified) */
|
||||||
discr_low = 1.0;
|
discr_low = 1.0;
|
||||||
discr_high = 27.0;
|
/* (high discriminator spec is failsafe) */
|
||||||
break;
|
discr_high = 14.0;
|
||||||
default:
|
|
||||||
LOG(4,("DAC: NV10/NV20/NV30 restrictions apply\n"));
|
|
||||||
/* set max. useable reference frequency postscaler divider factor;
|
|
||||||
* apparantly we would get distortions on high PLL output frequencies if
|
|
||||||
* we use the phase-discriminator at low frequencies */
|
|
||||||
if (req_sclk > 340.0) m_max = 2; /* Fpll > 340Mhz */
|
|
||||||
else if (req_sclk > 250.0) m_max = 6; /* 250Mhz < Fpll <= 340Mhz */
|
|
||||||
else m_max = 14; /* Fpll < 250Mhz */
|
|
||||||
|
|
||||||
/* set max. useable VCO output postscaler divider factor */
|
|
||||||
p_max = 16;
|
|
||||||
/* set phase-discriminator frequency range (Mhz) (verified) */
|
|
||||||
if (si->ps.card_type == NV36) discr_low = 3.2;
|
|
||||||
else discr_low = 1.0;
|
|
||||||
/* (high discriminator spec is failsafe) */
|
|
||||||
discr_high = 14.0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(4,("DAC: PLL reference frequency postscaler divider range is 1 - %d\n", m_max));
|
LOG(4,("DAC: PLL reference frequency postscaler divider range is 1 - %d\n", m_max));
|
||||||
LOG(4,("DAC: PLL VCO output postscaler divider range is 1 - %d\n", p_max));
|
LOG(4,("DAC: PLL VCO output postscaler divider range is 1 - %d\n", p_max));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* program the secondary DAC */
|
/* program the secondary DAC */
|
||||||
/* Author:
|
/* Author:
|
||||||
Rudolf Cornelissen 12/2003-9/2004
|
Rudolf Cornelissen 12/2003-6/2008
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MODULE_BIT 0x00001000
|
#define MODULE_BIT 0x00001000
|
||||||
@@ -312,15 +312,7 @@ static status_t nv10_nv20_dac2_pix_pll_find(
|
|||||||
for (m = 7; m <= 14; m++)
|
for (m = 7; m <= 14; m++)
|
||||||
{
|
{
|
||||||
/* check if phase-discriminator will be within operational limits */
|
/* check if phase-discriminator will be within operational limits */
|
||||||
//fixme: PLL calcs will be resetup/splitup/updated...
|
if (((si->ps.f_ref / m) < 1.0) || ((si->ps.f_ref / m) > 2.0)) continue;
|
||||||
if (si->ps.card_type == NV36)
|
|
||||||
{
|
|
||||||
if (((si->ps.f_ref / m) < 3.2) || ((si->ps.f_ref / m) > 6.4)) continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (((si->ps.f_ref / m) < 1.0) || ((si->ps.f_ref / m) > 2.0)) continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* calculate VCO postscaler setting for current setup.. */
|
/* calculate VCO postscaler setting for current setup.. */
|
||||||
n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5);
|
n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5);
|
||||||
|
|||||||
@@ -531,7 +531,6 @@ return B_OK;
|
|||||||
NV_REG32(NV32_2FUNCSEL) &= ~0x00001100;
|
NV_REG32(NV32_2FUNCSEL) &= ~0x00001100;
|
||||||
NV_REG32(NV32_FUNCSEL) |= 0x00001100;
|
NV_REG32(NV32_FUNCSEL) |= 0x00001100;
|
||||||
}
|
}
|
||||||
si->overlay.crtc = false;
|
|
||||||
|
|
||||||
/* enable 'enhanced' mode on primary head: */
|
/* enable 'enhanced' mode on primary head: */
|
||||||
/* enable access to primary head */
|
/* enable access to primary head */
|
||||||
@@ -668,45 +667,22 @@ status_t nv_general_validate_pic_size (display_mode *target, uint32 *bytes_per_r
|
|||||||
/* note:
|
/* note:
|
||||||
* because of the seemingly 'random' variations in these constraints we take
|
* because of the seemingly 'random' variations in these constraints we take
|
||||||
* a reasonable 'lowest common denominator' instead of always true constraints. */
|
* a reasonable 'lowest common denominator' instead of always true constraints. */
|
||||||
switch (si->ps.card_arch)
|
|
||||||
|
/* confirmed for:
|
||||||
|
* GeForce4 Ti4200 (NV28), GeForceFX 5600 (NV31) in PIO acc mode;
|
||||||
|
* confirmed for:
|
||||||
|
* GeForce2 MX400 (NV11), GeForce4 MX440 (NV18), GeForcePCX 5750 (NV36),
|
||||||
|
* GeForcePCX 6600 GT (NV43) in DMA acc mode. */
|
||||||
|
switch (target->space)
|
||||||
{
|
{
|
||||||
case NV04A:
|
case B_CMAP8: acc_mask = 0x3f; depth = 8; break;
|
||||||
/* confirmed for:
|
case B_RGB15: acc_mask = 0x1f; depth = 16; break;
|
||||||
* TNT1 (NV04), TNT2 (NV05), TNT2-M64 (NV05M64), GeForce2 MX400 (NV11),
|
case B_RGB16: acc_mask = 0x1f; depth = 16; break;
|
||||||
* GeForce4 MX440 (NV18), GeForceFX 5200 (NV34) in PIO acc mode;
|
case B_RGB24: acc_mask = 0x3f; depth = 24; break;
|
||||||
* confirmed for:
|
case B_RGB32: acc_mask = 0x0f; depth = 32; break;
|
||||||
* TNT1 (NV04), TNT2 (NV05), TNT2-M64 (NV05M64), GeForce4 Ti4200 (NV28),
|
default:
|
||||||
* GeForceFX 5200 (NV34) in DMA acc mode. */
|
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
|
||||||
switch (target->space)
|
return B_ERROR;
|
||||||
{
|
|
||||||
case B_CMAP8: acc_mask = 0x0f; depth = 8; break;
|
|
||||||
case B_RGB15: acc_mask = 0x07; depth = 16; break;
|
|
||||||
case B_RGB16: acc_mask = 0x07; depth = 16; break;
|
|
||||||
case B_RGB24: acc_mask = 0x0f; depth = 24; break;
|
|
||||||
case B_RGB32: acc_mask = 0x03; depth = 32; break;
|
|
||||||
default:
|
|
||||||
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* confirmed for:
|
|
||||||
* GeForce4 Ti4200 (NV28), GeForceFX 5600 (NV31) in PIO acc mode;
|
|
||||||
* confirmed for:
|
|
||||||
* GeForce2 MX400 (NV11), GeForce4 MX440 (NV18), GeForcePCX 5750 (NV36),
|
|
||||||
* GeForcePCX 6600 GT (NV43) in DMA acc mode. */
|
|
||||||
switch (target->space)
|
|
||||||
{
|
|
||||||
case B_CMAP8: acc_mask = 0x3f; depth = 8; break;
|
|
||||||
case B_RGB15: acc_mask = 0x1f; depth = 16; break;
|
|
||||||
case B_RGB16: acc_mask = 0x1f; depth = 16; break;
|
|
||||||
case B_RGB24: acc_mask = 0x3f; depth = 24; break;
|
|
||||||
case B_RGB32: acc_mask = 0x0f; depth = 32; break;
|
|
||||||
default:
|
|
||||||
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* determine pixel multiple based on CRTC memory pitch constraints:
|
/* determine pixel multiple based on CRTC memory pitch constraints:
|
||||||
@@ -764,45 +740,26 @@ status_t nv_general_validate_pic_size (display_mode *target, uint32 *bytes_per_r
|
|||||||
/* note:
|
/* note:
|
||||||
* because of the seemingly 'random' variations in these constraints we take
|
* because of the seemingly 'random' variations in these constraints we take
|
||||||
* a reasonable 'lowest common denominator' instead of always true constraints. */
|
* a reasonable 'lowest common denominator' instead of always true constraints. */
|
||||||
switch (si->ps.card_arch)
|
|
||||||
|
/* confirmed for:
|
||||||
|
* GeForce4 Ti4200 (NV28), GeForceFX 5600 (NV31) in PIO acc mode;
|
||||||
|
* GeForce2 MX400 (NV11), GeForce4 MX440 (NV18), GeForceFX 5200 (NV34) can do
|
||||||
|
* 16368/8184/8184/5456/4092, so a bit better in PIO acc mode;
|
||||||
|
* confirmed for:
|
||||||
|
* GeForce2 MX400 (NV11), GeForce4 MX440 (NV18), GeForcePCX 5750 (NV36),
|
||||||
|
* GeForcePCX 6600 GT (NV43) in DMA acc mode;
|
||||||
|
* GeForce4 Ti4200 (NV28), GeForceFX 5200 (NV34) can do
|
||||||
|
* 16368/8184/8184/5456/4092, so a bit better in DMA acc mode. */
|
||||||
|
switch(target->space)
|
||||||
{
|
{
|
||||||
case NV04A:
|
case B_CMAP8: max_acc_width = 16320; break;
|
||||||
/* confirmed for:
|
case B_RGB15: max_acc_width = 8160; break;
|
||||||
* TNT1 (NV04), TNT2 (NV05), TNT2-M64 (NV05M64) in both PIO and DMA acc mode. */
|
case B_RGB16: max_acc_width = 8160; break;
|
||||||
switch(target->space)
|
case B_RGB24: max_acc_width = 5440; break;
|
||||||
{
|
case B_RGB32: max_acc_width = 4080; break;
|
||||||
case B_CMAP8: max_acc_width = 8176; break;
|
default:
|
||||||
case B_RGB15: max_acc_width = 4088; break;
|
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
|
||||||
case B_RGB16: max_acc_width = 4088; break;
|
return B_ERROR;
|
||||||
case B_RGB24: max_acc_width = 2720; break;
|
|
||||||
case B_RGB32: max_acc_width = 2044; break;
|
|
||||||
default:
|
|
||||||
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* confirmed for:
|
|
||||||
* GeForce4 Ti4200 (NV28), GeForceFX 5600 (NV31) in PIO acc mode;
|
|
||||||
* GeForce2 MX400 (NV11), GeForce4 MX440 (NV18), GeForceFX 5200 (NV34) can do
|
|
||||||
* 16368/8184/8184/5456/4092, so a bit better in PIO acc mode;
|
|
||||||
* confirmed for:
|
|
||||||
* GeForce2 MX400 (NV11), GeForce4 MX440 (NV18), GeForcePCX 5750 (NV36),
|
|
||||||
* GeForcePCX 6600 GT (NV43) in DMA acc mode;
|
|
||||||
* GeForce4 Ti4200 (NV28), GeForceFX 5200 (NV34) can do
|
|
||||||
* 16368/8184/8184/5456/4092, so a bit better in DMA acc mode. */
|
|
||||||
switch(target->space)
|
|
||||||
{
|
|
||||||
case B_CMAP8: max_acc_width = 16320; break;
|
|
||||||
case B_RGB15: max_acc_width = 8160; break;
|
|
||||||
case B_RGB16: max_acc_width = 8160; break;
|
|
||||||
case B_RGB24: max_acc_width = 5440; break;
|
|
||||||
case B_RGB32: max_acc_width = 4080; break;
|
|
||||||
default:
|
|
||||||
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set virtual_width limit for unaccelerated modes */
|
/* set virtual_width limit for unaccelerated modes */
|
||||||
|
|||||||
@@ -22,10 +22,7 @@ typedef struct {
|
|||||||
static void detect_panels(void);
|
static void detect_panels(void);
|
||||||
static void setup_output_matrix(void);
|
static void setup_output_matrix(void);
|
||||||
|
|
||||||
static void pinsnv20_arch_fake(void);
|
|
||||||
static void pinsnv30_arch_fake(void);
|
static void pinsnv30_arch_fake(void);
|
||||||
static void getRAMsize_arch_nv4(void);
|
|
||||||
static void getstrap_arch_nv4(void);
|
|
||||||
static void getRAMsize_arch_nv10_20_30_40(void);
|
static void getRAMsize_arch_nv10_20_30_40(void);
|
||||||
static void getstrap_arch_nv10_20_30_40(void);
|
static void getstrap_arch_nv10_20_30_40(void);
|
||||||
static status_t pins2_read(uint8 *rom, uint32 offset);
|
static status_t pins2_read(uint8 *rom, uint32 offset);
|
||||||
@@ -39,7 +36,6 @@ static void exec_cmd_39_type2(uint8* rom, uint32 data, PinsTables tabs, bool* ex
|
|||||||
static void log_pll(uint32 reg, uint32 freq);
|
static void log_pll(uint32 reg, uint32 freq);
|
||||||
static void setup_ram_config(uint8* rom, uint16 ram_tab);
|
static void setup_ram_config(uint8* rom, uint16 ram_tab);
|
||||||
static void setup_ram_config_nv10_up(uint8* rom);
|
static void setup_ram_config_nv10_up(uint8* rom);
|
||||||
static void setup_ram_config_nv28(uint8* rom);
|
|
||||||
static status_t translate_ISA_PCI(uint32* reg);
|
static status_t translate_ISA_PCI(uint32* reg);
|
||||||
static status_t nv_crtc_setup_fifo(void);
|
static status_t nv_crtc_setup_fifo(void);
|
||||||
|
|
||||||
@@ -299,19 +295,9 @@ static status_t coldstart_card_516_up(uint8* rom, PinsTables tabs, uint16 ram_ta
|
|||||||
{
|
{
|
||||||
status_t result = B_OK;
|
status_t result = B_OK;
|
||||||
uint16 adress;
|
uint16 adress;
|
||||||
uint32 fb_mrs1 = 0;
|
|
||||||
uint32 fb_mrs2 = 0;
|
|
||||||
|
|
||||||
LOG(8,("INFO: now executing coldstart...\n"));
|
LOG(8,("INFO: now executing coldstart...\n"));
|
||||||
|
|
||||||
/* get some strapinfo(?) for NV28 framebuffer access */
|
|
||||||
//fixme?: works on at least one NV28... how about other cards?
|
|
||||||
if (si->ps.card_type == NV28)
|
|
||||||
{
|
|
||||||
fb_mrs2 = NV_REG32(NV32_FB_MRS2);
|
|
||||||
fb_mrs1 = NV_REG32(NV32_FB_MRS1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* select colormode CRTC registers base adresses */
|
/* select colormode CRTC registers base adresses */
|
||||||
NV_REG8(NV8_MISCW) = 0xcb;
|
NV_REG8(NV8_MISCW) = 0xcb;
|
||||||
|
|
||||||
@@ -368,20 +354,6 @@ static status_t coldstart_card_516_up(uint8* rom, PinsTables tabs, uint16 ram_ta
|
|||||||
adress = *((uint16*)(&(rom[index])));
|
adress = *((uint16*)(&(rom[index])));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do some NV28 specific extra stuff */
|
|
||||||
//fixme: NV28 only??
|
|
||||||
if (si->ps.card_type == NV28)
|
|
||||||
{
|
|
||||||
/* setup PTIMER */
|
|
||||||
ACCW(PT_NUMERATOR, (si->ps.std_engine_clock * 20));
|
|
||||||
ACCW(PT_DENOMINATR, 0x00000271);
|
|
||||||
|
|
||||||
/* get NV28 RAM access up and running */
|
|
||||||
//fixme?: works on at least one NV28... how about other cards?
|
|
||||||
NV_REG32(NV32_FB_MRS2) = fb_mrs2;
|
|
||||||
NV_REG32(NV32_FB_MRS1) = fb_mrs1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now enable ROM shadow or the card will remain shut-off! */
|
/* now enable ROM shadow or the card will remain shut-off! */
|
||||||
CFGW(ROMSHADOW, (CFGR(ROMSHADOW) |= 0x00000001));
|
CFGW(ROMSHADOW, (CFGR(ROMSHADOW) |= 0x00000001));
|
||||||
|
|
||||||
@@ -780,8 +752,6 @@ static status_t exec_type1_script(uint8* rom, uint16 adress, int16* size, uint16
|
|||||||
|
|
||||||
static void log_pll(uint32 reg, uint32 freq)
|
static void log_pll(uint32 reg, uint32 freq)
|
||||||
{
|
{
|
||||||
if ((si->ps.card_type == NV31) || (si->ps.card_type == NV36))
|
|
||||||
LOG(8,("INFO: ---WARNING: check/update PLL programming script code!!!\n"));
|
|
||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
case NV32_MEMPLL:
|
case NV32_MEMPLL:
|
||||||
@@ -1421,15 +1391,7 @@ static status_t exec_type2_script_mode(uint8* rom, uint16* adress, int16* size,
|
|||||||
*adress += 1;
|
*adress += 1;
|
||||||
LOG(8,("cmd 'setup RAM config' (always done)\n"));
|
LOG(8,("cmd 'setup RAM config' (always done)\n"));
|
||||||
/* always done */
|
/* always done */
|
||||||
switch (si->ps.card_type)
|
setup_ram_config_nv10_up(rom);
|
||||||
{
|
|
||||||
case NV28:
|
|
||||||
setup_ram_config_nv28(rom);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
setup_ram_config_nv10_up(rom);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 0x65: /* identical to type1 */
|
case 0x65: /* identical to type1 */
|
||||||
*size -= 13;
|
*size -= 13;
|
||||||
@@ -1948,57 +1910,6 @@ static void setup_ram_config_nv10_up(uint8* rom)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: this routine assumes at least 128Mb was mapped to memory (kerneldriver).
|
|
||||||
* It doesn't matter if the card actually _has_ this amount of RAM or not(!) */
|
|
||||||
static void setup_ram_config_nv28(uint8* rom)
|
|
||||||
{
|
|
||||||
/* note:
|
|
||||||
* After writing data to RAM a snooze is required to make the test work.
|
|
||||||
* Confirmed a NV11: without snooze it worked OK on a low-voltage AGP2.0 slot,
|
|
||||||
* but on a higher-voltage AGP 1.0 slot it failed to identify errors correctly!!
|
|
||||||
* Adding the snooze fixed that. */
|
|
||||||
|
|
||||||
uint32 dummy;
|
|
||||||
uint8 cnt = 0;
|
|
||||||
status_t stat = B_ERROR;
|
|
||||||
|
|
||||||
/* set 'refctrl is valid' */
|
|
||||||
NV_REG32(NV32_PFB_REFCTRL) = 0x80000000;
|
|
||||||
|
|
||||||
/* check RAM */
|
|
||||||
while ((cnt < 4) && (stat != B_OK))
|
|
||||||
{
|
|
||||||
/* set bit 11: 'pulse' something into a new setting? */
|
|
||||||
NV_REG32(NV32_PFB_CONFIG_0) |= 0x00000800;
|
|
||||||
/* write testpattern to RAM adress 127Mb */
|
|
||||||
((volatile uint32 *)si->framebuffer)[0x01fc0000] = 0x4e564441;
|
|
||||||
snooze(10);
|
|
||||||
/* reset first RAM adress */
|
|
||||||
((volatile uint32 *)si->framebuffer)[0x00000000] = 0x00000000;
|
|
||||||
snooze(10);
|
|
||||||
/* dummyread first RAM adress four times */
|
|
||||||
dummy = ((volatile uint32 *)si->framebuffer)[0x00000000];
|
|
||||||
LOG(8,("INFO: (#%d) dummy1 = $%08x, ", cnt, dummy));
|
|
||||||
dummy = ((volatile uint32 *)si->framebuffer)[0x00000000];
|
|
||||||
LOG(8,("dummy2 = $%08x, ", dummy));
|
|
||||||
dummy = ((volatile uint32 *)si->framebuffer)[0x00000000];
|
|
||||||
LOG(8,("dummy3 = $%08x, ", dummy));
|
|
||||||
dummy = ((volatile uint32 *)si->framebuffer)[0x00000000];
|
|
||||||
LOG(8,("dummy4 = $%08x\n", dummy));
|
|
||||||
/* check testpattern to have survived */
|
|
||||||
if (((volatile uint32 *)si->framebuffer)[0x01fc0000] == 0x4e564441) stat = B_OK;
|
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clear bit 11: set normal mode */
|
|
||||||
NV_REG32(NV32_PFB_CONFIG_0) &= ~0x00000800;
|
|
||||||
|
|
||||||
if (stat == B_OK)
|
|
||||||
LOG(8,("INFO: ---RAM test done: access was OK within %d iteration(s).\n", cnt));
|
|
||||||
else
|
|
||||||
LOG(8,("INFO: ---RAM test done: access was still not OK after 4 iterations.\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
static status_t translate_ISA_PCI(uint32* reg)
|
static status_t translate_ISA_PCI(uint32* reg)
|
||||||
{
|
{
|
||||||
switch (*reg)
|
switch (*reg)
|
||||||
@@ -2103,25 +2014,18 @@ void set_specs(void)
|
|||||||
/* set failsave speeds */
|
/* set failsave speeds */
|
||||||
switch (si->ps.card_arch)
|
switch (si->ps.card_arch)
|
||||||
{
|
{
|
||||||
case NV20A:
|
|
||||||
pinsnv20_arch_fake();
|
|
||||||
break;
|
|
||||||
case NV30A:
|
|
||||||
case NV40A:
|
case NV40A:
|
||||||
pinsnv30_arch_fake();
|
pinsnv30_arch_fake();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* 'failsafe' values... */
|
/* 'failsafe' values... */
|
||||||
pinsnv20_arch_fake();
|
pinsnv30_arch_fake();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* detect reference crystal frequency and dualhead */
|
/* detect reference crystal frequency and dualhead */
|
||||||
switch (si->ps.card_arch)
|
switch (si->ps.card_arch)
|
||||||
{
|
{
|
||||||
case NV04A:
|
|
||||||
getstrap_arch_nv4();
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
getstrap_arch_nv10_20_30_40();
|
getstrap_arch_nv10_20_30_40();
|
||||||
break;
|
break;
|
||||||
@@ -2136,9 +2040,6 @@ void fake_panel_start(void)
|
|||||||
/* detect RAM amount */
|
/* detect RAM amount */
|
||||||
switch (si->ps.card_arch)
|
switch (si->ps.card_arch)
|
||||||
{
|
{
|
||||||
case NV04A:
|
|
||||||
getRAMsize_arch_nv4();
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
getRAMsize_arch_nv10_20_30_40();
|
getRAMsize_arch_nv10_20_30_40();
|
||||||
break;
|
break;
|
||||||
@@ -2566,15 +2467,6 @@ static void setup_output_matrix()
|
|||||||
//Also: it looks as if each pixelclock PLL can select different CRTC's
|
//Also: it looks as if each pixelclock PLL can select different CRTC's
|
||||||
//as well now via a new register: one PLL can be driving both CRTC's
|
//as well now via a new register: one PLL can be driving both CRTC's
|
||||||
//and there's nothing we can do about that (yet). (DVI/dualhead trouble)
|
//and there's nothing we can do about that (yet). (DVI/dualhead trouble)
|
||||||
if (si->ps.card_arch < NV40A)
|
|
||||||
{
|
|
||||||
LOG(2,("INFO: illegal monitor setup ($%02x):\n", si->ps.monitors));
|
|
||||||
/* head 2 takes precedence because it has a digital panel while
|
|
||||||
* head 1 has not. */
|
|
||||||
LOG(2,("INFO: defaulting to head 2 for primary use.\n"));
|
|
||||||
si->ps.crtc2_prim = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: /* more than two monitors connected to just two outputs: illegal! */
|
default: /* more than two monitors connected to just two outputs: illegal! */
|
||||||
LOG(2,("INFO: illegal monitor setup ($%02x):\n", si->ps.monitors));
|
LOG(2,("INFO: illegal monitor setup ($%02x):\n", si->ps.monitors));
|
||||||
LOG(2,("INFO: defaulting to head 1 for primary use.\n"));
|
LOG(2,("INFO: defaulting to head 1 for primary use.\n"));
|
||||||
@@ -2626,57 +2518,10 @@ void get_panel_modes(display_mode *p1, display_mode *p2, bool *pan1, bool *pan2)
|
|||||||
*pan2 = false;
|
*pan2 = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pinsnv20_arch_fake(void)
|
|
||||||
{
|
|
||||||
/* we have a standard PLL */
|
|
||||||
si->ps.ext_pll = false;
|
|
||||||
/* carefull not to take to high limits, and high should be >= 2x low. */
|
|
||||||
si->ps.max_system_vco = 350;
|
|
||||||
si->ps.min_system_vco = 128;
|
|
||||||
si->ps.max_pixel_vco = 350;
|
|
||||||
si->ps.min_pixel_vco = 128;
|
|
||||||
si->ps.max_video_vco = 350;
|
|
||||||
si->ps.min_video_vco = 128;
|
|
||||||
si->ps.max_dac1_clock = 350;
|
|
||||||
si->ps.max_dac1_clock_8 = 350;
|
|
||||||
si->ps.max_dac1_clock_16 = 350;
|
|
||||||
/* 'failsave' values */
|
|
||||||
si->ps.max_dac1_clock_24 = 320;
|
|
||||||
si->ps.max_dac1_clock_32 = 280;
|
|
||||||
si->ps.max_dac1_clock_32dh = 250;
|
|
||||||
/* secondary head */
|
|
||||||
/* GeForce4 cards have dual integrated DACs with identical capaability */
|
|
||||||
/* (called nview technology) */
|
|
||||||
si->ps.max_dac2_clock = 350;
|
|
||||||
si->ps.max_dac2_clock_8 = 350;
|
|
||||||
si->ps.max_dac2_clock_16 = 350;
|
|
||||||
/* 'failsave' values */
|
|
||||||
si->ps.max_dac2_clock_24 = 320;
|
|
||||||
si->ps.max_dac2_clock_32 = 280;
|
|
||||||
si->ps.max_dac2_clock_32dh = 250;
|
|
||||||
//fixme: primary & secondary_dvi should be overrule-able via nv.settings
|
|
||||||
si->ps.primary_dvi = false;
|
|
||||||
si->ps.secondary_dvi = false;
|
|
||||||
/* not used (yet) because no coldstart will be attempted (yet) */
|
|
||||||
si->ps.std_engine_clock = 175;
|
|
||||||
si->ps.std_memory_clock = 200;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pinsnv30_arch_fake(void)
|
static void pinsnv30_arch_fake(void)
|
||||||
{
|
{
|
||||||
/* determine PLL type */
|
/* we have a extended PLL */
|
||||||
if ((si->ps.card_type == NV31) ||
|
si->ps.ext_pll = true;
|
||||||
(si->ps.card_type == NV36) ||
|
|
||||||
(si->ps.card_type >= NV40))
|
|
||||||
{
|
|
||||||
/* we have a extended PLL */
|
|
||||||
si->ps.ext_pll = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* we have a standard PLL */
|
|
||||||
si->ps.ext_pll = false;
|
|
||||||
}
|
|
||||||
/* carefull not to take to high limits, and high should be >= 2x low. */
|
/* carefull not to take to high limits, and high should be >= 2x low. */
|
||||||
si->ps.max_system_vco = 350;
|
si->ps.max_system_vco = 350;
|
||||||
si->ps.min_system_vco = 128;
|
si->ps.min_system_vco = 128;
|
||||||
@@ -2719,53 +2564,6 @@ static void pinsnv30_arch_fake(void)
|
|||||||
si->ps.std_memory_clock = 190;
|
si->ps.std_memory_clock = 190;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getRAMsize_arch_nv4(void)
|
|
||||||
{
|
|
||||||
uint32 strapinfo = NV_REG32(NV32_NV4STRAPINFO);
|
|
||||||
|
|
||||||
if (strapinfo & 0x00000100)
|
|
||||||
{
|
|
||||||
/* Unified memory architecture used */
|
|
||||||
si->ps.memory_size = 1024 * 1024 *
|
|
||||||
((((strapinfo & 0x0000f000) >> 12) * 2) + 2);
|
|
||||||
|
|
||||||
LOG(8,("INFO: NV4 architecture chip with UMA detected\n"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* private memory architecture used */
|
|
||||||
switch (strapinfo & 0x00000003)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
si->ps.memory_size = 32 * 1024 * 1024;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
si->ps.memory_size = 4 * 1024 * 1024;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
si->ps.memory_size = 8 * 1024 * 1024;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
si->ps.memory_size = 16 * 1024 * 1024;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void getstrap_arch_nv4(void)
|
|
||||||
{
|
|
||||||
uint32 strapinfo = NV_REG32(NV32_NVSTRAPINFO2);
|
|
||||||
|
|
||||||
/* determine PLL reference crystal frequency */
|
|
||||||
if (strapinfo & 0x00000040)
|
|
||||||
si->ps.f_ref = 14.31818;
|
|
||||||
else
|
|
||||||
si->ps.f_ref = 13.50000;
|
|
||||||
|
|
||||||
/* these cards are always singlehead */
|
|
||||||
si->ps.secondary_head = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void getRAMsize_arch_nv10_20_30_40(void)
|
static void getRAMsize_arch_nv10_20_30_40(void)
|
||||||
{
|
{
|
||||||
uint32 dev_manID = CFGR(DEVID);
|
uint32 dev_manID = CFGR(DEVID);
|
||||||
@@ -2823,25 +2621,10 @@ static void getRAMsize_arch_nv10_20_30_40(void)
|
|||||||
|
|
||||||
static void getstrap_arch_nv10_20_30_40(void)
|
static void getstrap_arch_nv10_20_30_40(void)
|
||||||
{
|
{
|
||||||
uint32 dev_manID = CFGR(DEVID);
|
|
||||||
uint32 strapinfo = NV_REG32(NV32_NVSTRAPINFO2);
|
uint32 strapinfo = NV_REG32(NV32_NVSTRAPINFO2);
|
||||||
|
|
||||||
/* determine if we have a dualhead card */
|
/* all cards are dualhead cards these days */
|
||||||
si->ps.secondary_head = false;
|
si->ps.secondary_head = true;
|
||||||
switch (si->ps.card_type)
|
|
||||||
{
|
|
||||||
case NV20:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if ((dev_manID & 0xfff0ffff) == 0x01a010de)
|
|
||||||
{
|
|
||||||
/* this is a singlehead NV11! */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
si->ps.secondary_head = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* determine PLL reference crystal frequency: three types are used... */
|
/* determine PLL reference crystal frequency: three types are used... */
|
||||||
if (strapinfo & 0x00000040)
|
if (strapinfo & 0x00000040)
|
||||||
|
|||||||
Reference in New Issue
Block a user