openBeOS_Neomagic_V0.03_src
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5514 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
SubDir OBOS_TOP src add-ons accelerants ;
|
||||
|
||||
SubInclude OBOS_TOP src add-ons accelerants neomagic ;
|
||||
SubInclude OBOS_TOP src add-ons accelerants nvidia ;
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
|
||||
Other authors:
|
||||
Rudolf Cornelissen 4/2003-
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x40000000
|
||||
|
||||
#include "acc_std.h"
|
||||
|
||||
void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count) {
|
||||
int i;
|
||||
|
||||
/*do each blit*/
|
||||
i=0;
|
||||
while (count--)
|
||||
{
|
||||
mn_acc_blit
|
||||
(
|
||||
list[i].src_left,
|
||||
list[i].src_top,
|
||||
list[i].dest_left,
|
||||
list[i].dest_top,
|
||||
list[i].width,
|
||||
list[i].height
|
||||
);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void SCREEN_TO_SCREEN_SCALED_FILTERED_BLIT(engine_token *et, scaled_blit_params *list, uint32 count) {
|
||||
int i;
|
||||
|
||||
/*do each blit*/
|
||||
i=0;
|
||||
while (count--)
|
||||
{
|
||||
mn_acc_video_blit
|
||||
(
|
||||
list[i].src_left,
|
||||
list[i].src_top,
|
||||
list[i].src_width,
|
||||
list[i].src_height,
|
||||
list[i].dest_left,
|
||||
list[i].dest_top,
|
||||
list[i].dest_width,
|
||||
list[i].dest_height
|
||||
);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void SCREEN_TO_SCREEN_TRANSPARENT_BLIT(engine_token *et, uint32 transparent_colour, blit_params *list, uint32 count) {
|
||||
int i;
|
||||
|
||||
/*do each blit*/
|
||||
i=0;
|
||||
while (count--)
|
||||
{
|
||||
mn_acc_transparent_blit
|
||||
(
|
||||
list[i].src_left,
|
||||
list[i].src_top,
|
||||
list[i].dest_left,
|
||||
list[i].dest_top,
|
||||
list[i].width,
|
||||
list[i].height,
|
||||
transparent_colour
|
||||
);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void FILL_RECTANGLE(engine_token *et, uint32 colorIndex, fill_rect_params *list, uint32 count) {
|
||||
int i;
|
||||
|
||||
/*draw each rectangle*/
|
||||
i=0;
|
||||
while (count--)
|
||||
{
|
||||
mn_acc_rectangle
|
||||
(
|
||||
list[i].left,
|
||||
(list[i].right)+1,
|
||||
list[i].top,
|
||||
(list[i].bottom-list[i].top)+1,
|
||||
colorIndex
|
||||
);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count) {
|
||||
int i;
|
||||
|
||||
/*draw each rectangle*/
|
||||
i=0;
|
||||
while (count--)
|
||||
{
|
||||
mn_acc_rectangle_invert
|
||||
(
|
||||
list[i].left,
|
||||
(list[i].right)+1,
|
||||
list[i].top,
|
||||
(list[i].bottom-list[i].top)+1,
|
||||
0
|
||||
);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void FILL_SPAN(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count) {
|
||||
int i;
|
||||
|
||||
/*draw each span*/
|
||||
i=0;
|
||||
while (count--)
|
||||
{
|
||||
mn_acc_rectangle
|
||||
(
|
||||
list[i+1],
|
||||
list[i+2]+1,
|
||||
list[i],
|
||||
1,
|
||||
colorIndex
|
||||
);
|
||||
i+=3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
|
||||
Other authors:
|
||||
Rudolf Cornelissen 4/2003-6/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x20000000
|
||||
|
||||
#include "acc_std.h"
|
||||
|
||||
status_t SET_CURSOR_SHAPE(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y, uint8 *andMask, uint8 *xorMask)
|
||||
{
|
||||
LOG(4,("SET_CURSOR_SHAPE: width %d, height %d, hot_x %d, hot_y %d\n",
|
||||
width, height, hot_x, hot_y));
|
||||
|
||||
if ((width != 16) || (height != 16))
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
else if ((hot_x >= width) || (hot_y >= height))
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
mn_crtc_cursor_define(andMask,xorMask);
|
||||
|
||||
/* Update cursor variables appropriately. */
|
||||
si->cursor.width = width;
|
||||
si->cursor.height = height;
|
||||
si->cursor.hot_x = hot_x;
|
||||
si->cursor.hot_y = hot_y;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* Move the cursor to the specified position on the desktop, taking account of virtual/dual issues */
|
||||
void MOVE_CURSOR(uint16 x, uint16 y)
|
||||
{
|
||||
uint16 hds = si->dm.h_display_start; /* the current horizontal starting pixel */
|
||||
uint16 vds = si->dm.v_display_start; /* the current vertical starting line */
|
||||
uint16 h_adjust;
|
||||
uint16 h_display = si->dm.timing.h_display; /* local copy needed for flatpanel */
|
||||
uint16 v_display = si->dm.timing.v_display; /* local copy needed for flatpanel */
|
||||
|
||||
/* clamp cursor to display */
|
||||
if (x >= si->dm.virtual_width) x = si->dm.virtual_width - 1;
|
||||
if (y >= si->dm.virtual_height) y = si->dm.virtual_height - 1;
|
||||
|
||||
/* store, for our info */
|
||||
si->cursor.x = x;
|
||||
si->cursor.y = y;
|
||||
|
||||
switch(si->dm.space)
|
||||
{
|
||||
case B_CMAP8:
|
||||
h_adjust = 0x03;
|
||||
break;
|
||||
case B_RGB15_LITTLE:case B_RGB16_LITTLE:
|
||||
h_adjust = 0x01;
|
||||
break;
|
||||
case B_RGB32_LITTLE:
|
||||
h_adjust = 0x00;
|
||||
break;
|
||||
default:
|
||||
h_adjust = 0x03;
|
||||
break;
|
||||
}
|
||||
|
||||
/* if internal panel is active correct visible screensize! */
|
||||
if (nm_general_output_read() & 0x02)
|
||||
{
|
||||
if (h_display > si->ps.panel_width) h_display = si->ps.panel_width;
|
||||
if (v_display > si->ps.panel_height) v_display = si->ps.panel_height;
|
||||
}
|
||||
|
||||
/* adjust h/v_display_start to move cursor onto screen */
|
||||
if (x >= (h_display + hds))
|
||||
{
|
||||
hds = ((x - h_display) + 1 + h_adjust) & ~h_adjust;
|
||||
/* make sure we stay within the display! */
|
||||
if ((hds + h_display) > si->dm.virtual_width)
|
||||
hds -= (h_adjust + 1);
|
||||
}
|
||||
else if (x < hds)
|
||||
hds = x & ~h_adjust;
|
||||
|
||||
if (y >= (v_display + vds))
|
||||
vds = y - v_display + 1;
|
||||
else if (y < vds)
|
||||
vds = y;
|
||||
|
||||
/* reposition the desktop _and_ the overlay on the display if required */
|
||||
if ((hds!=si->dm.h_display_start) || (vds!=si->dm.v_display_start))
|
||||
{
|
||||
MOVE_DISPLAY(hds,vds);
|
||||
//fixme: implement:
|
||||
//move_overlay(hds,vds);
|
||||
}
|
||||
|
||||
/* put cursor in correct physical position */
|
||||
if (x > (hds + si->cursor.hot_x)) x -= hds + si->cursor.hot_x;
|
||||
else x = 0;
|
||||
if (y > (vds + si->cursor.hot_y)) y -= vds + si->cursor.hot_y;
|
||||
else y = 0;
|
||||
|
||||
/* position the cursor on the display */
|
||||
mn_crtc_cursor_position(x,y);
|
||||
}
|
||||
|
||||
void SHOW_CURSOR(bool is_visible)
|
||||
{
|
||||
/* record for our info */
|
||||
si->cursor.is_visible = is_visible;
|
||||
|
||||
if (is_visible)
|
||||
mn_crtc_cursor_show();
|
||||
else
|
||||
mn_crtc_cursor_hide();
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
|
||||
modification to call G400 functions and mess-ups - Mark Watson
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x10000000
|
||||
|
||||
#include "acc_std.h"
|
||||
|
||||
|
||||
static engine_token mn_engine_token = { 1, B_2D_ACCELERATION, NULL };
|
||||
|
||||
uint32 ACCELERANT_ENGINE_COUNT(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
status_t ACQUIRE_ENGINE(uint32 capabilities, uint32 max_wait, sync_token *st, engine_token **et) {
|
||||
/* acquire the shared benaphore */
|
||||
AQUIRE_BEN(si->engine.lock)
|
||||
/* sync if required */
|
||||
if (st) SYNC_TO_TOKEN(st);
|
||||
|
||||
/* return an engine token */
|
||||
*et = &mn_engine_token;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t RELEASE_ENGINE(engine_token *et, sync_token *st) {
|
||||
/* update the sync token, if any */
|
||||
if (st) {
|
||||
GET_SYNC_TOKEN(et,st);
|
||||
}
|
||||
|
||||
/* release the shared benaphore */
|
||||
RELEASE_BEN(si->engine.lock)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void WAIT_ENGINE_IDLE(void) {
|
||||
uint32 count;
|
||||
/*wait for the engine to be totally idle*/
|
||||
count = si->engine.count;
|
||||
mn_acc_wait_idle();
|
||||
|
||||
si->engine.last_idle = count;
|
||||
}
|
||||
|
||||
status_t GET_SYNC_TOKEN(engine_token *et, sync_token *st) {
|
||||
si->engine.count+=4;
|
||||
st->engine_id = et->engine_id;
|
||||
st->counter = si->engine.count;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t SYNC_TO_TOKEN(sync_token *st) {
|
||||
/* a quick out */
|
||||
if (st->counter <= si->engine.last_idle) return B_OK;
|
||||
|
||||
/* another quick out! */
|
||||
if ((st->counter >0xFFFFFFF) && (si->engine.last_idle <0xFFFF)) return B_OK; /*for when counter wraps*/
|
||||
|
||||
/* If not we have to wait :-(*/
|
||||
WAIT_ENGINE_IDLE();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
|
||||
Other authors:
|
||||
Rudolf Cornelissen 10/2002-4/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x08000000
|
||||
|
||||
#include "acc_std.h"
|
||||
|
||||
/*
|
||||
The standard entry point. Given a uint32 feature identifier, this routine
|
||||
returns a pointer to the function that implements the feature. Some features
|
||||
require more information than just the identifier to select the proper
|
||||
function. The extra information (which is specific to the feature) is
|
||||
pointed at by the void *data parameter. By default, no extra information
|
||||
is available. Any extra information available to choose the function will be
|
||||
noted on a case by case below.
|
||||
*/
|
||||
|
||||
/*
|
||||
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: \
|
||||
if (check_acc_capability(B_##x) == B_OK) return (void *)x; else return (void *)0
|
||||
#define HOOK(x) case B_##x: return (void *)x
|
||||
#define ZERO(x) case B_##x: return (void *)0
|
||||
#define HRDC(x) case B_##x: return si->settings.hardcursor? (void *)x: (void *)0;
|
||||
|
||||
void * get_accelerant_hook(uint32 feature, void *data)
|
||||
{
|
||||
switch (feature)
|
||||
{
|
||||
/*
|
||||
One of either B_INIT_ACCELERANT or B_CLONE_ACCELERANT will be requested and
|
||||
subsequently called before any other hook is requested. All other feature
|
||||
hook selections can be predicated on variables assigned during the accelerant
|
||||
initialization process.
|
||||
*/
|
||||
|
||||
/* initialization */
|
||||
HOOK(INIT_ACCELERANT);
|
||||
HOOK(CLONE_ACCELERANT);
|
||||
|
||||
HOOK(ACCELERANT_CLONE_INFO_SIZE);
|
||||
HOOK(GET_ACCELERANT_CLONE_INFO);
|
||||
HOOK(UNINIT_ACCELERANT);
|
||||
HOOK(GET_ACCELERANT_DEVICE_INFO);
|
||||
HOOK(ACCELERANT_RETRACE_SEMAPHORE);
|
||||
|
||||
/* mode configuration */
|
||||
HOOK(ACCELERANT_MODE_COUNT);
|
||||
HOOK(GET_MODE_LIST);
|
||||
HOOK(PROPOSE_DISPLAY_MODE);
|
||||
HOOK(SET_DISPLAY_MODE);
|
||||
HOOK(GET_DISPLAY_MODE);
|
||||
HOOK(GET_FRAME_BUFFER_CONFIG);
|
||||
HOOK(GET_PIXEL_CLOCK_LIMITS);
|
||||
HOOK(MOVE_DISPLAY);
|
||||
HOOK(SET_INDEXED_COLORS);
|
||||
HOOK(GET_TIMING_CONSTRAINTS);
|
||||
|
||||
HOOK(DPMS_CAPABILITIES);
|
||||
HOOK(DPMS_MODE);
|
||||
HOOK(SET_DPMS_MODE);
|
||||
|
||||
/* cursor managment */
|
||||
HRDC(SET_CURSOR_SHAPE);
|
||||
HRDC(MOVE_CURSOR);
|
||||
HRDC(SHOW_CURSOR);
|
||||
|
||||
/* synchronization */
|
||||
HOOK(ACCELERANT_ENGINE_COUNT);
|
||||
HOOK(ACQUIRE_ENGINE);
|
||||
HOOK(RELEASE_ENGINE);
|
||||
HOOK(WAIT_ENGINE_IDLE);
|
||||
HOOK(GET_SYNC_TOKEN);
|
||||
HOOK(SYNC_TO_TOKEN);
|
||||
|
||||
/*
|
||||
Depending on the engine architecture, you may choose to provide a different
|
||||
function to be used with each bit-depth for example.
|
||||
|
||||
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 */
|
||||
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
|
||||
pointer to the display_mode for which the acceleration function will be used.
|
||||
Depending on the engine architecture, you may choose to provide a different
|
||||
function to be used with each bit-depth. In the sample driver we return
|
||||
the same function all the time.
|
||||
|
||||
Note: These hooks are re-acquired by the app_server after each mode switch.
|
||||
*/
|
||||
|
||||
/* only export 2D acceleration functions in modes that are capable of it */
|
||||
/* used by the app_server and applications (BWindowScreen) */
|
||||
CHKA(SCREEN_TO_SCREEN_BLIT);
|
||||
CHKA(FILL_RECTANGLE);
|
||||
CHKA(INVERT_RECTANGLE);
|
||||
CHKA(FILL_SPAN);
|
||||
/* not (yet) used by the app_server:
|
||||
* so just for application use (BWindowScreen) */
|
||||
CHKA(SCREEN_TO_SCREEN_TRANSPARENT_BLIT);
|
||||
//CHKA(SCREEN_TO_SCREEN_SCALED_FILTERED_BLIT;
|
||||
}
|
||||
|
||||
/* Return a null pointer for any feature we don't understand. */
|
||||
return 0;
|
||||
}
|
||||
#undef CHKO
|
||||
#undef CHKA
|
||||
#undef HOOK
|
||||
#undef ZERO
|
||||
#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;
|
||||
}
|
||||
|
||||
// if (si->ps.card_type > NM2070)
|
||||
// {
|
||||
/* export video overlay functions */
|
||||
// LOG(4, ("Overlay: Exporting hook %s.\n", msg));
|
||||
// return B_OK;
|
||||
// }
|
||||
|
||||
/* do not export video overlay functions */
|
||||
LOG(4, ("Overlay: Not exporting hook %s.\n", msg));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t check_acc_capability(uint32 feature)
|
||||
{
|
||||
bool fill = false;
|
||||
char *msg = "";
|
||||
|
||||
/* setup logmessage text */
|
||||
switch (feature)
|
||||
{
|
||||
case B_SCREEN_TO_SCREEN_BLIT:
|
||||
msg = "B_SCREEN_TO_SCREEN_BLIT";
|
||||
break;
|
||||
case B_FILL_RECTANGLE:
|
||||
msg = "B_FILL_RECTANGLE";
|
||||
fill = true;
|
||||
break;
|
||||
case B_INVERT_RECTANGLE:
|
||||
msg = "B_INVERT_RECTANGLE";
|
||||
fill = true;
|
||||
break;
|
||||
case B_FILL_SPAN:
|
||||
msg = "B_FILL_SPAN";
|
||||
fill = true;
|
||||
break;
|
||||
case B_SCREEN_TO_SCREEN_TRANSPARENT_BLIT:
|
||||
msg = "B_SCREEN_TO_SCREEN_TRANSPARENT_BLIT";
|
||||
break;
|
||||
case B_SCREEN_TO_SCREEN_SCALED_FILTERED_BLIT:
|
||||
msg = "B_SCREEN_TO_SCREEN_SCALED_FILTERED_BLIT";
|
||||
break;
|
||||
default:
|
||||
msg = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
|
||||
/* hardware acceleration is only supported in modes with upto a certain
|
||||
* memory pitch.. */
|
||||
if (si->acc_mode)
|
||||
{
|
||||
/* see if we support hardware rectangle fills in the current mode:
|
||||
* the Matrox card's acc engine can adress upto 16Mbyte memory for this cmd! */
|
||||
if (fill &&
|
||||
((si->fbc.bytes_per_row * si->dm.virtual_height) > (16 * 1024 * 1024)))
|
||||
{
|
||||
LOG(4, ("Acc: Not exporting hook %s.\n", msg));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
LOG(4, ("Acc: Exporting hook %s.\n", msg));
|
||||
return B_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(4, ("Acc: Not exporting hook %s.\n", msg));
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Authors:
|
||||
Rudolf Cornelissen 4/2003-
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x04000000
|
||||
|
||||
#include "acc_std.h"
|
||||
|
||||
/* Get some info about the device */
|
||||
status_t GET_ACCELERANT_DEVICE_INFO(accelerant_device_info * adi)
|
||||
{
|
||||
/*no info on version is provided, so presumably this is for my info*/
|
||||
LOG(4,("DEVICE_INFO: version 0x%08x\n", adi->version));
|
||||
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
case 0x01:
|
||||
sprintf(adi->name,"Neomagic Plain");
|
||||
break;
|
||||
case 0x02:
|
||||
sprintf(adi->name,"Neomagic MAX");
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(adi->chipset,"Neomagic");
|
||||
|
||||
sprintf(adi->serial_no,"01134"); /*FIXME*/
|
||||
|
||||
adi->memory=si->ps.memory_size * 1024;
|
||||
|
||||
adi->dac_speed=si->ps.max_dac1_clock;
|
||||
|
||||
// apsed, TODO ?? GET_ACCELERANT_DEVICE_INFO never called and kind of cards
|
||||
LOG(2,("GET_ACCELERANT_DEVICE_INFO %20s 0x%08x %d\n", "version", adi->version, adi->version));
|
||||
LOG(2,("GET_ACCELERANT_DEVICE_INFO %20s %s\n", "name", adi->name));
|
||||
LOG(2,("GET_ACCELERANT_DEVICE_INFO %20s %s\n", "chipset", adi->chipset));
|
||||
LOG(2,("GET_ACCELERANT_DEVICE_INFO %20s %s\n", "serial_no", adi->serial_no));
|
||||
LOG(2,("GET_ACCELERANT_DEVICE_INFO %20s 0x%08x %d\n", "memory", adi->memory, adi->memory));
|
||||
LOG(2,("GET_ACCELERANT_DEVICE_INFO %20s %d\n", "dac_speed", adi->dac_speed));
|
||||
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
|
||||
Other authors:
|
||||
Rudolf Cornelissen 4/2003-6/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x02000000
|
||||
|
||||
#include "acc_std.h"
|
||||
|
||||
/*
|
||||
Return the current display mode. The only time you might return an
|
||||
error is if a mode hasn't been set. Or if the system hands you a NULL pointer.
|
||||
*/
|
||||
status_t GET_DISPLAY_MODE(display_mode *current_mode)
|
||||
{
|
||||
/* check for NULL pointer */
|
||||
if (current_mode == NULL) return B_ERROR;
|
||||
|
||||
*current_mode = si->dm;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* Return the frame buffer configuration information. */
|
||||
status_t GET_FRAME_BUFFER_CONFIG(frame_buffer_config *afb)
|
||||
{
|
||||
/* check for NULL pointer */
|
||||
if (afb == NULL) return B_ERROR;
|
||||
|
||||
*afb = si->fbc;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* Return the maximum and minium pixelclock limits for the specified mode. */
|
||||
status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high)
|
||||
{
|
||||
uint32 max_pclk = 0;
|
||||
uint32 min_pclk = 0;
|
||||
|
||||
/* check for NULL pointers */
|
||||
if ((dm == NULL) || (low == NULL) || (high == NULL)) return B_ERROR;
|
||||
|
||||
/* specify requested info assuming CRT-only mode
|
||||
* (if panel is active, CRTC and pixelclock are not programmed!) */
|
||||
{
|
||||
/* find min. value */
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
default:
|
||||
*low = (si->ps.min_pixel_vco * 1000);
|
||||
break;
|
||||
}
|
||||
/* find max. value */
|
||||
switch (dm->space)
|
||||
{
|
||||
case B_CMAP8:
|
||||
max_pclk = si->ps.max_dac1_clock_8;
|
||||
break;
|
||||
case B_RGB15_LITTLE:
|
||||
case B_RGB16_LITTLE:
|
||||
max_pclk = si->ps.max_dac1_clock_16;
|
||||
break;
|
||||
case B_RGB24_LITTLE:
|
||||
max_pclk = si->ps.max_dac1_clock_24;
|
||||
break;
|
||||
default:
|
||||
/* use fail-safe value */
|
||||
max_pclk = si->ps.max_dac1_clock_24;
|
||||
break;
|
||||
}
|
||||
/* return values in kHz */
|
||||
*high = max_pclk * 1000;
|
||||
}
|
||||
|
||||
/* clamp lower limit to 48Hz vertical refresh for now.
|
||||
* Apparantly the BeOS screenprefs app does limit the upper refreshrate to 90Hz,
|
||||
* while it does not limit the lower refreshrate. */
|
||||
min_pclk = ((uint32)dm->timing.h_total * (uint32)dm->timing.v_total * 48) / 1000;
|
||||
if (min_pclk > *low) *low = min_pclk;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* Return the semaphore id that will be used to signal a vertical sync occured. */
|
||||
sem_id ACCELERANT_RETRACE_SEMAPHORE(void)
|
||||
{
|
||||
return si->vblank;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Authors:
|
||||
Mark Watson - 21/6/00,
|
||||
Apsed
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x01000000
|
||||
|
||||
#include "acc_std.h"
|
||||
|
||||
/* Used to help generate mode lines */
|
||||
status_t GET_TIMING_CONSTRAINTS(display_timing_constraints * dtc)
|
||||
{
|
||||
// apsed, TODO, is that following card capabilities ??
|
||||
LOG(4, ("GET_TIMING_CONSTRAINTS\n"));
|
||||
|
||||
dtc->h_res=8;
|
||||
dtc->h_sync_min=8;
|
||||
dtc->h_sync_max=248;
|
||||
dtc->h_blank_min=8;
|
||||
dtc->h_blank_max=504;
|
||||
|
||||
dtc->v_res=1;
|
||||
dtc->v_sync_min=1;
|
||||
dtc->v_sync_max=15;
|
||||
dtc->v_blank_min=1;
|
||||
dtc->v_blank_max=255;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
|
||||
Other authors:
|
||||
Mark Watson,
|
||||
Rudolf Cornelissen 4/2003-
|
||||
*/
|
||||
|
||||
#include "acc_std.h"
|
||||
|
||||
int fd;
|
||||
shared_info *si;
|
||||
area_id shared_info_area;
|
||||
vuint32 *regs, *regs2;
|
||||
area_id regs_area, regs2_area;
|
||||
display_mode *my_mode_list;
|
||||
area_id my_mode_list_area;
|
||||
int accelerantIsClone;
|
||||
|
||||
mn_get_set_pci mn_pci_access=
|
||||
{
|
||||
MN_PRIVATE_DATA_MAGIC,
|
||||
0,
|
||||
4,
|
||||
0
|
||||
};
|
||||
|
||||
mn_in_out_isa mn_isa_access=
|
||||
{
|
||||
MN_PRIVATE_DATA_MAGIC,
|
||||
0,
|
||||
1,
|
||||
0
|
||||
};
|
||||
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
|
||||
Other authors:
|
||||
Mark Watson,
|
||||
Rudolf Cornelissen 10/2002-3/2003.
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00800000
|
||||
|
||||
#include <string.h>
|
||||
#include "acc_std.h"
|
||||
|
||||
/* defined in ProposeDisplayMode.c */
|
||||
extern status_t create_mode_list(void);
|
||||
|
||||
static status_t init_common(int the_fd);
|
||||
|
||||
/* Initialization code shared between primary and cloned accelerants */
|
||||
static status_t init_common(int the_fd) {
|
||||
status_t result;
|
||||
mn_get_private_data gpd;
|
||||
|
||||
// LOG not available from here to next LOG: NULL si
|
||||
|
||||
/* memorize the file descriptor */
|
||||
fd = the_fd;
|
||||
/* set the magic number so the driver knows we're for real */
|
||||
gpd.magic = MN_PRIVATE_DATA_MAGIC;
|
||||
/* contact driver and get a pointer to the registers and shared data */
|
||||
result = ioctl(fd, MN_GET_PRIVATE_DATA, &gpd, sizeof(gpd));
|
||||
if (result != B_OK) goto error0;
|
||||
|
||||
/* clone the shared area for our use */
|
||||
shared_info_area = clone_area(DRIVER_PREFIX " shared", (void **)&si, B_ANY_ADDRESS,
|
||||
B_READ_AREA | B_WRITE_AREA, gpd.shared_info_area);
|
||||
if (shared_info_area < 0) {
|
||||
result = shared_info_area;
|
||||
goto error0;
|
||||
}
|
||||
// LOG is now available, si !NULL
|
||||
LOG(4,("init_common: logmask 0x%08x, memory %dMB, hardcursor %d, usebios %d\n",
|
||||
si->settings.logmask, si->settings.memory, si->settings.hardcursor, si->settings.usebios));
|
||||
|
||||
/*Check for R4.5.0 and if it is running, use work around*/
|
||||
{
|
||||
if (si->use_clone_bugfix)
|
||||
{
|
||||
/*check for R4.5.0 bug and attempt to work around*/
|
||||
LOG(2,("InitACC: Found R4.5.0 bug - attempting to work around\n"));
|
||||
regs = si->clone_bugfix_regs;
|
||||
regs2 = si->clone_bugfix_regs2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clone the memory mapped registers for our use - does not work on <4.5.2 (but is better this way)*/
|
||||
regs_area = clone_area(DRIVER_PREFIX " regs", (void **)®s, B_ANY_ADDRESS,
|
||||
B_READ_AREA | B_WRITE_AREA, si->regs_area);
|
||||
if (regs_area < 0)
|
||||
{
|
||||
result = regs_area;
|
||||
goto error1;
|
||||
}
|
||||
else
|
||||
{
|
||||
regs2_area = clone_area(DRIVER_PREFIX " regs2", (void **)®s2, B_ANY_ADDRESS,
|
||||
B_READ_AREA | B_WRITE_AREA, si->regs2_area);
|
||||
if (regs2_area < 0)
|
||||
{
|
||||
result = regs2_area;
|
||||
goto error2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*FIXME - print dma addresses*/
|
||||
//LOG(4,("DMA_virtual:%x\tDMA_physical:%x\tDMA_area:%x\n",si->dma_buffer,si->dma_buffer_pci,si->dma_buffer_area));
|
||||
|
||||
/* all done */
|
||||
goto error0;
|
||||
|
||||
error2:
|
||||
delete_area(regs_area);
|
||||
error1:
|
||||
delete_area(shared_info_area);
|
||||
error0:
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Clean up code shared between primary and cloned accelrants */
|
||||
static void uninit_common(void) {
|
||||
/* release the memory mapped registers */
|
||||
delete_area(regs2_area);
|
||||
delete_area(regs_area);
|
||||
/* a little cheap paranoia */
|
||||
regs = 0;
|
||||
regs2 = 0;
|
||||
/* release our copy of the shared info from the kernel driver */
|
||||
delete_area(shared_info_area);
|
||||
/* more cheap paranoia */
|
||||
si = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Initialize the accelerant. the_fd is the file handle of the device (in
|
||||
/dev/graphics) that has been opened by the app_server (or some test harness).
|
||||
We need to determine if the kernel driver and the accelerant are compatible.
|
||||
If they are, get the accelerant ready to handle other hook functions and
|
||||
report success or failure.
|
||||
*/
|
||||
status_t INIT_ACCELERANT(int the_fd) {
|
||||
status_t result;
|
||||
int pointer_reservation; //mem reserved for pointer
|
||||
int cnt; //used for iteration through the overlay buffers
|
||||
|
||||
if (1) {
|
||||
time_t now = time (NULL);
|
||||
// LOG not available from here to next LOG: NULL si
|
||||
MSG(("INIT_ACCELERANT: %s", ctime (&now)));
|
||||
}
|
||||
|
||||
/* note that we're the primary accelerant (accelerantIsClone is global) */
|
||||
accelerantIsClone = 0;
|
||||
|
||||
/* do the initialization common to both the primary and the clones */
|
||||
result = init_common(the_fd);
|
||||
|
||||
/* bail out if the common initialization failed */
|
||||
if (result != B_OK) goto error0;
|
||||
// LOG now available: !NULL si
|
||||
|
||||
/* call the device specific init code */
|
||||
result = mn_general_powerup();
|
||||
|
||||
/* bail out if it failed */
|
||||
if (result != B_OK) goto error1;
|
||||
|
||||
/*
|
||||
Now would be a good time to figure out what video modes your card supports.
|
||||
We'll place the list of modes in another shared area so all of the copies
|
||||
of the driver can see them. The primary copy of the accelerant (ie the one
|
||||
initialized with this routine) will own the "one true copy" of the list.
|
||||
Everybody else get's a read-only clone.
|
||||
*/
|
||||
result = create_mode_list();
|
||||
if (result != B_OK)
|
||||
{
|
||||
goto error1;
|
||||
}
|
||||
|
||||
/*
|
||||
Put the cursor at the start of the frame buffer. The typical 64x64 4 color
|
||||
(black, white, transparent, inverse) takes up 1024 bytes of RAM.
|
||||
*/
|
||||
/* Initialize the rest of the cursor information while we're here */
|
||||
si->cursor.width = 16;
|
||||
si->cursor.height = 16;
|
||||
si->cursor.hot_x = 0;
|
||||
si->cursor.hot_y = 0;
|
||||
si->cursor.x = 0;
|
||||
si->cursor.y = 0;
|
||||
|
||||
/*
|
||||
Put the frame buffer immediately following the cursor data. We store this
|
||||
info in a frame_buffer_config structure to make it convienient to return
|
||||
to the app_server later.
|
||||
*/
|
||||
pointer_reservation = 0;
|
||||
if (si->settings.hardcursor) pointer_reservation = si->ps.curmem_size;
|
||||
|
||||
si->fbc.frame_buffer = (void *)((char *)si->framebuffer+pointer_reservation);
|
||||
si->fbc.frame_buffer_dma = (void *)((char *)si->framebuffer_pci+pointer_reservation);
|
||||
|
||||
/* count of issued parameters or commands */
|
||||
si->engine.last_idle = si->engine.count = 0;
|
||||
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;
|
||||
|
||||
/* bail out if something failed */
|
||||
if (result != B_OK) goto error1;
|
||||
|
||||
/* initialise various cursor stuff*/
|
||||
mn_crtc_cursor_init();
|
||||
|
||||
/* ensure cursor state */
|
||||
SHOW_CURSOR(false);
|
||||
|
||||
/* a winner! */
|
||||
result = B_OK;
|
||||
goto error0;
|
||||
|
||||
error1:
|
||||
/*
|
||||
Initialization failed after init_common() succeeded, so we need to clean
|
||||
up before quiting.
|
||||
*/
|
||||
uninit_common();
|
||||
|
||||
error0:
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
Return the number of bytes required to hold the information required
|
||||
to clone the device.
|
||||
*/
|
||||
ssize_t ACCELERANT_CLONE_INFO_SIZE(void) {
|
||||
/*
|
||||
Since we're passing the name of the device as the only required
|
||||
info, return the size of the name buffer
|
||||
*/
|
||||
return B_OS_NAME_LENGTH; // apsed, was MAX_mn_DEVICE_NAME_LENGTH;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Return the info required to clone the device. void *data points to
|
||||
a buffer at least ACCELERANT_CLONE_INFO_SIZE() bytes in length.
|
||||
*/
|
||||
void GET_ACCELERANT_CLONE_INFO(void *data) {
|
||||
mn_device_name dn;
|
||||
status_t result;
|
||||
|
||||
/* call the kernel driver to get the device name */
|
||||
dn.magic = MN_PRIVATE_DATA_MAGIC;
|
||||
/* store the returned info directly into the passed buffer */
|
||||
dn.name = (char *)data;
|
||||
result = ioctl(fd, MN_DEVICE_NAME, &dn, sizeof(dn));
|
||||
}
|
||||
|
||||
/*
|
||||
Initialize a copy of the accelerant as a clone. void *data points to
|
||||
a copy of the data returned by GET_ACCELERANT_CLONE_INFO().
|
||||
*/
|
||||
status_t CLONE_ACCELERANT(void *data) {
|
||||
status_t result;
|
||||
char path[MAXPATHLEN];
|
||||
|
||||
/* the data is the device name */
|
||||
strcpy(path, "/dev");
|
||||
strcat(path, (const char *)data);
|
||||
/* open the device, the permissions aren't important */
|
||||
fd = open(path, B_READ_WRITE);
|
||||
if (fd < 0) {
|
||||
result = fd;
|
||||
goto error0;
|
||||
}
|
||||
|
||||
/* note that we're a clone accelerant */
|
||||
accelerantIsClone = 1;
|
||||
|
||||
/* call the shared initialization code */
|
||||
result = init_common(fd);
|
||||
|
||||
/* bail out if the common initialization failed */
|
||||
if (result != B_OK) goto error1;
|
||||
|
||||
/* get shared area for display modes */
|
||||
result = my_mode_list_area = clone_area(
|
||||
DRIVER_PREFIX " cloned display_modes",
|
||||
(void **)&my_mode_list,
|
||||
B_ANY_ADDRESS,
|
||||
B_READ_AREA,
|
||||
si->mode_area
|
||||
);
|
||||
if (result < B_OK) goto error2;
|
||||
|
||||
/* all done */
|
||||
LOG(4,("CLONE_ACCELERANT: cloning was succesfull.\n"));
|
||||
|
||||
result = B_OK;
|
||||
goto error0;
|
||||
|
||||
error2:
|
||||
/* free up the areas we cloned */
|
||||
uninit_common();
|
||||
error1:
|
||||
/* close the device we opened */
|
||||
close(fd);
|
||||
error0:
|
||||
return result;
|
||||
}
|
||||
|
||||
void UNINIT_ACCELERANT(void)
|
||||
{
|
||||
if (accelerantIsClone)
|
||||
LOG(4,("UNINIT_ACCELERANT: shutting down clone accelerant.\n"));
|
||||
else
|
||||
LOG(4,("UNINIT_ACCELERANT: shutting down primary accelerant.\n"));
|
||||
|
||||
/*delete benaphore*/
|
||||
DELETE_BEN(si->engine.lock);
|
||||
DELETE_BEN(si->overlay.lock);
|
||||
/* free our mode list area */
|
||||
delete_area(my_mode_list_area);
|
||||
/* paranoia */
|
||||
my_mode_list = 0;
|
||||
/* release our cloned data */
|
||||
uninit_common();
|
||||
/* close the file handle ONLY if we're the clone */
|
||||
if (accelerantIsClone) close(fd);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
SubDir OBOS_TOP src add-ons accelerants neomagic ;
|
||||
|
||||
UsePrivateHeaders graphics ;
|
||||
UsePrivateHeaders [ FDirName graphics neomagic ] ;
|
||||
UseHeaders [ FDirName $(SUBDIR) engine ] ;
|
||||
|
||||
|
||||
Addon nm.accelerant : accelerants :
|
||||
Acceleration.c
|
||||
Cursor.c
|
||||
EngineManagment.c
|
||||
GetAccelerantHook.c
|
||||
GetDeviceInfo.c
|
||||
GetModeInfo.c
|
||||
GetTimingConstraints.c
|
||||
GlobalData.c
|
||||
InitAccelerant.c
|
||||
Overlay.c
|
||||
ProposeDisplayMode.c
|
||||
SetDisplayMode.c
|
||||
: false : libneomagic_engine.a
|
||||
;
|
||||
|
||||
Depends nm.accelerant : nm.driver ;
|
||||
|
||||
SubInclude OBOS_TOP src add-ons accelerants neomagic engine ;
|
||||
@@ -0,0 +1,648 @@
|
||||
/* Written by Rudolf Cornelissen 05-2002/03-2003 */
|
||||
|
||||
/* 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 */
|
||||
/* Note:
|
||||
* G200-G550 can all do YUV4:2:0 2-plane colorspace as well,
|
||||
* G200 does not support RGB modes while > G200 do (but with limited scaling and without filtering),
|
||||
* G200 does not support YUV4:2:0 3-plane mode while > G200 do.
|
||||
* 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;
|
||||
}
|
||||
|
||||
/* interlaced VGA is not supported by G200-G550 BES */
|
||||
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 (like the keying method) are supported on the current
|
||||
* Desktop colorspace */
|
||||
//fixme? Or are we talking about the overlay input bitmap's colorspace?
|
||||
switch (a_color_space)
|
||||
{
|
||||
default:
|
||||
/* fixme: for now 'direct 32bit' desktop colorspace assumed */
|
||||
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 = %dKb\n",si->ps.memory_size));
|
||||
|
||||
/* 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:
|
||||
/* check if slopspace is needed: compatible settings choosen for now:
|
||||
* G200 can do with ~0x0003 while > G200 need ~x0007.
|
||||
* Optimized settings for G200 could reduce CPU load a tiny little bit there... */
|
||||
/* fixme: update needed for DVDmax support to adhere to CRTC2 constraints:
|
||||
* case display_mode == B_RGB16: multiple = 32
|
||||
* case display_mode == B_RGB32: multiple = 16 */
|
||||
if (width == (width & ~0x0007))
|
||||
{
|
||||
si->overlay.myBuffer[offset].width = width;
|
||||
}
|
||||
else
|
||||
{
|
||||
si->overlay.myBuffer[offset].width = (width & ~0x0007) + 8;
|
||||
}
|
||||
si->overlay.myBuffer[offset].bytes_per_row = 2 * si->overlay.myBuffer[offset].width;
|
||||
|
||||
/* check if the requested horizontal pitch is supported:
|
||||
* G200 max. pitch is 4092 pixels, > G200 max pitch is 4088 pixels for this colorspace.
|
||||
* Compatible check done, has no downside consequences here. */
|
||||
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;
|
||||
|
||||
// case 0xffff://fixme: which one(s)?
|
||||
//fixme: 4:2:0 2-plane supported format, should be selected only if detected
|
||||
/* check if slopspace is needed: compatible settings choosen for now:
|
||||
* G200 can do with ~0x0007 while > G200 need ~x001f.
|
||||
* Optimized settings for G200 could reduce CPU load a tiny little bit there... */
|
||||
/* if (width == (width & ~0x001f))
|
||||
{
|
||||
si->overlay.myBuffer[offset].width = width;
|
||||
}
|
||||
else
|
||||
{
|
||||
si->overlay.myBuffer[offset].width = (width & ~0x001f) + 32;
|
||||
}
|
||||
*/ /* assuming Y-plane only bytes_per_row are requested here */
|
||||
/* si->overlay.myBuffer[offset].bytes_per_row = si->overlay.myBuffer[offset].width;
|
||||
*/
|
||||
/* check if the requested horizontal pitch is supported:
|
||||
* G200 max. pitch is 4088 pixels, > G200 max pitch is 4064 pixels for this colorspace.
|
||||
* Compatible check done, has no real downside consequences here. */
|
||||
/* if (si->overlay.myBuffer[offset].width > 4064)
|
||||
{
|
||||
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 nm.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 * 1024));
|
||||
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) */
|
||||
/* 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 nm.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_pci)) + (si->ps.memory_size * 1024));
|
||||
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:
|
||||
/* G200 can work with 3, > G200 need 7. Compatible setting returned for now.
|
||||
* Note: this has to be in sync with the slopspace setup during buffer allocation.. */
|
||||
oc->view.width_alignment = 7;
|
||||
break;
|
||||
|
||||
// case 0xffff://fixme: which one(s)? (4:2:0 supported formats. Not yet used...)
|
||||
/* G200 can work with 7, > G200 need 31. Compatible setting returned for now.
|
||||
* 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;
|
||||
/* G200-G550 can output upto and including 2048 pixels in width */
|
||||
if (dm->virtual_width > 2048)
|
||||
{
|
||||
oc->window.width.max = 2048;
|
||||
}
|
||||
else
|
||||
{
|
||||
oc->window.width.max = dm->virtual_width;
|
||||
}
|
||||
oc->window.height.min = 2;
|
||||
/* G200-G550 can output upto and including 2048 pixels in height */
|
||||
if (dm->virtual_height > 2048)
|
||||
{
|
||||
oc->window.height.max = 2048;
|
||||
}
|
||||
else
|
||||
{
|
||||
oc->window.height.max = dm->virtual_height;
|
||||
}
|
||||
|
||||
/* G200-G550 scaling restrictions */
|
||||
/* Adjust horizontal restrictions if pixelclock is above BES max. speed! */
|
||||
/* Note: If RGB32 is implemented no scaling is supported! */
|
||||
if (si->dm.timing.pixel_clock > BESMAXSPEED)
|
||||
{
|
||||
oc->h_scale.min = (1 * 2) / (32 - (1 / (float)16384));
|
||||
oc->h_scale.max = (16384 * 2)/(float)(ob->width - si->overlay.myBufInfo[offset].slopspace);
|
||||
}
|
||||
else
|
||||
{
|
||||
oc->h_scale.min = 1 / (32 - (1 / (float)16384));
|
||||
oc->h_scale.max = 16384/(float)(ob->width - si->overlay.myBufInfo[offset].slopspace);
|
||||
}
|
||||
oc->v_scale.min = 1 / (32 - (1 / (float)16384));
|
||||
oc->v_scale.max = 16384/(float)ob->height;
|
||||
|
||||
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 */
|
||||
{
|
||||
|
||||
mn_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));
|
||||
|
||||
mn_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
|
||||
Other authors for nm driver:
|
||||
Rudolf Cornelissen 4/2003-6/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00400000
|
||||
|
||||
#include "acc_std.h"
|
||||
|
||||
#define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC)
|
||||
/* mode flags will be setup as status info by PROPOSEMODE! */
|
||||
#define MODE_FLAGS 0
|
||||
#define MODE_COUNT (sizeof (mode_list) / sizeof (display_mode))
|
||||
|
||||
/*some monitors only handle a fixed set of modes*/
|
||||
#include "valid_mode_list"
|
||||
|
||||
/* Standard VESA modes */
|
||||
static const display_mode mode_list[] = {
|
||||
{ { 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */
|
||||
{ { 27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* 640X480X60Hz */
|
||||
{ { 30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* SVGA_640X480X60HzNI */
|
||||
{ { 31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(640X480X8.Z1) */
|
||||
{ { 31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */
|
||||
{ { 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */
|
||||
{ { 38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* SVGA_800X600X56HzNI */
|
||||
{ { 40000, 800, 840, 968, 1056, 600, 601, 605, 628, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) */
|
||||
{ { 49500, 800, 816, 896, 1056, 600, 601, 604, 625, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(800X600X8.Z1) */
|
||||
{ { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(800X600X8.Z1) */
|
||||
{ { 56250, 800, 832, 896, 1048, 600, 601, 604, 631, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(800X600X8.Z1) */
|
||||
{ { 65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) */
|
||||
{ { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(1024X768X8.Z1) */
|
||||
{ { 78750, 1024, 1040, 1136, 1312, 768, 769, 772, 800, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1024X768X8.Z1) */
|
||||
{ { 94500, 1024, 1072, 1168, 1376, 768, 769, 772, 808, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1024X768X8.Z1) */
|
||||
{ { 94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */
|
||||
{ { 97800, 1152, 1216, 1344, 1552, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */
|
||||
{ { 108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1152X864X8.Z1) */
|
||||
{ { 108000, 1280, 1328, 1440, 1680, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X1024X8.Z1) */
|
||||
};
|
||||
|
||||
/*
|
||||
Check mode is between low and high limits
|
||||
returns:
|
||||
B_OK - found one
|
||||
B_BAD_VALUE - mode can be made, but outside limits
|
||||
B_ERROR - not possible
|
||||
*/
|
||||
/* BOUNDS WARNING:
|
||||
* BeOS (tested R5.0.3PE) is failing BWindowScreen.SetFrameBuffer() if PROPOSEMODE
|
||||
* returns B_BAD_VALUE. It's called by the OS with target, low and high set to
|
||||
* have the same settings for BWindowScreen!
|
||||
* Which means we should not return B_BAD_VALUE on anything except for deviations on:
|
||||
* display_mode.virtual_width;
|
||||
* display_mode.virtual_height;
|
||||
* display_mode.timing.h_display;
|
||||
* display_mode.timing.v_display;
|
||||
*/
|
||||
/* Note:
|
||||
* The target mode should be modified to correspond to the mode as it can be made. */
|
||||
status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const display_mode *high)
|
||||
{
|
||||
status_t status = B_OK;
|
||||
float pix_clock_found;
|
||||
uint8 m,n,p;
|
||||
status_t result;
|
||||
uint32 row_bytes, pointer_reservation;
|
||||
double target_refresh = ((double)target->timing.pixel_clock * 1000.0) /
|
||||
(
|
||||
(double)target->timing.h_total *
|
||||
(double)target->timing.v_total
|
||||
);
|
||||
bool
|
||||
want_same_width = target->timing.h_display == target->virtual_width,
|
||||
want_same_height = target->timing.v_display == target->virtual_height;
|
||||
|
||||
LOG(1, ("PROPOSEMODE: (ENTER) requested virtual_width %d, virtual_height %d\n",
|
||||
target->virtual_width, target->virtual_height));
|
||||
|
||||
/*check valid list:
|
||||
if (VALID_REQUIRED is set)
|
||||
{
|
||||
if (find modes with same size)
|
||||
{
|
||||
pick one with nearest pixel clock
|
||||
}
|
||||
else
|
||||
{
|
||||
pick next largest with nearest pixel clock and modify visible portion as far as possible
|
||||
}
|
||||
}
|
||||
*/
|
||||
#ifdef VALID_MODE_REQUIRED
|
||||
{
|
||||
int i;
|
||||
int closest_mode_ptr;
|
||||
uint32 closest_mode_clock;
|
||||
|
||||
LOG(1, ("PROPOSEMODE: valid mode required!\n"));
|
||||
|
||||
closest_mode_ptr = 0xbad;
|
||||
closest_mode_clock = 0;
|
||||
for (i=0;i<VALID_MODES;i++)
|
||||
{
|
||||
/*check size is ok and clock is better than any found before*/
|
||||
if(
|
||||
target->timing.h_display==valid_mode_list[i].h_display &&
|
||||
target->timing.v_display==valid_mode_list[i].v_display
|
||||
)
|
||||
{
|
||||
if (
|
||||
abs(valid_mode_list[i].pixel_clock-target->timing.pixel_clock)<
|
||||
abs(closest_mode_clock-target->timing.pixel_clock)
|
||||
)
|
||||
{
|
||||
closest_mode_clock=valid_mode_list[i].pixel_clock;
|
||||
closest_mode_ptr=i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (closest_mode_ptr==0xbad)/*if no modes of correct size*/
|
||||
{
|
||||
LOG(4, ("PROPOSEMODE: no valid mode found, aborted.\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
target->timing=valid_mode_list[closest_mode_ptr];
|
||||
target_refresh = ((double)target->timing.pixel_clock * 1000.0) / /*I require this refresh*/
|
||||
((double)target->timing.h_total * (double)target->timing.v_total);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*find a nearby valid timing from that given*/
|
||||
result = mn_crtc_validate_timing
|
||||
(
|
||||
&target->timing.h_display, &target->timing.h_sync_start, &target->timing.h_sync_end, &target->timing.h_total,
|
||||
&target->timing.v_display, &target->timing.v_sync_start, &target->timing.v_sync_end, &target->timing.v_total
|
||||
);
|
||||
if (result == B_ERROR)
|
||||
{
|
||||
LOG(4, ("PROPOSEMODE: could not validate timing, aborted.\n"));
|
||||
return result;
|
||||
}
|
||||
|
||||
/* validate display vs. virtual */
|
||||
if ((target->timing.h_display > target->virtual_width) || want_same_width)
|
||||
target->virtual_width = target->timing.h_display;
|
||||
if ((target->timing.v_display > target->virtual_height) || want_same_height)
|
||||
target->virtual_height = target->timing.v_display;
|
||||
|
||||
/* nail virtual size and 'subsequently' calculate rowbytes */
|
||||
result = mn_general_validate_pic_size (target, &row_bytes);
|
||||
if (result == B_ERROR)
|
||||
{
|
||||
LOG(4, ("PROPOSEMODE: could not validate virtual picture size, aborted.\n"));
|
||||
return result;
|
||||
}
|
||||
|
||||
/*check if virtual_width is still within the requested limits*/
|
||||
if ((target->virtual_width < low->virtual_width) ||
|
||||
(target->virtual_width > high->virtual_width))
|
||||
{
|
||||
status = B_BAD_VALUE;
|
||||
LOG(4, ("PROPOSEMODE: WARNING: virtual_width deviates too much\n"));
|
||||
}
|
||||
|
||||
/*check if timing found is within the requested horizontal limits*/
|
||||
if ((target->timing.h_display < low->timing.h_display) ||
|
||||
(target->timing.h_display > high->timing.h_display) ||
|
||||
(target->timing.h_sync_start < low->timing.h_sync_start) ||
|
||||
(target->timing.h_sync_start > high->timing.h_sync_start) ||
|
||||
(target->timing.h_sync_end < low->timing.h_sync_end) ||
|
||||
(target->timing.h_sync_end > high->timing.h_sync_end) ||
|
||||
(target->timing.h_total < low->timing.h_total) ||
|
||||
(target->timing.h_total > high->timing.h_total))
|
||||
{
|
||||
/* BWindowScreen workaround: we accept everything except h_display deviations */
|
||||
if ((target->timing.h_display < low->timing.h_display) ||
|
||||
(target->timing.h_display > high->timing.h_display))
|
||||
{
|
||||
status = B_BAD_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = B_OK;
|
||||
}
|
||||
LOG(4, ("PROPOSEMODE: WARNING: horizontal timing deviates too much\n"));
|
||||
}
|
||||
|
||||
/*check if timing found is within the requested vertical limits*/
|
||||
if (
|
||||
(target->timing.v_display < low->timing.v_display) ||
|
||||
(target->timing.v_display > high->timing.v_display) ||
|
||||
(target->timing.v_sync_start < low->timing.v_sync_start) ||
|
||||
(target->timing.v_sync_start > high->timing.v_sync_start) ||
|
||||
(target->timing.v_sync_end < low->timing.v_sync_end) ||
|
||||
(target->timing.v_sync_end > high->timing.v_sync_end) ||
|
||||
(target->timing.v_total < low->timing.v_total) ||
|
||||
(target->timing.v_total > high->timing.v_total)
|
||||
)
|
||||
{
|
||||
/* BWindowScreen workaround: we accept everything except v_display deviations */
|
||||
if ((target->timing.v_display < low->timing.v_display) ||
|
||||
(target->timing.v_display > high->timing.v_display))
|
||||
{
|
||||
status = B_BAD_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = B_OK;
|
||||
}
|
||||
LOG(4, ("PROPOSEMODE: WARNING: vertical timing deviates too much\n"));
|
||||
}
|
||||
|
||||
/* adjust pixelclock for possible timing modifications done above */
|
||||
target->timing.pixel_clock = target_refresh * ((double)target->timing.h_total) * ((double)target->timing.v_total) / 1000.0;
|
||||
|
||||
/* Now find the nearest valid pixelclock we actually can setup for the target mode,
|
||||
* this also makes sure we don't generate more pixel bandwidth than the device can handle */
|
||||
result = mn_dac_pix_pll_find(*target,&pix_clock_found,&m,&n,&p);
|
||||
/* update the target mode */
|
||||
target->timing.pixel_clock = (pix_clock_found * 1000);
|
||||
|
||||
/* note if we fell outside the limits */
|
||||
if ((target->timing.pixel_clock < low->timing.pixel_clock) ||
|
||||
(target->timing.pixel_clock > high->timing.pixel_clock)
|
||||
)
|
||||
{
|
||||
/* BWindowScreen workaround: we accept deviations <= 1Mhz */
|
||||
if ((target->timing.pixel_clock < (low->timing.pixel_clock - 1000)) ||
|
||||
(target->timing.pixel_clock > (high->timing.pixel_clock + 1000)))
|
||||
{
|
||||
status = B_BAD_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = B_OK;
|
||||
}
|
||||
LOG(4, ("PROPOSEMODE: WARNING: pixelclock deviates too much\n"));
|
||||
}
|
||||
|
||||
/* checkout space needed for hardcursor (if any) */
|
||||
pointer_reservation = 0;
|
||||
if (si->settings.hardcursor) pointer_reservation = si->ps.curmem_size;
|
||||
/* memory requirement for frame buffer */
|
||||
if ((row_bytes * target->virtual_height) >
|
||||
((si->ps.memory_size * 1024) - pointer_reservation))
|
||||
{
|
||||
target->virtual_height =
|
||||
((si->ps.memory_size * 1024) - pointer_reservation) / row_bytes;
|
||||
}
|
||||
if (target->virtual_height < target->timing.v_display)
|
||||
{
|
||||
LOG(4,("PROPOSEMODE: not enough memory for current mode, aborted.\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
LOG(4,("PROPOSEMODE: validated virtual_width %d, virtual_height %d pixels\n",
|
||||
target->virtual_width, target->virtual_height));
|
||||
|
||||
if ((target->virtual_height < low->virtual_height) ||
|
||||
(target->virtual_height > high->virtual_height))
|
||||
{
|
||||
status = B_BAD_VALUE;
|
||||
LOG(4, ("PROPOSEMODE: WARNING: virtual_height deviates too much\n"));
|
||||
}
|
||||
|
||||
/* setup status flags */
|
||||
LOG(1, ("PROPOSEMODE: initial modeflags: $%08x\n", target->flags));
|
||||
/* preset to singlehead card without TVout, no overlay support and no hardcursor.
|
||||
* also advice system that app_server and acc engine may touch the framebuffer
|
||||
* simultaneously (fixed). */
|
||||
//fixme: introduce dualhead_clone_only flag compatible with matrox so the same prefs
|
||||
//util can be used
|
||||
target->flags &=
|
||||
~(DUALHEAD_CAPABLE | TV_CAPABLE | B_SUPPORTS_OVERLAYS | B_IO_FB_NA);
|
||||
/* we always allow parallel access (fixed), the DAC is always in 'enhanced'
|
||||
* mode (fixed), and all modes support DPMS (fixed);
|
||||
* We support scrolling and panning in every mode, so we 'send a signal' to
|
||||
* BWindowScreen.CanControlFrameBuffer() by setting B_SCROLL. */
|
||||
target->flags |= (B_PARALLEL_ACCESS | B_8_BIT_DAC | B_DPMS | B_SCROLL);
|
||||
|
||||
/* set HARDWARE_CURSOR mode if suitable */
|
||||
if (si->settings.hardcursor)
|
||||
target->flags |= B_HARDWARE_CURSOR;
|
||||
|
||||
/* set SUPPORTS_OVERLAYS if suitable */
|
||||
if (si->ps.card_type > NM2070)
|
||||
target->flags |= B_SUPPORTS_OVERLAYS;
|
||||
|
||||
LOG(1, ("PROPOSEMODE: validated status modeflags: $%08x\n", target->flags));
|
||||
|
||||
/* overrule timing command flags to be (fixed) blank_pedestal = 0.0IRE,
|
||||
* progressive scan (fixed), and sync_on_green not used */
|
||||
target->timing.flags &= ~(B_BLANK_PEDESTAL | B_TIMING_INTERLACED | B_SYNC_ON_GREEN);
|
||||
/* The HSYNC and VSYNC command flags are actually executed by the driver. */
|
||||
|
||||
if (status == B_OK) LOG(4, ("PROPOSEMODE: completed successfully.\n"));
|
||||
else LOG(4, ("PROPOSEMODE: mode can be made, but outside given limits.\n"));
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Return the number of modes this device will return from GET_MODE_LIST().
|
||||
This is precalculated in create_mode_list (called from InitAccelerant stuff)
|
||||
*/
|
||||
uint32 ACCELERANT_MODE_COUNT(void)
|
||||
{
|
||||
LOG(1, ("ACCELERANT_MODE_COUNT: the modelist contains %d modes\n",si->mode_count));
|
||||
|
||||
return si->mode_count;
|
||||
}
|
||||
|
||||
/* Copy the list of guaranteed supported video modes to the location provided.*/
|
||||
status_t GET_MODE_LIST(display_mode *dm)
|
||||
{
|
||||
LOG(1, ("GET_MODE_LIST: exporting the modelist created before.\n"));
|
||||
|
||||
memcpy(dm, my_mode_list, si->mode_count * sizeof(display_mode));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Create a list of display_modes to pass back to the caller.*/
|
||||
status_t create_mode_list(void) {
|
||||
size_t max_size;
|
||||
uint32
|
||||
i, j,
|
||||
pix_clk_range;
|
||||
const display_mode
|
||||
*src;
|
||||
display_mode
|
||||
*dst,
|
||||
low,
|
||||
high;
|
||||
|
||||
color_space spaces[4] = {B_RGB24_LITTLE,B_RGB16_LITTLE,B_RGB15_LITTLE,B_CMAP8};
|
||||
|
||||
/* figure out how big the list could be, and adjust up to nearest multiple of B_PAGE_SIZE*/
|
||||
max_size = (((MODE_COUNT * 4) * sizeof(display_mode)) + (B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1);
|
||||
/* create an area to hold the info */
|
||||
si->mode_area = my_mode_list_area =
|
||||
create_area("nm accelerant mode info", (void **)&my_mode_list, B_ANY_ADDRESS, max_size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
||||
if (my_mode_list_area < B_OK) return my_mode_list_area;
|
||||
|
||||
/* walk through our predefined list and see which modes fit this device */
|
||||
src = mode_list;
|
||||
dst = my_mode_list;
|
||||
si->mode_count = 0;
|
||||
for (i = 0; i < MODE_COUNT; i++) {
|
||||
/* set ranges for acceptable values */
|
||||
low = high = *src;
|
||||
/* range is 6.25% of default clock: arbitrarily picked */
|
||||
pix_clk_range = low.timing.pixel_clock >> 5;
|
||||
low.timing.pixel_clock -= pix_clk_range;
|
||||
high.timing.pixel_clock += pix_clk_range;
|
||||
/* 'some cards need wider virtual widths for certain modes':
|
||||
* Not true. They might need a wider pitch, but this is _not_ reflected in
|
||||
* virtual_width, but in fbc.bytes_per_row. */
|
||||
//So disable next line:
|
||||
//high.virtual_width = 4096;
|
||||
/* do it once for each depth we want to support */
|
||||
for (j = 0; j < (sizeof(spaces) / sizeof(color_space)); j++)
|
||||
{
|
||||
/* set target values */
|
||||
*dst = *src;
|
||||
/* poke the specific space */
|
||||
dst->space = low.space = high.space = spaces[j];
|
||||
/* ask for a compatible mode */
|
||||
/* We have to check for B_OK, because otherwise the pix_clk_range
|
||||
* won't be taken into account!! */
|
||||
//So don't do this:
|
||||
//if (PROPOSE_DISPLAY_MODE(dst, &low, &high) != B_ERROR) {
|
||||
//Instead, do this:
|
||||
if (PROPOSE_DISPLAY_MODE(dst, &low, &high) == B_OK) {
|
||||
/* count it, and move on to next mode */
|
||||
dst++;
|
||||
si->mode_count++;
|
||||
}
|
||||
}
|
||||
/* advance to next mode */
|
||||
src++;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
|
||||
Other authors:
|
||||
Rudolf Cornelissen 4/2003-6/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00200000
|
||||
|
||||
#include "acc_std.h"
|
||||
|
||||
/*
|
||||
Enable/Disable interrupts. Just a wrapper around the
|
||||
ioctl() to the kernel driver.
|
||||
*/
|
||||
static void interrupt_enable(bool flag) {
|
||||
status_t result;
|
||||
mn_set_bool_state sbs;
|
||||
|
||||
/* set the magic number so the driver knows we're for real */
|
||||
sbs.magic = MN_PRIVATE_DATA_MAGIC;
|
||||
sbs.do_it = flag;
|
||||
/* contact driver and get a pointer to the registers and shared data */
|
||||
result = ioctl(fd, MN_RUN_INTERRUPTS, &sbs, sizeof(sbs));
|
||||
}
|
||||
|
||||
/* First validate the mode, then call lots of bit banging stuff to set the mode(s)! */
|
||||
status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
{
|
||||
/* BOUNDS WARNING:
|
||||
* It's impossible to deviate whatever small amount in a display_mode if the lower
|
||||
* and upper limits are the same!
|
||||
* Besides:
|
||||
* BeOS (tested R5.0.3PE) is failing BWindowScreen::SetFrameBuffer() if PROPOSEMODE
|
||||
* returns B_BAD_VALUE!
|
||||
* Which means PROPOSEMODE should not return that on anything except on
|
||||
* deviations for:
|
||||
* display_mode.virtual_width;
|
||||
* display_mode.virtual_height;
|
||||
* display_mode.timing.h_display;
|
||||
* display_mode.timing.v_display;
|
||||
* So:
|
||||
* We don't use bounds here by making sure bounds and target are the same struct!
|
||||
* (See the call to PROPOSE_DISPLAY_MODE below) */
|
||||
display_mode /*bounds,*/ target;
|
||||
|
||||
uint8 colour_depth = 24;
|
||||
uint32 startadd;
|
||||
|
||||
bool display, h, v;
|
||||
|
||||
/* if internal panel is active we don't touch the CRTC timing and the pixelPLL */
|
||||
bool crt_only = true;
|
||||
|
||||
/* Adjust mode to valid one and fail if invalid */
|
||||
target /*= bounds*/ = *mode_to_set;
|
||||
/* show the mode bits */
|
||||
LOG(1, ("SETMODE: (ENTER) initial modeflags: $%08x\n", target.flags));
|
||||
LOG(1, ("SETMODE: requested target pixelclock %dkHz\n", target.timing.pixel_clock));
|
||||
LOG(1, ("SETMODE: requested virtual_width %d, virtual_height %d\n",
|
||||
target.virtual_width, target.virtual_height));
|
||||
|
||||
/* See BOUNDS WARNING above... */
|
||||
if (PROPOSE_DISPLAY_MODE(&target, &target, &target) == B_ERROR) return B_ERROR;
|
||||
|
||||
/* if we have the flatpanel turned on modify visible part of mode if nessesary */
|
||||
if (nm_general_output_read() & 0x02)
|
||||
{
|
||||
LOG(4,("SETMODE: internal flatpanel enabled, skipping CRTC/pixelPLL setup\n"));
|
||||
crt_only = false;
|
||||
}
|
||||
|
||||
/* disable interrupts using the kernel driver */
|
||||
interrupt_enable(false);
|
||||
|
||||
/* find current DPMS state, then turn off screen(s) */
|
||||
mn_crtc_dpms_fetch(&display, &h, &v);
|
||||
mn_crtc_dpms(false, false, false);
|
||||
|
||||
/*where in framebuffer the screen is (should this be dependant on previous MOVEDISPLAY?)*/
|
||||
startadd = si->fbc.frame_buffer - si->framebuffer;
|
||||
|
||||
/* Perform the mode switch */
|
||||
{
|
||||
status_t status = B_OK;
|
||||
int colour_mode = BPP24;
|
||||
|
||||
switch(target.space)
|
||||
{
|
||||
case B_CMAP8: colour_depth = 8; colour_mode = BPP8; break;
|
||||
case B_RGB15_LITTLE: colour_depth = 16; colour_mode = BPP15; break;
|
||||
case B_RGB16_LITTLE: colour_depth = 16; colour_mode = BPP16; break;
|
||||
case B_RGB24_LITTLE: colour_depth = 24; colour_mode = BPP24; break;
|
||||
default:
|
||||
LOG(8,("SETMODE: Invalid colorspace $%08x\n", target.space));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/* calculate and set new mode bytes_per_row */
|
||||
mn_general_validate_pic_size (&target, &si->fbc.bytes_per_row);
|
||||
|
||||
/* set the pixelclock PLL */
|
||||
if (crt_only)
|
||||
{
|
||||
status = mn_dac_set_pix_pll(target);
|
||||
if (status == B_ERROR)
|
||||
LOG(8,("CRTC: error setting pixelclock\n"));
|
||||
}
|
||||
|
||||
/* set the colour depth for CRTC1 and the DAC */
|
||||
mn_dac_mode(colour_mode, 1.0);
|
||||
mn_crtc_depth(colour_mode);
|
||||
|
||||
/* set the display pitch */
|
||||
mn_crtc_set_display_pitch();
|
||||
|
||||
/* tell the card what memory to display */
|
||||
mn_crtc_set_display_start(startadd,colour_depth);
|
||||
|
||||
/* enable primary analog output */
|
||||
//fixme: choose output connector(s)
|
||||
|
||||
/* set the timing */
|
||||
mn_crtc_set_timing(target, crt_only);
|
||||
|
||||
/* always setup centering so a KB BIOS switch to flatpanel will go OK... */
|
||||
mn_crtc_center(target);
|
||||
}
|
||||
|
||||
/* update driver's mode store */
|
||||
si->dm = target;
|
||||
|
||||
/* turn screen on */
|
||||
mn_crtc_dpms(display,h,v);
|
||||
|
||||
/* set up acceleration for this mode */
|
||||
si->dm.virtual_height += 1;//for clipping!
|
||||
// mn_acc_init();
|
||||
si->dm.virtual_height -= 1;
|
||||
|
||||
/* log currently selected output */
|
||||
nm_general_output_select();
|
||||
|
||||
MSG(("SETMODE: booted since %f mS\n", system_time()/1000.0));
|
||||
|
||||
/* enable interrupts using the kernel driver */
|
||||
interrupt_enable(true);
|
||||
|
||||
/* Tune RAM CAS-latency if needed. Must be done *here*! */
|
||||
nm_set_cas_latency();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
Set which pixel of the virtual frame buffer will show up in the
|
||||
top left corner of the display device. Used for page-flipping
|
||||
games and virtual desktops.
|
||||
*/
|
||||
status_t MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start)
|
||||
{
|
||||
uint8 colour_depth;
|
||||
uint32 startadd;
|
||||
|
||||
uint16 h_display = si->dm.timing.h_display; /* local copy needed for flatpanel */
|
||||
uint16 v_display = si->dm.timing.v_display; /* local copy needed for flatpanel */
|
||||
|
||||
LOG(4,("MOVE_DISPLAY: h %d, v %d\n", h_display_start, v_display_start));
|
||||
|
||||
/* reset lower bits, don't return an error! */
|
||||
switch(si->dm.space)
|
||||
{
|
||||
case B_CMAP8:
|
||||
colour_depth=8;
|
||||
h_display_start &= ~0x03;
|
||||
break;
|
||||
case B_RGB15_LITTLE: case B_RGB16_LITTLE:
|
||||
colour_depth=16;
|
||||
h_display_start &= ~0x01;
|
||||
break;
|
||||
case B_RGB24_LITTLE:
|
||||
colour_depth=24;
|
||||
h_display_start &= ~0x03;
|
||||
break;
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/* if internal panel is active correct visible screensize! */
|
||||
if (nm_general_output_read() & 0x02)
|
||||
{
|
||||
if (h_display > si->ps.panel_width) h_display = si->ps.panel_width;
|
||||
if (v_display > si->ps.panel_height) v_display = si->ps.panel_height;
|
||||
}
|
||||
|
||||
/* do not run past end of display */
|
||||
if ((h_display + h_display_start) > si->dm.virtual_width)
|
||||
return B_ERROR;
|
||||
if ((v_display + v_display_start) > si->dm.virtual_height)
|
||||
return B_ERROR;
|
||||
|
||||
/* everybody remember where we parked... */
|
||||
si->dm.h_display_start = h_display_start;
|
||||
si->dm.v_display_start = v_display_start;
|
||||
|
||||
/* actually set the registers */
|
||||
startadd = v_display_start * si->fbc.bytes_per_row;
|
||||
startadd += h_display_start * (colour_depth >> 3);
|
||||
startadd += si->fbc.frame_buffer - si->framebuffer;
|
||||
|
||||
interrupt_enable(false);
|
||||
|
||||
mn_crtc_set_display_start(startadd,colour_depth);
|
||||
|
||||
interrupt_enable(true);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* Set the indexed color palette. */
|
||||
void SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags) {
|
||||
int i;
|
||||
uint8 *r,*g,*b;
|
||||
|
||||
/* Protect gamma correction when not in CMAP8 */
|
||||
if (si->dm.space != B_CMAP8) return;
|
||||
|
||||
r = si->color_data;
|
||||
g = r + 256;
|
||||
b = g + 256;
|
||||
|
||||
i = first;
|
||||
while (count--)
|
||||
{
|
||||
r[i] = *color_data++;
|
||||
g[i] = *color_data++;
|
||||
b[i] = *color_data++;
|
||||
i++;
|
||||
}
|
||||
mn_dac_palette(r,g,b, 256);
|
||||
}
|
||||
|
||||
|
||||
/* masks for DPMS control bits */
|
||||
/*
|
||||
enum
|
||||
{
|
||||
H_SYNC_OFF = 0x01,
|
||||
V_SYNC_OFF = 0x02,
|
||||
DISPLAY_OFF = 0x04,
|
||||
BITSMASK = (H_SYNC_OFF | V_SYNC_OFF | DISPLAY_OFF)
|
||||
};
|
||||
*/
|
||||
|
||||
/* Put the display into one of the Display Power Management modes. */
|
||||
status_t SET_DPMS_MODE(uint32 dpms_flags)
|
||||
{
|
||||
interrupt_enable(false);
|
||||
|
||||
LOG(4,("SET_DPMS_MODE: $%08x\n", dpms_flags));
|
||||
|
||||
switch(dpms_flags)
|
||||
{
|
||||
case B_DPMS_ON: /* H: on, V: on */
|
||||
mn_crtc_dpms(true, true , true);
|
||||
break;
|
||||
case B_DPMS_STAND_BY:
|
||||
mn_crtc_dpms(false, false, true);
|
||||
break;
|
||||
case B_DPMS_SUSPEND:
|
||||
mn_crtc_dpms(false, true, false);
|
||||
break;
|
||||
case B_DPMS_OFF: /* H: off, V: off, display off */
|
||||
mn_crtc_dpms(false, false, false);
|
||||
break;
|
||||
default:
|
||||
LOG(8,("SET_DPMS_MODE: Invalid DPMS settings) $%08x\n", dpms_flags));
|
||||
interrupt_enable(true);
|
||||
return B_ERROR;
|
||||
}
|
||||
interrupt_enable(true);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* Report device DPMS capabilities. */
|
||||
uint32 DPMS_CAPABILITIES(void)
|
||||
{
|
||||
return (B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF);
|
||||
}
|
||||
|
||||
|
||||
/* Return the current DPMS mode. */
|
||||
uint32 DPMS_MODE(void)
|
||||
{
|
||||
bool display, h, v;
|
||||
|
||||
interrupt_enable(false);
|
||||
mn_crtc_dpms_fetch(&display, &h, &v);
|
||||
interrupt_enable(true);
|
||||
|
||||
if (display && h && v)
|
||||
return B_DPMS_ON;
|
||||
else if(v)
|
||||
return B_DPMS_STAND_BY;
|
||||
else if(h)
|
||||
return B_DPMS_SUSPEND;
|
||||
else
|
||||
return B_DPMS_OFF;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#if !defined(GLOBALDATA_H)
|
||||
#define GLOBALDATA_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "DriverInterface.h"
|
||||
#include "global.h"
|
||||
#include "nm_proto.h"
|
||||
#include "be_driver_proto.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#if !defined(GENERIC_H)
|
||||
#define GENERIC_H
|
||||
|
||||
#include <Accelerant.h>
|
||||
#include "video_overlay.h"
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
status_t INIT_ACCELERANT(int fd);
|
||||
ssize_t ACCELERANT_CLONE_INFO_SIZE(void);
|
||||
void GET_ACCELERANT_CLONE_INFO(void *data);
|
||||
status_t CLONE_ACCELERANT(void *data);
|
||||
void UNINIT_ACCELERANT(void);
|
||||
status_t GET_ACCELERANT_DEVICE_INFO(accelerant_device_info *adi);
|
||||
sem_id ACCELERANT_RETRACE_SEMAPHORE(void);
|
||||
|
||||
uint32 ACCELERANT_MODE_COUNT(void);
|
||||
status_t GET_MODE_LIST(display_mode *dm);
|
||||
status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const display_mode *high);
|
||||
status_t SET_DISPLAY_MODE(display_mode *mode_to_set);
|
||||
status_t GET_DISPLAY_MODE(display_mode *current_mode);
|
||||
status_t GET_FRAME_BUFFER_CONFIG(frame_buffer_config *a_frame_buffer);
|
||||
status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high);
|
||||
status_t MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start);
|
||||
status_t GET_TIMING_CONSTRAINTS(display_timing_constraints *dtc);
|
||||
void SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags);
|
||||
|
||||
uint32 DPMS_CAPABILITIES(void);
|
||||
uint32 DPMS_MODE(void);
|
||||
status_t SET_DPMS_MODE(uint32 dpms_flags);
|
||||
|
||||
status_t SET_CURSOR_SHAPE(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y, uint8 *andMask, uint8 *xorMask);
|
||||
void MOVE_CURSOR(uint16 x, uint16 y);
|
||||
void SHOW_CURSOR(bool is_visible);
|
||||
|
||||
uint32 ACCELERANT_ENGINE_COUNT(void);
|
||||
status_t ACQUIRE_ENGINE(uint32 capabilities, uint32 max_wait, sync_token *st, engine_token **et);
|
||||
status_t RELEASE_ENGINE(engine_token *et, sync_token *st);
|
||||
void WAIT_ENGINE_IDLE(void);
|
||||
status_t GET_SYNC_TOKEN(engine_token *et, sync_token *st);
|
||||
status_t SYNC_TO_TOKEN(sync_token *st);
|
||||
|
||||
void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count);
|
||||
void SCREEN_TO_SCREEN_TRANSPARENT_BLIT(engine_token *et, uint32 transparent_colour, blit_params *list, uint32 count);
|
||||
void FILL_RECTANGLE(engine_token *et, uint32 color, fill_rect_params *list, uint32 count);
|
||||
void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count);
|
||||
|
||||
void FILL_SPAN(engine_token *et, uint32 color, uint16 *list, uint32 count);
|
||||
|
||||
/* video_overlay */
|
||||
uint32 OVERLAY_COUNT(const display_mode *dm);
|
||||
const uint32 *OVERLAY_SUPPORTED_SPACES(const display_mode *dm);
|
||||
uint32 OVERLAY_SUPPORTED_FEATURES(uint32 a_color_space);
|
||||
const overlay_buffer *ALLOCATE_OVERLAY_BUFFER(color_space cs, uint16 width, uint16 height);
|
||||
status_t RELEASE_OVERLAY_BUFFER(const overlay_buffer *ob);
|
||||
status_t GET_OVERLAY_CONSTRAINTS(const display_mode *dm, const overlay_buffer *ob, overlay_constraints *oc);
|
||||
overlay_token ALLOCATE_OVERLAY(void);
|
||||
status_t RELEASE_OVERLAY(overlay_token ot);
|
||||
status_t CONFIGURE_OVERLAY(overlay_token ot, const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
SubDir OBOS_TOP src add-ons accelerants neomagic engine ;
|
||||
|
||||
UsePrivateHeaders graphics ;
|
||||
UsePrivateHeaders [ FDirName graphics neomagic ] ;
|
||||
UseHeaders [ FDirName $(SUBDIR) .. ] ;
|
||||
|
||||
StaticLibrary neomagic_engine :
|
||||
nm_acc.c
|
||||
nm_bes.c
|
||||
nm_crtc.c
|
||||
nm_dac.c
|
||||
nm_general.c
|
||||
nm_info.c
|
||||
nm_support.c
|
||||
;
|
||||
@@ -0,0 +1,350 @@
|
||||
/* nm Acceleration functions */
|
||||
/* Authors:
|
||||
Mark Watson 2/2000,
|
||||
Rudolf Cornelissen 10/2002-4/2003.
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00080000
|
||||
|
||||
#include "nm_std.h"
|
||||
|
||||
/*acceleration notes*/
|
||||
|
||||
/*functions Be's app_server uses:
|
||||
fill span (horizontal only)
|
||||
fill rectangle (these 2 are very similar)
|
||||
invert rectangle
|
||||
blit
|
||||
*/
|
||||
|
||||
/* G100 pre SRCORG/DSTORG registers */
|
||||
static uint32 src_dst;
|
||||
/* MIL1/2 adress linearisation does not always work */
|
||||
static uint8 y_lin;
|
||||
static uint8 depth;
|
||||
|
||||
/* needed by MIL 1/2 because of adress linearisation constraints */
|
||||
#define ACCW_YDSTLEN(dst, len) do { \
|
||||
if (y_lin) { \
|
||||
ACCW(YDST,((dst)* (si->fbc.bytes_per_row / (depth >> 3))) >> 5); \
|
||||
ACCW(LEN,len); \
|
||||
} else ACCW(YDSTLEN,((dst)<<16)|(len)); \
|
||||
} while (0)
|
||||
|
||||
status_t mn_acc_wait_idle()
|
||||
{
|
||||
volatile int i;
|
||||
while (ACCR(STATUS)&(1<<16))
|
||||
{
|
||||
for (i=0;i<10000;i++); /*spin in place so I do not hammer the bus*/
|
||||
};
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* AFAIK this must be done for every new screenmode.
|
||||
* Engine required init. */
|
||||
status_t mn_acc_init()
|
||||
{
|
||||
/* used for convenience: MACCESS is a write only register! */
|
||||
uint32 maccess = 0x00000000;
|
||||
|
||||
/* preset using hardware adress linearisation */
|
||||
y_lin = 0x00;
|
||||
/* reset depth */
|
||||
depth = 0;
|
||||
|
||||
/* cleanup bitblt */
|
||||
ACCW(OPMODE,0);
|
||||
|
||||
/* Set the Z origin to the start of FB (otherwise lockup on blits) */
|
||||
ACCW(ZORG,0);
|
||||
|
||||
/* Set pixel width */
|
||||
switch(si->dm.space)
|
||||
{
|
||||
case B_CMAP8:
|
||||
ACCW(MACCESS, ((maccess & 0xfffffffc) | 0x00));
|
||||
depth = 8;
|
||||
break;
|
||||
case B_RGB15_LITTLE:case B_RGB16_LITTLE:
|
||||
ACCW(MACCESS, ((maccess & 0xfffffffc) | 0x01));
|
||||
depth = 16;
|
||||
break;
|
||||
case B_RGB32_LITTLE:case B_RGBA32_LITTLE:
|
||||
ACCW(MACCESS, ((maccess & 0xfffffffc) | 0x02));
|
||||
depth = 32;
|
||||
break;
|
||||
default:
|
||||
LOG(8,("ACC: init, invalid bit depth\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/* setup PITCH: very cardtype specific! */
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
case G100:
|
||||
/* always using hardware adress linearisation, because 2D/3D
|
||||
* engine works on every pitch multiple of 32 */
|
||||
ACCW(PITCH, ((si->fbc.bytes_per_row / (depth >> 3)) & 0x0FFF));
|
||||
break;
|
||||
default:
|
||||
/* G200 and up are equal.. */
|
||||
/* always using hardware adress linearisation, because 2D/3D
|
||||
* engine works on every pitch multiple of 32 */
|
||||
ACCW(PITCH, ((si->fbc.bytes_per_row / (depth >> 3)) & 0x1FFF));
|
||||
break;
|
||||
}
|
||||
|
||||
/* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
|
||||
ACCW(PLNWT,0x00000000);
|
||||
ACCW(PLNWT,0xffffffff);
|
||||
|
||||
if (si->ps.card_type >= G200) {
|
||||
/*DSTORG - location of active screen in framebuffer*/
|
||||
ACCW(DSTORG,(si->fbc.frame_buffer)-(si->framebuffer));
|
||||
|
||||
/*SRCORG - init source address - same as dest*/
|
||||
ACCW(SRCORG,(si->fbc.frame_buffer)-(si->framebuffer));
|
||||
}
|
||||
|
||||
/* init YDSTORG - apsed, if not inited, BitBlts may fails on <= G200 */
|
||||
src_dst = 0;
|
||||
ACCW(YDSTORG, src_dst);
|
||||
|
||||
/* <= G100 uses this register as SRCORG/DSTORG replacement, but
|
||||
* MIL 1/2 does not need framebuffer space for the hardcursor! */
|
||||
if ((si->ps.card_type == G100) && (si->settings.hardcursor))
|
||||
{
|
||||
switch (si->dm.space)
|
||||
{
|
||||
case B_CMAP8:
|
||||
src_dst = 1024 / 1;
|
||||
break;
|
||||
case B_RGB15_LITTLE:
|
||||
case B_RGB16_LITTLE:
|
||||
src_dst = 1024 / 2;
|
||||
break;
|
||||
case B_RGB32_LITTLE:
|
||||
src_dst = 1024 / 4;
|
||||
break;
|
||||
default:
|
||||
LOG(8,("ACC: G100 hardcursor not supported for current colorspace\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
ACCW(YDSTORG,src_dst);
|
||||
|
||||
/* clipping */
|
||||
/* i.e. highest and lowest X pixel adresses */
|
||||
ACCW(CXBNDRY,(((si->fbc.bytes_per_row / (depth >> 3)) - 1) << 16) | (0));
|
||||
|
||||
/* Y pixel addresses must be linear */
|
||||
/* lowest adress */
|
||||
ACCW(YTOP, 0 + src_dst);
|
||||
/* highest adress */
|
||||
ACCW(YBOT,((si->dm.virtual_height - 1) *
|
||||
(si->fbc.bytes_per_row / (depth >> 3))) + src_dst);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* screen to screen blit - i.e. move windows around.
|
||||
* Engine function bitblit, paragraph 4.5.7.2 */
|
||||
status_t mn_acc_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint16 w,uint16 h)
|
||||
{
|
||||
uint32 t_start,t_end,offset;
|
||||
uint32 b_start,b_end;
|
||||
|
||||
/*find where the top,bottom and offset are*/
|
||||
offset = (si->fbc.bytes_per_row / (depth >> 3));
|
||||
|
||||
t_end = t_start = xs + (offset*ys) + src_dst;
|
||||
t_end += w;
|
||||
|
||||
b_end = b_start = xs + (offset*(ys+h)) + src_dst;
|
||||
b_end +=w;
|
||||
|
||||
/* sgnzero bit _must_ be '0' before accessing SGN! */
|
||||
ACCW(DWGCTL,0x00000000);
|
||||
|
||||
/*find which quadrant */
|
||||
switch((yd>ys)|((xd>xs)<<1))
|
||||
{
|
||||
case 0: /*L->R,down*/
|
||||
ACCW(SGN,0);
|
||||
|
||||
ACCW(AR3,t_start);
|
||||
ACCW(AR0,t_end);
|
||||
ACCW(AR5,offset);
|
||||
|
||||
ACCW_YDSTLEN(yd,h+1);
|
||||
break;
|
||||
case 1: /*L->R,up*/
|
||||
ACCW(SGN,4);
|
||||
|
||||
ACCW(AR3,b_start);
|
||||
ACCW(AR0,b_end);
|
||||
ACCW(AR5,-offset);
|
||||
|
||||
ACCW_YDSTLEN(yd+h,h+1);
|
||||
break;
|
||||
case 2: /*R->L,down*/
|
||||
ACCW(SGN,1);
|
||||
|
||||
ACCW(AR3,t_end);
|
||||
ACCW(AR0,t_start);
|
||||
ACCW(AR5,offset);
|
||||
|
||||
ACCW_YDSTLEN(yd,h+1);
|
||||
break;
|
||||
case 3: /*R->L,up*/
|
||||
ACCW(SGN,5);
|
||||
|
||||
ACCW(AR3,b_end);
|
||||
ACCW(AR0,b_start);
|
||||
ACCW(AR5,-offset);
|
||||
|
||||
ACCW_YDSTLEN(yd+h,h+1);
|
||||
break;
|
||||
}
|
||||
ACCW(FXBNDRY,((xd+w)<<16)|xd);
|
||||
|
||||
/*do the blit*/
|
||||
ACCGO(DWGCTL,0x040C4018); // atype RSTR
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* screen to screen tranparent blit - not sure what uses this.
|
||||
* Engine function bitblit, paragraph 4.5.7.2 */
|
||||
status_t mn_acc_transparent_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint16 w,uint16 h,uint32 colour)
|
||||
{
|
||||
uint32 t_start,t_end,offset;
|
||||
uint32 b_start,b_end;
|
||||
|
||||
return B_ERROR;
|
||||
|
||||
/*find where the top,bottom and offset are*/
|
||||
offset = (si->fbc.bytes_per_row / (depth >> 3));
|
||||
|
||||
t_end = t_start = xs + (offset*ys) + src_dst;
|
||||
t_end += w;
|
||||
|
||||
b_end = b_start = xs + (offset*(ys+h)) + src_dst;
|
||||
b_end +=w;
|
||||
|
||||
/* sgnzero bit _must_ be '0' before accessing SGN! */
|
||||
ACCW(DWGCTL,0x00000000);
|
||||
|
||||
/*find which quadrant */
|
||||
switch((yd>ys)|((xd>xs)<<1))
|
||||
{
|
||||
case 0: /*L->R,down*/
|
||||
ACCW(SGN,0);
|
||||
|
||||
ACCW(AR3,t_start);
|
||||
ACCW(AR0,t_end);
|
||||
ACCW(AR5,offset);
|
||||
|
||||
ACCW_YDSTLEN(yd,h+1);
|
||||
break;
|
||||
case 1: /*L->R,up*/
|
||||
ACCW(SGN,4);
|
||||
|
||||
ACCW(AR3,b_start);
|
||||
ACCW(AR0,b_end);
|
||||
ACCW(AR5,-offset);
|
||||
|
||||
ACCW_YDSTLEN(yd+h,h+1);
|
||||
break;
|
||||
case 2: /*R->L,down*/
|
||||
ACCW(SGN,1);
|
||||
|
||||
ACCW(AR3,t_end);
|
||||
ACCW(AR0,t_start);
|
||||
ACCW(AR5,offset);
|
||||
|
||||
ACCW_YDSTLEN(yd,h+1);
|
||||
break;
|
||||
case 3: /*R->L,up*/
|
||||
ACCW(SGN,5);
|
||||
|
||||
ACCW(AR3,b_end);
|
||||
ACCW(AR0,b_start);
|
||||
ACCW(AR5,-offset);
|
||||
|
||||
ACCW_YDSTLEN(yd+h,h+1);
|
||||
break;
|
||||
}
|
||||
ACCW(FXBNDRY,((xd+w)<<16)|xd);
|
||||
|
||||
/*do the blit*/
|
||||
ACCW(FCOL,colour);
|
||||
ACCW(BCOL,0xffffffff);
|
||||
ACCGO(DWGCTL,0x440C4018); // atype RSTR
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* rectangle fill.
|
||||
* Engine function rectangle_fill: paragraph 4.5.5.2 */
|
||||
/*colorIndex,fill_rect_params,count*/
|
||||
status_t mn_acc_rectangle(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint32 col)
|
||||
{
|
||||
/*
|
||||
FXBNDRY - left and right coordinates a
|
||||
YDSTLEN - y start and no of lines a
|
||||
(or YDST and LEN)
|
||||
DWGCTL - atype must be RSTR or BLK a
|
||||
FCOL - foreground colour a
|
||||
*/
|
||||
|
||||
ACCW(FXBNDRY,(xe<<16)|xs); /*set x start and end*/
|
||||
ACCW_YDSTLEN(ys,yl); /*set y start and length*/
|
||||
ACCW(FCOL,col); /*set colour*/
|
||||
|
||||
//acc fixme: checkout blockmode constraints for G100+ (mil: nc?): also add blockmode
|
||||
// for other functions, and use fastblt on MIL1/2 if possible...
|
||||
//or is CMAP8 contraint a non-blockmode contraint? (linearisation problem maybe?)
|
||||
if (si->dm.space==B_CMAP8)
|
||||
{
|
||||
ACCGO(DWGCTL,0x400C7814); // atype RSTR
|
||||
}
|
||||
else
|
||||
{
|
||||
ACCGO(DWGCTL,0x400C7844); // atype BLK
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* rectangle invert.
|
||||
* Engine function rectangle_fill: paragraph 4.5.5.2 */
|
||||
/*colorIndex,fill_rect_params,count*/
|
||||
status_t mn_acc_rectangle_invert(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint32 col)
|
||||
{
|
||||
/*
|
||||
FXBNDRY - left and right coordinates a
|
||||
YDSTLEN - y start and no of lines a
|
||||
(or YDST and LEN)
|
||||
DWGCTL - atype must be RSTR or BLK a
|
||||
FCOL - foreground colour a
|
||||
*/
|
||||
|
||||
ACCW(FXBNDRY,(xe<<16)|xs); /*set x start and end*/
|
||||
ACCW_YDSTLEN(ys,yl); /*set y start and length*/
|
||||
ACCW(FCOL,col); /*set colour*/
|
||||
|
||||
/*draw it! top nibble is c is clipping enabled*/
|
||||
ACCGO(DWGCTL,0x40057814); // atype RSTR
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* screen to screen scaled filtered blit - i.e. scale video in memory.
|
||||
* Engine function texture mapping for video, paragraphs 4.5.5.5 - 4.5.5.9 */
|
||||
status_t mn_acc_video_blit(uint16 xs,uint16 ys,uint16 ws, uint16 hs,
|
||||
uint16 xd,uint16 yd,uint16 wd,uint16 hd)
|
||||
{
|
||||
//fixme: implement.
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,694 @@
|
||||
/* G200-G550 Back End Scaler functions */
|
||||
/* Written by Rudolf Cornelissen 05/2002-04/2003 */
|
||||
|
||||
#define MODULE_BIT 0x00000200
|
||||
|
||||
#include "nm_std.h"
|
||||
|
||||
//fixme: implement: (used for virtual screens!)
|
||||
//void move_overlay(uint16 hdisp_start, uint16 vdisp_start);
|
||||
|
||||
status_t mn_configure_bes
|
||||
(const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov, int offset)
|
||||
{
|
||||
/* yuy2 (4:2:2) colorspace calculations */
|
||||
/* Note: Some calculations will have to be modified for other colorspaces if they are incorporated. */
|
||||
|
||||
/* Note:
|
||||
* in BeOS R5.0.3 and DANO:
|
||||
* 'ow->offset_xxx' is always 0, so not used;
|
||||
* 'ow->width' and 'ow->height' are the output window size: does not change
|
||||
* if window is clipping;
|
||||
* 'ow->h_start' and 'ow->v_start' are the left-top position of the output
|
||||
* window. These values can be negative: this means the window is clipping
|
||||
* at the left or the top of the display, respectively. */
|
||||
|
||||
/* 'ov' is the view in the source bitmap, so which part of the bitmap is actually
|
||||
* displayed on screen. This is used for the 'hardware zoom' function. */
|
||||
|
||||
/* calculated BES register values */
|
||||
uint32 hcoordv, vcoordv, hiscalv, hsrcstv, hsrcendv, hsrclstv,
|
||||
viscalv, a1orgv, v1wghtv, v1srclstv, globctlv, ctlv;
|
||||
/* misc used variables */
|
||||
uint16 temp1, temp2;
|
||||
/* interval representation, used for scaling calculations */
|
||||
uint16 intrep, crtc_hstart, crtc_vstart, crtc_hend, crtc_vend;
|
||||
/* inverse scaling factor, used for source positioning */
|
||||
uint32 ifactor;
|
||||
/* used for vertical weight starting value */
|
||||
uint32 weight;
|
||||
/* copy of overlay view which has checked valid values */
|
||||
overlay_view my_ov;
|
||||
|
||||
/* Slowdown the G200-G550 BES if the pixelclock is too high for it to cope.
|
||||
* This will in fact half the horizontal resolution of the BES with high
|
||||
* pixelclocks (by setting a BES hardware 'zoom' = 2x).
|
||||
* If you want optimal output quality better make sure you set the refreshrate/resolution
|
||||
* of your monitor not too high ... */
|
||||
uint16 acczoom = 1;
|
||||
LOG(4,("Overlay: pixelclock is %dkHz, ", si->dm.timing.pixel_clock));
|
||||
if (si->dm.timing.pixel_clock > BESMAXSPEED)
|
||||
{
|
||||
/* BES running at half speed and resolution */
|
||||
/* This is how it works (BES slowing down):
|
||||
* - Activate BES internal horizontal hardware scaling = 4x (in GLOBCTL below),
|
||||
* - This also sets up BES only getting half the amount of pixels per line from
|
||||
* the input picture buffer (in effect half-ing the BES pixelclock input speed).
|
||||
* Now in order to get the picture back to original size, we need to also double
|
||||
* the inverse horizontal scaling factor here (x4 /2 /2 = 1x again).
|
||||
* Note that every other pixel is now doubled or interpolated, according to another
|
||||
* GLOBCTL bit. */
|
||||
acczoom = 2;
|
||||
LOG(4,("slowing down BES!\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* BES running at full speed and resolution */
|
||||
LOG(4,("BES is running at full speed\n"));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************************
|
||||
*** 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(6,("Overlay: inputbuffer view (zoom) left %d, top %d, width %d, height %d\n",
|
||||
my_ov.h_start, my_ov.v_start, my_ov.width, my_ov.height));
|
||||
|
||||
/* the BES does not respect virtual_workspaces, but adheres to CRTC
|
||||
* constraints only */
|
||||
crtc_hstart = si->dm.h_display_start;
|
||||
/* 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 */
|
||||
hcoordv = 0;
|
||||
/* left edge coordinate of output window, must be inside desktop */
|
||||
/* clipping on the left side */
|
||||
if (ow->h_start < crtc_hstart)
|
||||
{
|
||||
temp1 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clipping on the right side */
|
||||
if (ow->h_start >= (crtc_hend - 1))
|
||||
{
|
||||
/* width < 2 is not allowed */
|
||||
temp1 = (crtc_hend - crtc_hstart - 2) & 0x7ff;
|
||||
}
|
||||
else
|
||||
/* no clipping here */
|
||||
{
|
||||
temp1 = (ow->h_start - crtc_hstart) & 0x7ff;
|
||||
}
|
||||
}
|
||||
hcoordv |= temp1 << 16;
|
||||
/* right edge coordinate of output window, must be inside desktop */
|
||||
/* width < 2 is not allowed */
|
||||
if (ow->width < 2)
|
||||
{
|
||||
temp2 = (temp1 + 1) & 0x7ff;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clipping on the right side */
|
||||
if ((ow->h_start + ow->width - 1) > (crtc_hend - 1))
|
||||
{
|
||||
temp2 = (crtc_hend - crtc_hstart - 1) & 0x7ff;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clipping on the left side */
|
||||
if ((ow->h_start + ow->width - 1) < (crtc_hstart + 1))
|
||||
{
|
||||
/* width < 2 is not allowed */
|
||||
temp2 = 1;
|
||||
}
|
||||
else
|
||||
/* no clipping here */
|
||||
{
|
||||
temp2 = ((uint16)(ow->h_start + ow->width - crtc_hstart - 1)) & 0x7ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 */
|
||||
vcoordv = 0;
|
||||
/* top edge coordinate of output window, must be inside desktop */
|
||||
/* clipping on the top side */
|
||||
if (ow->v_start < crtc_vstart)
|
||||
{
|
||||
temp1 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clipping on the bottom side */
|
||||
if (ow->v_start >= (crtc_vend - 1))
|
||||
{
|
||||
/* height < 2 is not allowed */
|
||||
temp1 = (crtc_vend - crtc_vstart - 2) & 0x7ff;
|
||||
}
|
||||
else
|
||||
/* no clipping here */
|
||||
{
|
||||
temp1 = (ow->v_start - crtc_vstart) & 0x7ff;
|
||||
}
|
||||
}
|
||||
vcoordv |= temp1 << 16;
|
||||
/* bottom edge coordinate of output window, must be inside desktop */
|
||||
/* height < 2 is not allowed */
|
||||
if (ow->height < 2)
|
||||
{
|
||||
temp2 = (temp1 + 1) & 0x7ff;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clipping on the bottom side */
|
||||
if ((ow->v_start + ow->height - 1) > (crtc_vend - 1))
|
||||
{
|
||||
temp2 = (crtc_vend - crtc_vstart - 1) & 0x7ff;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clipping on the top side */
|
||||
if ((ow->v_start + ow->height - 1) < (crtc_vstart + 1))
|
||||
{
|
||||
/* height < 2 is not allowed */
|
||||
temp2 = 1;
|
||||
}
|
||||
else
|
||||
/* no clipping here */
|
||||
{
|
||||
temp2 = ((uint16)(ow->v_start + ow->height - crtc_vstart - 1)) & 0x7ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
vcoordv |= temp2 << 0;
|
||||
LOG(4,("Overlay: CRTC top-edge output %d, bottom-edge output %d\n",temp1, temp2));
|
||||
|
||||
|
||||
/*********************************************
|
||||
*** setup horizontal scaling and clipping ***
|
||||
*********************************************/
|
||||
|
||||
LOG(6,("Overlay: total input picture width = %d, height = %d\n",
|
||||
(ob->width - si->overlay.myBufInfo[offset].slopspace), ob->height));
|
||||
LOG(6,("Overlay: output picture width = %d, height = %d\n", ow->width, ow->height));
|
||||
|
||||
/* do horizontal scaling... */
|
||||
/* 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);
|
||||
LOG(4,("Overlay: horizontal scaling factor is %f\n", (float)65536 / ifactor));
|
||||
|
||||
/* compensate for accelerated 2x zoom (slowdown BES if pixelclock is too high) */
|
||||
hiscalv = ifactor * acczoom;
|
||||
LOG(4,("Overlay: horizontal speed compensated factor is %f\n", (float)65536 / hiscalv));
|
||||
|
||||
/* check scaling factor (and modify if needed) to be within scaling limits */
|
||||
if (((((uint32)my_ov.width) << 16) / 16384) > hiscalv)
|
||||
{
|
||||
/* (non-inverse) factor too large, set factor to max. valid value */
|
||||
hiscalv = ((((uint32)my_ov.width) << 16) / 16384);
|
||||
LOG(4,("Overlay: horizontal scaling factor too large, clamping at %f\n", (float)65536 / hiscalv));
|
||||
}
|
||||
if (hiscalv >= (32 << 16))
|
||||
{
|
||||
/* (non-inverse) factor too small, set factor to min. valid value */
|
||||
hiscalv = 0x1ffffc;
|
||||
LOG(4,("Overlay: horizontal scaling factor too small, clamping at %f\n", (float)65536 / hiscalv));
|
||||
}
|
||||
/* AND below is required by hardware */
|
||||
hiscalv &= 0x001ffffc;
|
||||
|
||||
|
||||
/* do 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.! */
|
||||
hsrcstv = 0;
|
||||
/* check for destination horizontal clipping at left side */
|
||||
if (ow->h_start < crtc_hstart)
|
||||
{
|
||||
/* check if entire destination picture is clipping left:
|
||||
* (2 pixels will be clamped onscreen at least) */
|
||||
if ((ow->h_start + ow->width - 1) < (crtc_hstart + 1))
|
||||
{
|
||||
/* increase 'first contributing pixel' with 'fixed value': (total dest. width - 2) */
|
||||
hsrcstv += (ow->width - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* increase 'first contributing pixel' with actual number of dest. clipping pixels */
|
||||
hsrcstv += (crtc_hstart - 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! */
|
||||
hsrcstv *= ifactor;
|
||||
}
|
||||
/* take zoom into account */
|
||||
hsrcstv += ((uint32)my_ov.h_start) << 16;
|
||||
/* AND below required by hardware */
|
||||
hsrcstv &= 0x03fffffc;
|
||||
LOG(4,("Overlay: first hor. (sub)pixel of input bitmap contributing %f\n", hsrcstv / (float)65536));
|
||||
|
||||
|
||||
/* Setup horizontal source end: last (sub)pixel contributing to output picture */
|
||||
/* Note:
|
||||
* The method is to calculate, based on 1:1 scaling, based on the output window.
|
||||
* After this is done, include the scaling factor so you get a value based on the input bitmap.
|
||||
* Then add the right ending position of the bitmap's view (zoom function) to get the final value needed. */
|
||||
/* Note also:
|
||||
* Even if the scaling factor is clamping we instruct the BES to use the correct source end pos.! */
|
||||
|
||||
hsrcendv = 0;
|
||||
/* check for destination horizontal clipping at right side */
|
||||
if ((ow->h_start + ow->width - 1) > (crtc_hend - 1))
|
||||
{
|
||||
/* check if entire destination picture is clipping right:
|
||||
* (2 pixels will be clamped onscreen at least) */
|
||||
if (ow->h_start > (crtc_hend - 2))
|
||||
{
|
||||
/* increase 'number of clipping pixels' with 'fixed value': (total dest. width - 2) */
|
||||
hsrcendv += (ow->width - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* increase 'number of clipping pixels' with actual number of dest. clipping pixels */
|
||||
hsrcendv += ((ow->h_start + ow->width - 1) - (crtc_hend - 1));
|
||||
}
|
||||
LOG(4,("Overlay: clipping right...\n"));
|
||||
|
||||
/* The calculated value is based on scaling = 1x. So we now compensate for scaling.
|
||||
* Note that this also already takes care of aligning the value to the BES register! */
|
||||
hsrcendv *= ifactor;
|
||||
/* now subtract this value from the last used pixel in (zoomed) inputbuffer, aligned to BES */
|
||||
hsrcendv = (((uint32)((my_ov.h_start + my_ov.width) - 1)) << 16) - hsrcendv;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set last contributing pixel to last used pixel in (zoomed) inputbuffer, aligned to BES */
|
||||
hsrcendv = (((uint32)((my_ov.h_start + my_ov.width) - 1)) << 16);
|
||||
}
|
||||
/* AND below required by hardware */
|
||||
hsrcendv &= 0x03fffffc;
|
||||
LOG(4,("Overlay: last horizontal (sub)pixel of input bitmap contributing %f\n", hsrcendv / (float)65536));
|
||||
|
||||
|
||||
/* setup horizontal source last position excluding slopspace:
|
||||
* this is the last pixel that will be used for calculating interpolated pixels */
|
||||
hsrclstv = ((ob->width - 1) - si->overlay.myBufInfo[offset].slopspace) << 16;
|
||||
/* AND below required by hardware */
|
||||
hsrclstv &= 0x03ff0000;
|
||||
|
||||
|
||||
/*******************************************
|
||||
*** setup vertical scaling and clipping ***
|
||||
*******************************************/
|
||||
|
||||
/* do 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;
|
||||
|
||||
/* check scaling factor (and modify if needed) to be within scaling limits */
|
||||
if (((((uint32)my_ov.height) << 16) / 16384) > viscalv)
|
||||
{
|
||||
/* (non-inverse) factor too large, set factor to max. valid value */
|
||||
viscalv = ((((uint32)my_ov.height) << 16) / 16384);
|
||||
LOG(4,("Overlay: vertical scaling factor too large, clamping at %f\n", (float)65536 / viscalv));
|
||||
}
|
||||
if (viscalv >= (32 << 16))
|
||||
{
|
||||
/* (non-inverse) factor too small, set factor to min. valid value */
|
||||
viscalv = 0x1ffffc;
|
||||
LOG(4,("Overlay: vertical scaling factor too small, clamping at %f\n", (float)65536 / viscalv));
|
||||
}
|
||||
/* AND below is required by hardware */
|
||||
viscalv &= 0x001ffffc;
|
||||
|
||||
|
||||
/* do vertical clipping... */
|
||||
/* Setup vertical source start: first (sub)pixel contributing to output picture.
|
||||
* Note: this exists of two parts:
|
||||
* 1. setup fractional part (sign is always 'positive');
|
||||
* 2. setup relative base_adress, taking clipping on top (and zoom) into account.
|
||||
* Both parts are done intertwined below. */
|
||||
/* Note:
|
||||
* The method is to calculate, based on 1:1 scaling, based on the output window.
|
||||
* 'After' this is done, include the scaling factor so you get a value based on the input bitmap.
|
||||
* Then add the top starting position of the bitmap's view (zoom function) to get the final value needed. */
|
||||
/* Note also:
|
||||
* Even if the scaling factor is clamping we instruct the BES to use the correct source start pos.! */
|
||||
|
||||
/* calculate relative base_adress and 'vertical weight fractional part' */
|
||||
weight = 0;
|
||||
a1orgv = (uint32)((vuint32 *)ob->buffer);
|
||||
a1orgv -= (uint32)((vuint32 *)si->framebuffer);
|
||||
/* calculate origin adress */
|
||||
LOG(4,("Overlay: topleft corner of input bitmap (cardRAM offset) $%08x\n",a1orgv));
|
||||
/* check for destination vertical clipping at top side */
|
||||
if (ow->v_start < crtc_vstart)
|
||||
{
|
||||
/* check if entire destination picture is clipping at top:
|
||||
* (2 pixels will be clamped onscreen at least) */
|
||||
if ((ow->v_start + ow->height - 1) < (crtc_vstart + 1))
|
||||
{
|
||||
/* increase source buffer origin with 'fixed value':
|
||||
* (integer part of ('total height - 2' of dest. picture in pixels * inverse scaling factor)) *
|
||||
* bytes per row source picture */
|
||||
a1orgv += ((((ow->height - 2) * ifactor) >> 16) * ob->bytes_per_row);
|
||||
weight = (ow->height - 2) * ifactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* increase source buffer origin with:
|
||||
* (integer part of (number of destination picture clipping pixels * inverse scaling factor)) *
|
||||
* bytes per row source picture */
|
||||
a1orgv += ((((crtc_vstart - ow->v_start) * ifactor) >> 16) * ob->bytes_per_row);
|
||||
weight = (crtc_vstart - ow->v_start) * ifactor;
|
||||
}
|
||||
LOG(4,("Overlay: clipping at top...\n"));
|
||||
}
|
||||
/* take zoom into account */
|
||||
a1orgv += (my_ov.v_start * ob->bytes_per_row);
|
||||
weight += (((uint32)my_ov.v_start) << 16);
|
||||
LOG(4,("Overlay: 'contributing part of buffer' origin is (cardRAM offset) $%08x\n",a1orgv));
|
||||
LOG(4,("Overlay: first vert. (sub)pixel of input bitmap contributing %f\n", weight / (float)65536));
|
||||
|
||||
/* Note:
|
||||
* Because all > G200 overlay units will ignore b0-3 of the calculated adress,
|
||||
* we do not use the above way for horizontal source positioning.
|
||||
* (G200 cards ignore b0-2.)
|
||||
* If we did, 8 source-image pixel jumps (in 4:2:2 colorspace) will occur if the picture
|
||||
* is shifted horizontally during left clipping on all > G200 cards, while G200 cards
|
||||
* will have 4 source-image pixel jumps occuring. */
|
||||
|
||||
/* AND below is required by G200-G550 hardware. > G200 cards can have max. 32Mb RAM on board
|
||||
* (16Mb on G200 cards). Compatible setting used (between G200 and the rest), this has no
|
||||
* downside consequences here. */
|
||||
/* Buffer A topleft corner of field 1 (origin)(field 1 contains our full frames) */
|
||||
a1orgv &= 0x01fffff0;
|
||||
|
||||
/* field 1 weight: AND below required by hardware, also make sure 'sign' is always 'positive' */
|
||||
v1wghtv = weight & 0x0000fffc;
|
||||
|
||||
|
||||
/* setup field 1 (is our complete frame) vertical source last position.
|
||||
* this is the last pixel that will be used for calculating interpolated pixels */
|
||||
v1srclstv = (ob->height - 1);
|
||||
/* AND below required by hardware */
|
||||
v1srclstv &= 0x000003ff;
|
||||
|
||||
|
||||
/*****************************
|
||||
*** log color keying info ***
|
||||
*****************************/
|
||||
|
||||
LOG(6,("Overlay: key_red %d, key_green %d, key_blue %d, key_alpha %d\n",
|
||||
ow->red.value, ow->green.value, ow->blue.value, ow->alpha.value));
|
||||
LOG(6,("Overlay: mask_red %d, mask_green %d, mask_blue %d, mask_alpha %d\n",
|
||||
ow->red.mask, ow->green.mask, ow->blue.mask, ow->alpha.mask));
|
||||
|
||||
|
||||
/*************************
|
||||
*** setup BES control ***
|
||||
*************************/
|
||||
|
||||
/* BES global control: setup functions */
|
||||
globctlv = 0;
|
||||
|
||||
/* slowdown BES if nessesary */
|
||||
if (acczoom == 1)
|
||||
{
|
||||
/* run at full speed and resolution */
|
||||
globctlv |= 0 << 0;
|
||||
/* disable filtering for half speed interpolation */
|
||||
globctlv |= 0 << 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* run at half speed and resolution */
|
||||
globctlv |= 1 << 0;
|
||||
/* enable filtering for half speed interpolation */
|
||||
globctlv |= 1 << 1;
|
||||
}
|
||||
|
||||
/* 4:2:0 specific setup: not needed here */
|
||||
globctlv |= 0 << 3;
|
||||
/* BES testregister: keep zero */
|
||||
globctlv |= 0 << 4;
|
||||
/* the following bits marked (> G200) *must* be zero on G200: */
|
||||
/* 4:2:0 specific setup: not needed here (> G200) */
|
||||
globctlv |= 0 << 5;
|
||||
/* select yuy2 byte-order to B_YCbCr422 (> G200) */
|
||||
globctlv |= 0 << 6;
|
||||
/* BES internal contrast and brighness controls are not used, disabled (> G200) */
|
||||
globctlv |= 0 << 7;
|
||||
/* RGB specific setup: not needed here, so disabled (> G200) */
|
||||
globctlv |= 0 << 8;
|
||||
globctlv |= 0 << 9;
|
||||
/* 4:2:0 specific setup: not needed here (> G200) */
|
||||
globctlv |= 0 << 10;
|
||||
/* Tell BES when to copy the new register values to the actual active registers.
|
||||
* bits 16-27 (12 bits) are the CRTC vert. count value at which copying takes
|
||||
* place.
|
||||
* (This is the double buffering feature: programming must be completed *before*
|
||||
* the CRTC vert count value set here!) */
|
||||
/* CRTC vert count for copying = $000, so during retrace, line 0. */
|
||||
globctlv |= 0x000 << 16;
|
||||
|
||||
/* BES control: enable scaler and setup functions */
|
||||
/* pre-reset all bits */
|
||||
ctlv = 0;
|
||||
/* enable BES */
|
||||
ctlv |= 1 << 0;
|
||||
/* we start displaying at an even startline (zero) in 'field 1' (no hardware de-interlacing is used) */
|
||||
ctlv |= 0 << 6;
|
||||
/* we don't use field 2, so its startline is not important */
|
||||
ctlv |= 0 << 7;
|
||||
|
||||
LOG(6,("Overlay: ow->flags is $%08x\n",ow->flags));
|
||||
/* enable horizontal filtering on scaling if asked for: if we *are* actually scaling */
|
||||
if ((ow->flags & B_OVERLAY_HORIZONTAL_FILTERING) && (hiscalv != (0x01 << 16)))
|
||||
{
|
||||
ctlv |= 1 << 10;
|
||||
LOG(6,("Overlay: using horizontal interpolation on scaling\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ctlv |= 0 << 10;
|
||||
LOG(6,("Overlay: using horizontal dropping or replication on scaling\n"));
|
||||
}
|
||||
/* enable vertical filtering on scaling if asked for: if we are *upscaling* only */
|
||||
if ((ow->flags & B_OVERLAY_VERTICAL_FILTERING) && (viscalv < (0x01 << 16)))
|
||||
{
|
||||
ctlv |= 1 << 11;
|
||||
LOG(6,("Overlay: using vertical interpolation on scaling\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ctlv |= 0 << 11;
|
||||
LOG(6,("Overlay: using vertical dropping or replication on scaling\n"));
|
||||
}
|
||||
|
||||
/* use actual calculated weight for horizontal interpolation */
|
||||
ctlv |= 0 << 12;
|
||||
/* use horizontal chroma interpolation upsampling on BES input picture */
|
||||
ctlv |= 1 << 16;
|
||||
/* select 4:2:2 BES input format */
|
||||
ctlv |= 0 << 17;
|
||||
/* dithering is enabled */
|
||||
ctlv |= 1 << 18;
|
||||
/* horizontal mirroring is not used */
|
||||
ctlv |= 0 << 19;
|
||||
/* BES output should be in color */
|
||||
ctlv |= 0 << 20;
|
||||
/* BES output blanking is disabled: we want a picture, no 'black box'! */
|
||||
ctlv |= 0 << 21;
|
||||
/* we do software field select (field select is not used) */
|
||||
ctlv |= 0 << 24;
|
||||
/* we always display field 1 in buffer A, this contains our full frames */
|
||||
/* select field 1 */
|
||||
ctlv |= 0 << 25;
|
||||
/* select buffer A */
|
||||
ctlv |= 0 << 26;
|
||||
|
||||
|
||||
/*************************************
|
||||
*** sync to BES (Back End Scaler) ***
|
||||
*************************************/
|
||||
|
||||
/* Make sure reprogramming the BES completes before the next retrace occurs,
|
||||
* to prevent register-update glitches (double buffer feature). */
|
||||
|
||||
// LOG(3,("Overlay: starting register programming beyond Vcount %d\n", CR1R(VCOUNT)));
|
||||
/* Even at 1600x1200x90Hz, a single line still takes about 9uS to complete:
|
||||
* this resolution will generate about 180Mhz pixelclock while we can do
|
||||
* upto 360Mhz. So snooze about 4uS to prevent bus-congestion...
|
||||
* Appr. 200 lines time will provide enough room even on a 100Mhz CPU if it's
|
||||
* screen is set to the highest refreshrate/resolution possible. */
|
||||
// while (CR1R(VCOUNT) > (si->dm.timing.v_total - 200)) snooze(4);
|
||||
|
||||
|
||||
/**************************************
|
||||
*** actually program the registers ***
|
||||
**************************************/
|
||||
/*
|
||||
BESW(HCOORD, hcoordv);
|
||||
BESW(VCOORD, vcoordv);
|
||||
BESW(HISCAL, hiscalv);
|
||||
BESW(HSRCST, hsrcstv);
|
||||
BESW(HSRCEND, hsrcendv);
|
||||
BESW(HSRCLST, hsrclstv);
|
||||
BESW(VISCAL, viscalv);
|
||||
BESW(A1ORG, a1orgv);
|
||||
BESW(V1WGHT, v1wghtv);
|
||||
BESW(V1SRCLST, v1srclstv);
|
||||
BESW(GLOBCTL, globctlv);
|
||||
BESW(CTL, ctlv);
|
||||
*/
|
||||
|
||||
/**************************
|
||||
*** setup color keying ***
|
||||
**************************/
|
||||
|
||||
/* setup colorkeying */
|
||||
/* DXIW(COLKEY, (ow->alpha.value & ow->alpha.mask));
|
||||
|
||||
DXIW(COLKEY0RED, (ow->red.value & ow->red.mask));
|
||||
DXIW(COLKEY0GREEN, (ow->green.value & ow->green.mask));
|
||||
DXIW(COLKEY0BLUE, (ow->blue.value & ow->blue.mask));
|
||||
|
||||
DXIW(COLMSK, ow->alpha.mask);
|
||||
|
||||
DXIW(COLMSK0RED, ow->red.mask);
|
||||
DXIW(COLMSK0GREEN, ow->green.mask);
|
||||
DXIW(COLMSK0BLUE, ow->blue.mask);
|
||||
*/
|
||||
/* enable colorkeying */
|
||||
// DXIW(KEYOPMODE,0x01);
|
||||
|
||||
|
||||
/*************************
|
||||
*** setup misc. stuff ***
|
||||
*************************/
|
||||
|
||||
/* setup brightness and contrast to be 'neutral' (this is not implemented on G200) */
|
||||
// BESW(LUMACTL, 0x00000080);
|
||||
|
||||
/* setup source pitch including slopspace (in pixels); AND is required by hardware */
|
||||
// BESW(PITCH, (ob->width & 0x00000fff));
|
||||
|
||||
/* on a 500Mhz P3 CPU just logging a line costs 400uS (18-19 vcounts at 1024x768x60Hz)!
|
||||
* programming the registers above actually costs 180uS here */
|
||||
// LOG(3,("Overlay: completed at Vcount %d\n", CR1R(VCOUNT)));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t mn_release_bes()
|
||||
{
|
||||
/* setup BES control: disable scaler */
|
||||
// BESW(CTL, 0x00000000);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,696 @@
|
||||
/* CTRC functionality */
|
||||
/* Author:
|
||||
Rudolf Cornelissen 4/2003-6/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00040000
|
||||
|
||||
#include "nm_std.h"
|
||||
|
||||
/* Adjust passed parameters to a valid mode line */
|
||||
//fixme: the order of the sync edges should also be checked,
|
||||
//just like the sync signal's min. pulse length...
|
||||
status_t mn_crtc_validate_timing(
|
||||
uint16 *hd_e,uint16 *hs_s,uint16 *hs_e,uint16 *ht,
|
||||
uint16 *vd_e,uint16 *vs_s,uint16 *vs_e,uint16 *vt
|
||||
)
|
||||
{
|
||||
/* horizontal */
|
||||
/* make all parameters multiples of 8 */
|
||||
*hd_e &= 0xfff8;
|
||||
*hs_s &= 0xfff8;
|
||||
*hs_e &= 0xfff8;
|
||||
*ht &= 0xfff8;
|
||||
|
||||
/* confine to required number of bits, taking logic into account */
|
||||
if (*hd_e > ((0xff - 2) << 3)) *hd_e = ((0xff - 2) << 3);
|
||||
if (*hs_s > ((0xff - 1) << 3)) *hs_s = ((0xff - 1) << 3);
|
||||
if (*hs_e > ( 0xff << 3)) *hs_e = ( 0xff << 3);
|
||||
if (*ht > ((0xff + 5) << 3)) *ht = ((0xff + 5) << 3);
|
||||
|
||||
/* NOTE: keep horizontal timing at multiples of 8! */
|
||||
/* confine to a reasonable width */
|
||||
if (*hd_e < 640) *hd_e = 640;
|
||||
if (*hd_e > 2000) *hd_e = 2000;
|
||||
|
||||
/* if hor. total does not leave room for a sensible sync pulse, increase it! */
|
||||
if (*ht < (*hd_e + 80)) *ht = (*hd_e + 80);
|
||||
|
||||
/* make sure sync pulse is not during display */
|
||||
if (*hs_e > (*ht - 8)) *hs_e = (*ht - 8);
|
||||
if (*hs_s < (*hd_e + 8)) *hs_s = (*hd_e + 8);
|
||||
|
||||
/* correct sync pulse if it is too long:
|
||||
* there are only 5 bits available to save this in the card registers! */
|
||||
if (*hs_e > (*hs_s + 0xf8)) *hs_e = (*hs_s + 0xf8);
|
||||
|
||||
/*vertical*/
|
||||
/* confine to required number of bits, taking logic into account */
|
||||
if (si->ps.card_type < NM2200)
|
||||
{
|
||||
if (*vd_e > (0x3ff - 2)) *vd_e = (0x3ff - 2);
|
||||
if (*vs_s > (0x3ff - 1)) *vs_s = (0x3ff - 1);
|
||||
if (*vs_e > 0x3ff ) *vs_e = 0x3ff ;
|
||||
if (*vt > (0x3ff + 2)) *vt = (0x3ff + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*vd_e > (0x7ff - 2)) *vd_e = (0x7ff - 2);
|
||||
if (*vs_s > (0x7ff - 1)) *vs_s = (0x7ff - 1);
|
||||
if (*vs_e > 0x7ff ) *vs_e = 0x7ff ;
|
||||
if (*vt > (0x7ff + 2)) *vt = (0x7ff + 2);
|
||||
}
|
||||
|
||||
/* confine to a reasonable height */
|
||||
if (*vd_e < 480) *vd_e = 480;
|
||||
/* (max height was already confined in a reasonable way above) */
|
||||
|
||||
/*if vertical total does not leave room for a sync pulse, increase it!*/
|
||||
if (*vt < (*vd_e + 3)) *vt = (*vd_e + 3);
|
||||
|
||||
/* make sure sync pulse is not during display */
|
||||
if (*vs_e > (*vt - 1)) *vs_e = (*vt - 1);
|
||||
if (*vs_s < (*vd_e + 1)) *vs_s = (*vd_e + 1);
|
||||
|
||||
/* correct sync pulse if it is too long:
|
||||
* there are only 4 bits available to save this in the card registers! */
|
||||
if (*vs_e > (*vs_s + 0x0f)) *vs_e = (*vs_s + 0x0f);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* set a mode line */
|
||||
status_t mn_crtc_set_timing(display_mode target, bool crt_only)
|
||||
{
|
||||
uint8 hsync_pos = (target.timing.flags & B_POSITIVE_HSYNC);
|
||||
uint8 vsync_pos = (target.timing.flags & B_POSITIVE_VSYNC);
|
||||
|
||||
uint8 temp;
|
||||
|
||||
uint32 htotal; /*total horizontal total VCLKs*/
|
||||
uint32 hdisp_e; /*end of horizontal display (begins at 0)*/
|
||||
uint32 hsync_s; /*begin of horizontal sync pulse*/
|
||||
uint32 hsync_e; /*end of horizontal sync pulse*/
|
||||
uint32 hblnk_s; /*begin horizontal blanking*/
|
||||
uint32 hblnk_e; /*end horizontal blanking*/
|
||||
|
||||
uint32 vtotal; /*total vertical total scanlines*/
|
||||
uint32 vdisp_e; /*end of vertical display*/
|
||||
uint32 vsync_s; /*begin of vertical sync pulse*/
|
||||
uint32 vsync_e; /*end of vertical sync pulse*/
|
||||
uint32 vblnk_s; /*begin vertical blanking*/
|
||||
uint32 vblnk_e; /*end vertical blanking*/
|
||||
|
||||
uint32 linecomp; /*split screen and vdisp_e interrupt*/
|
||||
|
||||
LOG(4,("CRTC: setting timing\n"));
|
||||
|
||||
/* modify visible sceensize if needed */
|
||||
/* (note that MOVE_CURSOR checks for a panning/scrolling mode itself,
|
||||
* the display_mode as placed in si->dm may _not_ be modified!) */
|
||||
if (!(crt_only))
|
||||
{
|
||||
if (target.timing.h_display > si->ps.panel_width)
|
||||
{
|
||||
target.timing.h_display = si->ps.panel_width;
|
||||
LOG(4, ("CRTC: req. width > panel width: setting panning mode\n"));
|
||||
}
|
||||
if (target.timing.v_display > si->ps.panel_height)
|
||||
{
|
||||
target.timing.v_display = si->ps.panel_height;
|
||||
LOG(4, ("CRTC: req. height > panel height: setting scrolling mode\n"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Modify parameters as required by standard VGA */
|
||||
htotal = ((target.timing.h_total >> 3) - 5);
|
||||
hdisp_e = ((target.timing.h_display >> 3) - 1);
|
||||
hblnk_s = hdisp_e;
|
||||
hblnk_e = (htotal + 0); /* this register differs from standard VGA! (says + 4) */
|
||||
hsync_s = (target.timing.h_sync_start >> 3);
|
||||
hsync_e = (target.timing.h_sync_end >> 3);
|
||||
|
||||
vtotal = target.timing.v_total - 2;
|
||||
vdisp_e = target.timing.v_display - 1;
|
||||
vblnk_s = vdisp_e;
|
||||
vblnk_e = (vtotal + 1);
|
||||
vsync_s = target.timing.v_sync_start;//-1;
|
||||
vsync_e = target.timing.v_sync_end;//-1;
|
||||
|
||||
/* prevent memory adress counter from being reset (linecomp may not occur) */
|
||||
linecomp = target.timing.v_display;
|
||||
|
||||
if (crt_only)
|
||||
{
|
||||
LOG(4,("CRTC: CRT only mode, setting full timing...\n"));
|
||||
|
||||
/* log the mode that will be set */
|
||||
LOG(2,("CRTC:\n\tHTOT:%x\n\tHDISPEND:%x\n\tHBLNKS:%x\n\tHBLNKE:%x\n\tHSYNCS:%x\n\tHSYNCE:%x\n\t",htotal,hdisp_e,hblnk_s,hblnk_e,hsync_s,hsync_e));
|
||||
LOG(2,("VTOT:%x\n\tVDISPEND:%x\n\tVBLNKS:%x\n\tVBLNKE:%x\n\tVSYNCS:%x\n\tVSYNCE:%x\n",vtotal,vdisp_e,vblnk_s,vblnk_e,vsync_s,vsync_e));
|
||||
|
||||
/* actually program the card! */
|
||||
/* unlock CRTC registers at index 0-7 */
|
||||
temp = (ISACRTCR(VSYNCE) & 0x7f);
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. */
|
||||
snooze(10);
|
||||
ISACRTCW(VSYNCE, temp);
|
||||
/* horizontal standard VGA regs */
|
||||
ISACRTCW(HTOTAL, (htotal & 0xff));
|
||||
ISACRTCW(HDISPE, (hdisp_e & 0xff));
|
||||
ISACRTCW(HBLANKS, (hblnk_s & 0xff));
|
||||
/* also unlock vertical retrace registers in advance */
|
||||
ISACRTCW(HBLANKE, ((hblnk_e & 0x1f) | 0x80));
|
||||
ISACRTCW(HSYNCS, (hsync_s & 0xff));
|
||||
ISACRTCW(HSYNCE, ((hsync_e & 0x1f) | ((hblnk_e & 0x20) << 2)));
|
||||
|
||||
/* vertical standard VGA regs */
|
||||
ISACRTCW(VTOTAL, (vtotal & 0xff));
|
||||
ISACRTCW(OVERFLOW,
|
||||
(
|
||||
((vtotal & 0x100) >> (8 - 0)) | ((vtotal & 0x200) >> (9 - 5)) |
|
||||
((vdisp_e & 0x100) >> (8 - 1)) | ((vdisp_e & 0x200) >> (9 - 6)) |
|
||||
((vsync_s & 0x100) >> (8 - 2)) | ((vsync_s & 0x200) >> (9 - 7)) |
|
||||
((vblnk_s & 0x100) >> (8 - 3)) | ((linecomp & 0x100) >> (8 - 4))
|
||||
));
|
||||
ISACRTCW(PRROWSCN, 0x00); /* not used */
|
||||
ISACRTCW(MAXSCLIN, (((vblnk_s & 0x200) >> (9 - 5)) | ((linecomp & 0x200) >> (9 - 6))));
|
||||
ISACRTCW(VSYNCS, (vsync_s & 0xff));
|
||||
temp = (ISACRTCR(VSYNCE) & 0xf0);
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. */
|
||||
snooze(10);
|
||||
ISACRTCW(VSYNCE, (temp | (vsync_e & 0x0f)));
|
||||
ISACRTCW(VDISPE, (vdisp_e & 0xff));
|
||||
ISACRTCW(VBLANKS, (vblnk_s & 0xff));
|
||||
ISACRTCW(VBLANKE, (vblnk_e & 0xff));
|
||||
//linux:
|
||||
// regp->CRTC[23] = 0xC3;
|
||||
ISACRTCW(LINECOMP, (linecomp & 0xff));
|
||||
|
||||
/* horizontal - no extended regs available or needed on NeoMagic chips */
|
||||
|
||||
/* vertical - extended regs */
|
||||
//fixme: checkout if b2 or 3 should be switched! (linux contains error here)
|
||||
//fixme: linecomp should also have an extra bit... testable by setting linecomp
|
||||
//to 100 for example and then try out writing an '1' to b2, b3(!) and the rest
|
||||
//for screenorig reset visible on upper half of the screen or not at all..
|
||||
if (si->ps.card_type >= NM2200)
|
||||
ISACRTCW(VEXT,
|
||||
(
|
||||
((vtotal & 0x400) >> (10 - 0)) |
|
||||
((vdisp_e & 0x400) >> (10 - 1)) |
|
||||
((vblnk_s & 0x400) >> (10 - 2)) |
|
||||
((vsync_s & 0x400) >> (10 - 3))/*|
|
||||
((linecomp&0x400)>>3)*/
|
||||
));
|
||||
|
||||
/* setup HSYNC & VSYNC polarity */
|
||||
temp = ISARB(MISCR);
|
||||
if (vsync_pos) temp &= ~0x80;
|
||||
else temp |= 0x80;
|
||||
if (hsync_pos) temp &= ~0x40;
|
||||
else temp |= 0x40;
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. */
|
||||
snooze(10);
|
||||
ISAWB(MISCW, temp);
|
||||
|
||||
LOG(2,("CRTC: HSYNC/VSYNC polarity: %x %x, MISC reg readback: $%02x\n",
|
||||
hsync_pos, vsync_pos, ISARB(MISCR)));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(4,("CRTC: internal flatpanel active, setting display region only\n"));
|
||||
|
||||
/* actually program the card! */
|
||||
/* unlock CRTC registers at index 0-7 */
|
||||
temp = (ISACRTCR(VSYNCE) & 0x7f);
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. */
|
||||
snooze(10);
|
||||
ISACRTCW(VSYNCE, temp);
|
||||
/* horizontal standard VGA regs */
|
||||
ISACRTCW(HDISPE, (hdisp_e & 0xff));
|
||||
|
||||
/* vertical standard VGA regs */
|
||||
temp = (ISACRTCR(OVERFLOW) & ~0x52);
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. */
|
||||
snooze(10);
|
||||
ISACRTCW(OVERFLOW,
|
||||
(
|
||||
temp |
|
||||
((vdisp_e & 0x100) >> (8 - 1)) |
|
||||
((vdisp_e & 0x200) >> (9 - 6)) |
|
||||
((linecomp & 0x100) >> (8 - 4))
|
||||
));
|
||||
|
||||
ISACRTCW(PRROWSCN, 0x00); /* not used */
|
||||
|
||||
temp = (ISACRTCR(MAXSCLIN) & ~0x40);
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. */
|
||||
snooze(10);
|
||||
ISACRTCW(MAXSCLIN, (temp | ((linecomp & 0x200) >> (9 - 6))));
|
||||
|
||||
ISACRTCW(VDISPE, (vdisp_e & 0xff));
|
||||
//linux:
|
||||
// regp->CRTC[23] = 0xC3;
|
||||
ISACRTCW(LINECOMP, (linecomp & 0xff));
|
||||
|
||||
/* horizontal - no extended regs available or needed on NeoMagic chips */
|
||||
|
||||
/* vertical - extended regs */
|
||||
//fixme: linecomp should have an extra bit... testable by setting linecomp
|
||||
//to 100 for example and then try out writing an '1' to b2, b3(!) and the rest
|
||||
//for screenorig reset visible on upper half of the screen or not at all..
|
||||
if (si->ps.card_type >= NM2200)
|
||||
{
|
||||
temp = (ISACRTCR(VEXT) & ~0x02);
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. */
|
||||
snooze(10);
|
||||
ISACRTCW(VEXT,
|
||||
(
|
||||
temp |
|
||||
((vdisp_e & 0x400) >> (10 - 1))/*|
|
||||
((linecomp&0x400)>>3)*/
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t mn_crtc_depth(int mode)
|
||||
{
|
||||
uint8 vid_delay = 0;
|
||||
|
||||
LOG(4,("CRTC: setting colordepth to be displayed\n"));
|
||||
|
||||
/* set VCLK scaling */
|
||||
switch(mode)
|
||||
{
|
||||
case BPP8:
|
||||
vid_delay = 0x01;
|
||||
break;
|
||||
case BPP15:
|
||||
vid_delay = 0x02;
|
||||
break;
|
||||
case BPP16:
|
||||
vid_delay = 0x03;
|
||||
break;
|
||||
case BPP24:
|
||||
vid_delay = 0x04;
|
||||
break;
|
||||
default:
|
||||
LOG(4,("CRTC: colordepth not supported, aborting!\n"));
|
||||
return B_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
case NM2070:
|
||||
vid_delay |= (ISAGRPHR(COLDEPTH) & 0xf0);
|
||||
break;
|
||||
default:
|
||||
vid_delay |= (ISAGRPHR(COLDEPTH) & 0x70);
|
||||
break;
|
||||
}
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */
|
||||
snooze(10);
|
||||
ISAGRPHW(COLDEPTH, vid_delay);
|
||||
|
||||
snooze(10);
|
||||
LOG(4,("CRTC: colordepth register readback $%02x\n", (ISAGRPHR(COLDEPTH))));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t mn_crtc_dpms(bool display, bool h, bool v)
|
||||
{
|
||||
uint8 temp;
|
||||
|
||||
LOG(4,("CRTC: setting DPMS: "));
|
||||
|
||||
/* start synchronous reset: required before turning screen off! */
|
||||
ISASEQW(RESET, 0x01);
|
||||
|
||||
/* turn screen off */
|
||||
temp = ISASEQR(CLKMODE);
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */
|
||||
snooze(10);
|
||||
|
||||
if (display)
|
||||
{
|
||||
ISASEQW(CLKMODE, (temp & ~0x20));
|
||||
|
||||
/* end synchronous reset if display should be enabled */
|
||||
ISASEQW(RESET, 0x03);
|
||||
|
||||
LOG(4,("display on\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ISASEQW(CLKMODE, (temp | 0x20));
|
||||
|
||||
LOG(4,("display off\n"));
|
||||
}
|
||||
|
||||
// LOG(4,("CRTC: setting DPMS (%d,%d,%d)\n", display,h,v));
|
||||
|
||||
// VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0xCF)|((!v)<<5))|((!h)<<4);
|
||||
|
||||
/* set some required fixed values for proper nm mode initialisation */
|
||||
// VGAW_I(CRTC,0x17,0xC3);
|
||||
// VGAW_I(CRTC,0x14,0x00);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t mn_crtc_dpms_fetch(bool * display, bool * h, bool * v)
|
||||
{
|
||||
*display = !(ISASEQR(CLKMODE) & 0x20);
|
||||
|
||||
// *display=!((VGAR_I(SEQ,1)&0x20)>>5);
|
||||
// *h=!((VGAR_I(CRTCEXT,1)&0x10)>>4);
|
||||
// *v=!((VGAR_I(CRTCEXT,1)&0x20)>>5);
|
||||
|
||||
*h = *v = true;
|
||||
|
||||
LOG(4,("CTRC: fetched DPMS state:"));
|
||||
if (display) LOG(4,("display on\n"));
|
||||
else LOG(4,("display off\n"));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t mn_crtc_set_display_pitch()
|
||||
{
|
||||
uint32 offset;
|
||||
|
||||
LOG(4,("CRTC: setting card pitch (offset between lines)\n"));
|
||||
|
||||
/* figure out offset value hardware needs: same for all Neomagic cards */
|
||||
offset = si->fbc.bytes_per_row / 8;
|
||||
|
||||
LOG(2,("CRTC: offset register set to: $%04x\n", offset));
|
||||
|
||||
/* program the card */
|
||||
ISACRTCW(PITCHL, (offset & 0xff));
|
||||
//fixme: test for max supported pitch if possible,
|
||||
//not all bits below will be implemented.
|
||||
//NM2160: confirmed b0 and b1 in register below to exist and work.
|
||||
ISAGRPHW(CRTC_PITCHE, ((offset & 0xff00) >> 8));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t mn_crtc_set_display_start(uint32 startadd,uint8 bpp)
|
||||
{
|
||||
uint8 val;
|
||||
uint32 timeout = 0;
|
||||
|
||||
LOG(2,("CRTC: relative startadd: $%06x\n",startadd));
|
||||
LOG(2,("CRTC: frameRAM: $%08x\n",si->framebuffer));
|
||||
LOG(2,("CRTC: framebuffer: $%08x\n",si->fbc.frame_buffer));
|
||||
|
||||
/* make sure we are in retrace, because otherwise distortions might occur
|
||||
* during our reprogramming them (no double buffering) (verified on NM2160) */
|
||||
|
||||
/* we might have no retraces during setmode! So:
|
||||
* wait 25mS max. for retrace to occur (refresh > 40Hz) */
|
||||
//fixme? move this function to the kernel driver... is much 'faster'.
|
||||
while ((!(ISARB(INSTAT1) & 0x08)) && (timeout < (25000/4)))
|
||||
{
|
||||
snooze(4);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
/* the neomagic framebuffer startadress is given in 32bit words */
|
||||
startadd >>= 2;
|
||||
|
||||
/* set standard VGA registers */
|
||||
ISACRTCW(FBSTADDH, ((startadd & 0x00FF00) >> 8));
|
||||
ISACRTCW(FBSTADDL, (startadd & 0x0000FF));
|
||||
|
||||
/* set NM extended register */
|
||||
//fixme: NM2380 _must_ have one more bit (has >4Mb RAM)!!
|
||||
//this is testable via virtualscreen in 640x480x8 mode...
|
||||
//(b4 is >256Kb adresswrap bit, so that's already occupied)
|
||||
val = ISAGRPHR(FBSTADDE);
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */
|
||||
snooze(10);
|
||||
if (si->ps.card_type < NM2200)
|
||||
ISAGRPHW(FBSTADDE,(((startadd >> 16) & 0x07) | (val & 0xf8)));
|
||||
else
|
||||
ISAGRPHW(FBSTADDE,(((startadd >> 16) & 0x0f) | (val & 0xf0)));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* setup centering mode for current internal or simultaneous flatpanel mode */
|
||||
status_t mn_crtc_center(display_mode target)
|
||||
{
|
||||
uint8 vcent1, vcent2, vcent3, vcent4, vcent5;
|
||||
uint8 hcent1, hcent2, hcent3, hcent4, hcent5;
|
||||
uint8 ctrl2, ctrl3;
|
||||
|
||||
/* preset no centering */
|
||||
uint16 hoffset = 0;
|
||||
uint16 voffset = 0;
|
||||
vcent1 = vcent2 = vcent3 = vcent4 = vcent5 = 0x00;
|
||||
hcent1 = hcent2 = hcent3 = hcent4 = hcent5 = 0x00;
|
||||
ctrl2 = ctrl3 = 0x00;
|
||||
|
||||
/* calculate offsets for centering if prudent */
|
||||
if (target.timing.h_display < si->ps.panel_width)
|
||||
{
|
||||
hoffset = (si->ps.panel_width - target.timing.h_display);
|
||||
/* adjust for register contraints:
|
||||
* horizontal center granularity is 16 pixels */
|
||||
hoffset = ((hoffset >> 4) - 1);
|
||||
//fixme: what does this do?
|
||||
/* turn on horizontal centering? */
|
||||
ctrl3 = 0x10;
|
||||
}
|
||||
|
||||
if (target.timing.v_display < si->ps.panel_height)
|
||||
{
|
||||
voffset = (si->ps.panel_height - target.timing.v_display);
|
||||
/* adjust for register contraints:
|
||||
* vertical center granularity is 2 pixels */
|
||||
voffset = ((voffset >> 1) - 2);
|
||||
//fixme: what does this do?
|
||||
/* turn on vertical centering? */
|
||||
ctrl2 = 0x01;
|
||||
}
|
||||
|
||||
switch(target.timing.h_display)
|
||||
{
|
||||
case 640:
|
||||
hcent1 = hoffset;
|
||||
vcent3 = voffset;
|
||||
break;
|
||||
case 800:
|
||||
hcent2 = hoffset;
|
||||
switch(target.timing.v_display)
|
||||
{
|
||||
case 480:
|
||||
//Linux fixme: check this out...
|
||||
vcent3 = voffset;
|
||||
break;
|
||||
case 600:
|
||||
vcent4 = voffset;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1024:
|
||||
hcent5 = hoffset;
|
||||
vcent5 = voffset;
|
||||
break;
|
||||
case 1280:
|
||||
/* this mode equals the largest possible panel on the newest chip:
|
||||
* so no centering needed here. */
|
||||
break;
|
||||
default:
|
||||
//fixme?: block non-standard modes? for now: not centered.
|
||||
break;
|
||||
}
|
||||
|
||||
/* now program the card's registers */
|
||||
ISAGRPHW(PANELVCENT1, vcent1);
|
||||
ISAGRPHW(PANELVCENT2, vcent2);
|
||||
ISAGRPHW(PANELVCENT3, vcent3);
|
||||
if (si->ps.card_type > NM2070)
|
||||
{
|
||||
ISAGRPHW(PANELVCENT4, vcent4);
|
||||
ISAGRPHW(PANELHCENT1, hcent1);
|
||||
ISAGRPHW(PANELHCENT2, hcent2);
|
||||
ISAGRPHW(PANELHCENT3, hcent3);
|
||||
}
|
||||
if (si->ps.card_type >= NM2160)
|
||||
{
|
||||
ISAGRPHW(PANELHCENT4, hcent4);
|
||||
}
|
||||
if (si->ps.card_type >= NM2200)
|
||||
{
|
||||
ISAGRPHW(PANELVCENT5, vcent5);
|
||||
ISAGRPHW(PANELHCENT5, hcent5);
|
||||
}
|
||||
|
||||
/* program panel control register 2: don't touch bit 3-5 */
|
||||
ctrl2 |= (ISAGRPHR(PANELCTRL2) & 0x38);
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */
|
||||
snooze(10);
|
||||
ISAGRPHW(PANELCTRL2, ctrl2);
|
||||
|
||||
if (si->ps.card_type > NM2070)
|
||||
{
|
||||
/* program panel control register 3: don't touch bit 7-5 and bit 3-0 */
|
||||
ctrl3 |= (ISAGRPHR(PANELCTRL3) & 0xef);
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. (NM2160) */
|
||||
snooze(10);
|
||||
ISAGRPHW(PANELCTRL3, ctrl3);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t mn_crtc_cursor_init()
|
||||
{
|
||||
int i;
|
||||
uint32 * fb;
|
||||
/* cursor bitmap will be stored at the start of the framebuffer */
|
||||
uint32 curadd = 0, curreg;
|
||||
|
||||
/* set cursor bitmap adress on a 1kb boundary, and move the bits around
|
||||
* so they get placed at the correct registerbits */
|
||||
//fixme: NM2380 must have an extra bit for > 4Mb???
|
||||
curreg = (((curadd >> 10) & 0x000f) << 8);
|
||||
curreg |= (((curadd >> 10) & 0x0ff0) >> 4);
|
||||
|
||||
if (si->ps.card_type < NM2200)
|
||||
CR1W(CURADDRESS, curreg);
|
||||
else
|
||||
CR1W(22CURADDRESS, curreg);
|
||||
|
||||
/*set cursor colour*/
|
||||
if (si->ps.card_type < NM2200)
|
||||
{
|
||||
/* background is black */
|
||||
CR1W(CURBGCOLOR, 0x00000000);
|
||||
/* foreground is white */
|
||||
CR1W(CURFGCOLOR, 0x00ffffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* background is black */
|
||||
CR1W(22CURBGCOLOR, 0x00000000);
|
||||
/* foreground is white */
|
||||
CR1W(22CURFGCOLOR, 0x00ffffff);
|
||||
}
|
||||
|
||||
/*clear cursor*/
|
||||
fb = (uint32 *) si->framebuffer + curadd;
|
||||
for (i=0;i<(1024/4);i++)
|
||||
{
|
||||
fb[i]=0;
|
||||
}
|
||||
|
||||
/* activate hardware cursor */
|
||||
mn_crtc_cursor_show();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t mn_crtc_cursor_show()
|
||||
{
|
||||
if (si->ps.card_type < NM2200)
|
||||
{
|
||||
CR1W(CURCTRL, 0x00000001);
|
||||
}
|
||||
else
|
||||
{
|
||||
CR1W(22CURCTRL, 0x00000001);
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t mn_crtc_cursor_hide()
|
||||
{
|
||||
//linux fixme: using this kills PCI(?) access sometimes, so use ISA access as below...
|
||||
/*
|
||||
if (si->ps.card_type < NM2200)
|
||||
{
|
||||
CR1W(CURCTRL, 0x00000000);
|
||||
}
|
||||
else
|
||||
{
|
||||
CR1W(22CURCTRL, 0x00000000);
|
||||
}
|
||||
*/
|
||||
/* disable cursor */
|
||||
ISAGRPHW(CURCTRL,0x00);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*set up cursor shape*/
|
||||
status_t mn_crtc_cursor_define(uint8* andMask,uint8* xorMask)
|
||||
{
|
||||
uint8 y;
|
||||
uint8 * cursor;
|
||||
|
||||
/*get a pointer to the cursor*/
|
||||
cursor = (uint8*) si->framebuffer;
|
||||
|
||||
/*draw the cursor*/
|
||||
for(y=0;y<16;y++)
|
||||
{
|
||||
cursor[y*16+8]=~*andMask++;
|
||||
cursor[y*16+0]=*xorMask++;
|
||||
cursor[y*16+9]=~*andMask++;
|
||||
cursor[y*16+1]=*xorMask++;
|
||||
}
|
||||
|
||||
//test.. only valid for <NM2200!!
|
||||
{
|
||||
float pclk;
|
||||
uint8 n,m,x = 1;
|
||||
n = ISAGRPHR(PLLC_NL);
|
||||
m = ISAGRPHR(PLLC_M);
|
||||
LOG(4,("CRTC: PLLSEL $%02x\n", ISARB(MISCR)));
|
||||
LOG(4,("CRTC: PLLN $%02x\n", n));
|
||||
LOG(4,("CRTC: PLLM $%02x\n", m));
|
||||
|
||||
if (n & 0x80) x = 2;
|
||||
n &= 0x7f;
|
||||
pclk = ((si->ps.f_ref * (n + 1)) / ((m + 1) * x));
|
||||
LOG(2,("CRTC: Pixelclock is %fMHz\n", pclk));
|
||||
nm_general_output_select();
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*position the cursor*/
|
||||
status_t mn_crtc_cursor_position(uint16 x ,uint16 y)
|
||||
{
|
||||
//NM2160 is ok without this, still verify the rest..:
|
||||
/* make sure we are not in retrace, because the register(s) might get copied
|
||||
* during our reprogramming them (double buffering feature) */
|
||||
/* fixme!?
|
||||
while (ACCR(STATUS) & 0x08)
|
||||
{
|
||||
snooze(4);
|
||||
}
|
||||
*/
|
||||
if (si->ps.card_type < NM2200)
|
||||
{
|
||||
CR1W(CURX, (uint32)x);
|
||||
CR1W(CURY, (uint32)y);
|
||||
}
|
||||
else
|
||||
{
|
||||
CR1W(22CURX, (uint32)x);
|
||||
CR1W(22CURY, (uint32)y);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
/* program the DAC */
|
||||
/* Author:
|
||||
Rudolf Cornelissen 4/2003-5/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00010000
|
||||
|
||||
#include "nm_std.h"
|
||||
|
||||
/*set the mode, brightness is a value from 0->2 (where 1 is equivalent to direct)*/
|
||||
status_t mn_dac_mode(int mode,float brightness)
|
||||
{
|
||||
uint8 *r, *g, *b, t[256];
|
||||
uint16 i;
|
||||
|
||||
/*set colour arrays to point to space reserved in shared info*/
|
||||
r = si->color_data;
|
||||
g = r + 256;
|
||||
b = g + 256;
|
||||
|
||||
LOG(4,("DAC: Setting screen mode %d brightness %f\n", mode, brightness));
|
||||
/*init a basic palette for brightness specified*/
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
int ri = i * brightness;
|
||||
if (ri > 255) ri = 255;
|
||||
t[i] = ri;
|
||||
}
|
||||
|
||||
/*modify the palette for the specified mode (&validate mode)*/
|
||||
/* Note: the Neomagic chips have a 6 bit wide Palette RAM! */
|
||||
switch(mode)
|
||||
{
|
||||
case BPP8:
|
||||
LOG(8,("DAC: 8bit mode is indexed by OS, aborting brightness setup.\n"));
|
||||
return B_OK;
|
||||
break;
|
||||
case BPP24:
|
||||
LOG(8,("DAC: 24bit mode is a direct mode, aborting brightness setup.\n"));
|
||||
return B_OK;
|
||||
//fixme: unnessesary? direct mode (6bits PAL RAM is insufficient here!)
|
||||
/* for (i = 0; i < 256; i++)
|
||||
{
|
||||
b[i] = g[i] = r[i] = t[i];
|
||||
}
|
||||
*/ break;
|
||||
case BPP16:
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
/* blue and red have only the 5 most significant bits */
|
||||
b[i] = r[i] = t[i << 3];
|
||||
}
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
/* the green component has 6 bits */
|
||||
g[i] = t[i << 2];
|
||||
}
|
||||
break;
|
||||
case BPP15:
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
/* all color components have 5 bits */
|
||||
g[i] = r[i] = b[i] = t[i << 3];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG(8,("DAC: Invalid colordepth requested, aborting!\n"));
|
||||
return B_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mn_dac_palette(r, g, b, i) != B_OK) return B_ERROR;
|
||||
|
||||
/*set the mode - also sets VCLK dividor*/
|
||||
// DXIW(MULCTRL, mode);
|
||||
// LOG(2,("DAC: mulctrl 0x%02x\n", DXIR(MULCTRL)));
|
||||
|
||||
/* disable palette RAM adressing mask */
|
||||
ISAWB(PALMASK, 0xff);
|
||||
LOG(2,("DAC: PAL pixrdmsk readback $%02x\n", ISARB(PALMASK)));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* program the DAC palette using the given r,g,b values */
|
||||
status_t mn_dac_palette(uint8 r[256],uint8 g[256],uint8 b[256], uint16 cnt)
|
||||
{
|
||||
int i;
|
||||
|
||||
LOG(4,("DAC: setting palette\n"));
|
||||
|
||||
/* select first PAL adress before starting programming */
|
||||
ISAWB(PALINDW, 0x00);
|
||||
|
||||
/* loop through all 256 to program DAC */
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
/* the 6 implemented bits are on b0-b5 of the bus */
|
||||
ISAWB(PALDATA, (r[i] >> 2));
|
||||
ISAWB(PALDATA, (g[i] >> 2));
|
||||
ISAWB(PALDATA, (b[i] >> 2));
|
||||
}
|
||||
if (ISARB(PALINDW) != (cnt & 0x00ff))
|
||||
{
|
||||
LOG(8,("DAC: PAL write index incorrect after programming\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
if (1)
|
||||
{//reread LUT
|
||||
uint8 R, G, B;
|
||||
|
||||
/* select first PAL adress to read (modulo 3 counter) */
|
||||
ISAWB(PALINDR, 0x00);
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
/* the 6 implemented bits are on b0-b5 of the bus */
|
||||
R = (ISARB(PALDATA) << 2);
|
||||
G = (ISARB(PALDATA) << 2);
|
||||
B = (ISARB(PALDATA) << 2);
|
||||
/* only compare the most significant 6 bits */
|
||||
if (((r[i] & 0xfc) != R) || ((g[i] & 0xfc) != G) || ((b[i] & 0xfc) != B))
|
||||
LOG(1,("DAC palette %d: w %x %x %x, r %x %x %x\n", i, r[i], g[i], b[i], R, G, B)); // apsed
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*program the pixpll - frequency in kHz*/
|
||||
/* important note:
|
||||
* PIXPLLC is used - others should be kept as is
|
||||
*/
|
||||
status_t mn_dac_set_pix_pll(display_mode target)
|
||||
{
|
||||
uint8 m=0,n=0,p=0;
|
||||
uint8 temp;
|
||||
// uint time = 0;
|
||||
|
||||
float pix_setting, req_pclk;
|
||||
status_t result;
|
||||
|
||||
req_pclk = (target.timing.pixel_clock)/1000.0;
|
||||
LOG(4,("DAC: Setting PIX PLL for pixelclock %f\n", req_pclk));
|
||||
|
||||
result = mn_dac_pix_pll_find(target,&pix_setting,&m,&n,&p);
|
||||
if (result != B_OK)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/*reprogram (disable,select,wait for stability,enable)*/
|
||||
//unknown on Neomagic?:
|
||||
// DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0F)|0x04); /*disable the PIXPLL*/
|
||||
// DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0C)|0x01); /*select the PIXPLL*/
|
||||
|
||||
/* select PixelPLL registerset C */
|
||||
temp = (ISARB(MISCR) | 0x0c);
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. */
|
||||
snooze(10);
|
||||
ISAWB(MISCW, temp);
|
||||
|
||||
/*set VCO divider (lsb) */
|
||||
ISAGRPHW(PLLC_NL, n);
|
||||
/*set VCO divider (msb) if it exists */
|
||||
if (si->ps.card_type >= NM2200)
|
||||
{
|
||||
temp = (ISAGRPHR(PLLC_NH) & 0x0f);
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. */
|
||||
snooze(10);
|
||||
ISAGRPHW(PLLC_NH, (temp | (p & 0xf0)));
|
||||
}
|
||||
/*set main reference frequency divider */
|
||||
ISAGRPHW(PLLC_M, m);
|
||||
|
||||
/* Wait for the PIXPLL frequency to lock until timeout occurs */
|
||||
//unknown on Neomagic?:
|
||||
/* while((!(DXIR(PIXPLLSTAT)&0x40)) & (time <= 2000))
|
||||
{
|
||||
time++;
|
||||
snooze(1);
|
||||
}
|
||||
|
||||
if (time > 2000)
|
||||
LOG(2,("DAC: PIX PLL frequency not locked!\n"));
|
||||
else
|
||||
LOG(2,("DAC: PIX PLL frequency locked\n"));
|
||||
DXIW(PIXCLKCTRL,DXIR(PIXCLKCTRL)&0x0B); //enable the PIXPLL
|
||||
*/
|
||||
|
||||
//for now:
|
||||
/* Give the PIXPLL frequency some time to lock... */
|
||||
snooze(1000);
|
||||
LOG(4,("DAC: PLLSEL $%02x\n", ISARB(MISCR)));
|
||||
LOG(4,("DAC: PLLN $%02x\n", ISAGRPHR(PLLC_NL)));
|
||||
LOG(4,("DAC: PLLM $%02x\n", ISAGRPHR(PLLC_M)));
|
||||
|
||||
LOG(2,("DAC: PIX PLL frequency should be locked now...\n"));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* find nearest valid pix pll */
|
||||
status_t mn_dac_pix_pll_find
|
||||
(display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result)
|
||||
{
|
||||
int m = 0, n = 0, p = 0, n_max;
|
||||
float error, error_best = 999999999;
|
||||
int best[2];
|
||||
float f_vco, max_pclk;
|
||||
float req_pclk = target.timing.pixel_clock/1000.0;
|
||||
|
||||
/* determine the max. VCO oscillator postscaler setting for the current card */
|
||||
if (si->ps.card_type < NM2200)
|
||||
{
|
||||
LOG(4,("DAC: NM20xx/NM21xx restrictions apply\n"));
|
||||
n_max = 128;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(4,("DAC: NM22xx/NM23xx restrictions apply\n"));
|
||||
n_max = 2048;
|
||||
}
|
||||
|
||||
/* determine the max. pixelclock for the current videomode */
|
||||
switch (target.space)
|
||||
{
|
||||
case B_CMAP8:
|
||||
max_pclk = si->ps.max_dac1_clock_8;
|
||||
break;
|
||||
case B_RGB15_LITTLE:
|
||||
case B_RGB16_LITTLE:
|
||||
max_pclk = si->ps.max_dac1_clock_16;
|
||||
break;
|
||||
case B_RGB24_LITTLE:
|
||||
max_pclk = si->ps.max_dac1_clock_24;
|
||||
break;
|
||||
default:
|
||||
/* use fail-safe value */
|
||||
max_pclk = si->ps.max_dac1_clock_24;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure the requested pixelclock is within the PLL's operational limits */
|
||||
/* lower limit is min_pixel_vco (PLL postscaler does not exist in NM cards) */
|
||||
if (req_pclk < si->ps.min_pixel_vco)
|
||||
{
|
||||
LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n",
|
||||
req_pclk, (float)si->ps.min_pixel_vco));
|
||||
req_pclk = si->ps.min_pixel_vco;
|
||||
}
|
||||
/* upper limit is given by pins in combination with current active mode */
|
||||
if (req_pclk > max_pclk)
|
||||
{
|
||||
LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n",
|
||||
req_pclk, (float)max_pclk));
|
||||
req_pclk = max_pclk;
|
||||
}
|
||||
|
||||
/* calculate the needed VCO frequency for this postscaler setting
|
||||
* (NM cards have no PLL postscaler) */
|
||||
f_vco = req_pclk;
|
||||
|
||||
/* iterate trough all valid reference-frequency postscaler settings */
|
||||
for (m = 1; m <= 64; m++)
|
||||
{
|
||||
/* only even reference postscaler settings are supported beyond 32 */
|
||||
if ((m > 32) && ((m / 2.0) != 0.0)) continue;
|
||||
/* calculate VCO postscaler setting for current setup.. */
|
||||
n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5);
|
||||
/* ..and check for validity */
|
||||
if ((n < 1) || (n > n_max)) continue;
|
||||
|
||||
/* find error in frequency this setting gives */
|
||||
error = fabs(req_pclk - ((si->ps.f_ref / m) * n));
|
||||
|
||||
/* note the setting if best yet */
|
||||
if (error < error_best)
|
||||
{
|
||||
error_best = error;
|
||||
best[0] = m;
|
||||
best[1] = n;
|
||||
}
|
||||
}
|
||||
|
||||
/* setup the scalers programming values for found optimum setting */
|
||||
n = best[1] - 1;
|
||||
/* the reference frequency postscaler are actually two postscalers:
|
||||
* p can divide by 1 or 2, and m can divide by 1-32. */
|
||||
if (best[0] <= 32)
|
||||
{
|
||||
m = best[0] - 1;
|
||||
p = (0 << 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
m = (best[0] / 2) - 1;
|
||||
p = (1 << 7);
|
||||
}
|
||||
|
||||
/* display and return the results */
|
||||
*calc_pclk = (si->ps.f_ref / best[0]) * best[1];
|
||||
*m_result = m;
|
||||
if (si->ps.card_type < NM2200)
|
||||
{
|
||||
*n_result = ((n & 0x07f) | p);
|
||||
*p_result = 0;
|
||||
LOG(2,("DAC: pix PLL check: requested %fMHz got %fMHz, nm $%02x $%02x\n",
|
||||
req_pclk, *calc_pclk, *n_result, *m_result));
|
||||
}
|
||||
else
|
||||
{
|
||||
*n_result = (n & 0x0ff);
|
||||
*p_result = (((n & 0x700) >> 4) | p);
|
||||
LOG(2,("DAC: pix PLL check: requested %fMHz got %fMHz, pnm $%02x $%02x $%02x\n",
|
||||
req_pclk, *calc_pclk, *p_result, *n_result, *m_result));
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,514 @@
|
||||
/* Author:
|
||||
Rudolf Cornelissen 4/2003-6/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00008000
|
||||
|
||||
#include "nm_std.h"
|
||||
|
||||
status_t test_ram();
|
||||
static status_t nm_general_powerup (void);
|
||||
static status_t mn_general_bios_to_powergraphics(void);
|
||||
|
||||
static void nm_dump_configuration_space (void)
|
||||
{
|
||||
#define DUMP_CFG(reg, type) if (si->ps.card_type >= type) do { \
|
||||
uint32 value = CFGR(reg); \
|
||||
MSG(("configuration_space 0x%02x %20s 0x%08x\n", \
|
||||
NMCFG_##reg, #reg, value)); \
|
||||
} while (0)
|
||||
DUMP_CFG (DEVID, 0);
|
||||
DUMP_CFG (DEVCTRL, 0);
|
||||
DUMP_CFG (CLASS, 0);
|
||||
DUMP_CFG (HEADER, 0);
|
||||
DUMP_CFG (NMBASE2, 0);
|
||||
DUMP_CFG (NMBASE1, 0);
|
||||
DUMP_CFG (NMBASE3, 0);
|
||||
DUMP_CFG (SUBSYSIDR, 0);
|
||||
DUMP_CFG (ROMBASE, 0);
|
||||
DUMP_CFG (CAP_PTR, 0);
|
||||
DUMP_CFG (INTCTRL, 0);
|
||||
DUMP_CFG (OPTION, 0);
|
||||
DUMP_CFG (NM_INDEX, 0);
|
||||
DUMP_CFG (NM_DATA, 0);
|
||||
DUMP_CFG (SUBSYSIDW, 0);
|
||||
DUMP_CFG (OPTION2, G100);
|
||||
DUMP_CFG (OPTION3, 0);
|
||||
DUMP_CFG (OPTION4, 0);
|
||||
DUMP_CFG (PM_IDENT, G100);
|
||||
DUMP_CFG (PM_CSR, G100);
|
||||
DUMP_CFG (AGP_IDENT, 0);
|
||||
DUMP_CFG (AGP_STS, 0);
|
||||
DUMP_CFG (AGP_CMD, 0);
|
||||
#undef DUMP_CFG
|
||||
}
|
||||
|
||||
status_t mn_general_powerup()
|
||||
{
|
||||
status_t status;
|
||||
|
||||
LOG(1,("POWERUP: Neomagic (open)BeOS Accelerant 0.03 running.\n"));
|
||||
|
||||
/* detect card type and power it up */
|
||||
switch(CFGR(DEVID))
|
||||
{
|
||||
case 0x000110c8: //NM2070
|
||||
si->ps.card_type = NM2070;
|
||||
LOG(4,("POWERUP: Detected MagicGraph 128 (NM2070)\n"));
|
||||
break;
|
||||
case 0x000210c8: //NM2090
|
||||
si->ps.card_type = NM2090;
|
||||
LOG(4,("POWERUP: Detected MagicGraph 128V (NM2090)\n"));
|
||||
break;
|
||||
case 0x000310c8: //NM2093
|
||||
si->ps.card_type = NM2093;
|
||||
LOG(4,("POWERUP: Detected MagicGraph 128ZV (NM2093)\n"));
|
||||
break;
|
||||
case 0x008310c8: //NM2097 PCI
|
||||
si->ps.card_type = NM2097;
|
||||
LOG(4,("POWERUP: Detected MagicGraph 128ZV+ (NM2097)\n"));
|
||||
break;
|
||||
case 0x000410c8: //NM2160 PCI
|
||||
si->ps.card_type = NM2160;
|
||||
LOG(4,("POWERUP: Detected MagicGraph 128XD (NM2160)\n"));
|
||||
break;
|
||||
case 0x000510c8: //NM2200
|
||||
si->ps.card_type = NM2200;
|
||||
LOG(4,("POWERUP: Detected MagicMedia 256AV (NM2200)\n"));
|
||||
break;
|
||||
case 0x002510c8: //NM2230
|
||||
si->ps.card_type = NM2230;
|
||||
LOG(4,("POWERUP: Detected MagicMedia 256AV+ (NM2230)\n"));
|
||||
break;
|
||||
case 0x000610c8: //NM2360
|
||||
si->ps.card_type = NM2360;
|
||||
LOG(4,("POWERUP: Detected MagicMedia 256ZX (NM2360)\n"));
|
||||
break;
|
||||
case 0x001610c8: //NM2380
|
||||
si->ps.card_type = NM2380;
|
||||
LOG(4,("POWERUP: Detected MagicMedia 256XL+ (NM2380)\n"));
|
||||
break;
|
||||
default:
|
||||
LOG(8,("POWERUP: Failed to detect valid card 0x%08x\n",CFGR(DEVID)));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/* power up the card */
|
||||
status = nm_general_powerup();
|
||||
|
||||
/* override memory detection if requested by user */
|
||||
if (si->settings.memory != 0)
|
||||
si->ps.memory_size = si->settings.memory;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
status_t test_ram()
|
||||
{
|
||||
uint32 value, offset;
|
||||
status_t result = B_OK;
|
||||
|
||||
/* make sure we don't corrupt the hardware cursor by using fbc.frame_buffer. */
|
||||
if (si->fbc.frame_buffer == NULL)
|
||||
{
|
||||
LOG(8,("INIT: test_ram detected NULL pointer.\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
|
||||
{
|
||||
/* write testpattern to cardRAM */
|
||||
((uint32 *)si->fbc.frame_buffer)[offset] = value;
|
||||
/* toggle testpattern */
|
||||
value = 0xffffffff - value;
|
||||
}
|
||||
|
||||
for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
|
||||
{
|
||||
/* readback and verify testpattern from cardRAM */
|
||||
if (((uint32 *)si->fbc.frame_buffer)[offset] != value) result = B_ERROR;
|
||||
/* toggle testpattern */
|
||||
value = 0xffffffff - value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* NOTE:
|
||||
* This routine *has* to be done *after* SetDispplayMode has been executed,
|
||||
* or test results will not be representative!
|
||||
* (CAS latency is dependant on nm setup on some (DRAM) boards) */
|
||||
status_t nm_set_cas_latency()
|
||||
{
|
||||
/* check current RAM access to see if we need to change anything */
|
||||
if (test_ram() == B_OK)
|
||||
{
|
||||
LOG(4,("INIT: RAM access OK.\n"));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* check if we read PINS at starttime so we have valid registersettings at our disposal */
|
||||
LOG(4,("INIT: RAM access errors; not fixable: missing coldstart specs.\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
static
|
||||
status_t nm_general_powerup()
|
||||
{
|
||||
uint8 temp;
|
||||
// status_t result;
|
||||
|
||||
LOG(4, ("INIT: powerup\n"));
|
||||
if (si->settings.logmask & 0x80000000) nm_dump_configuration_space();
|
||||
|
||||
/* set ISA registermapping to VGA colormode */
|
||||
temp = (ISARB(MISCR) | 0x01);
|
||||
/* we need to wait a bit or the card will mess-up it's register values.. */
|
||||
snooze(10);
|
||||
ISAWB(MISCW, temp);
|
||||
|
||||
/* unlock cards GRAPHICS registers (any other value than 0x26 should lock it again) */
|
||||
ISAGRPHW(GRPHXLOCK,0x26);
|
||||
|
||||
/* unlock shadow registers */
|
||||
// ISAGRPHW(GENLOCK,0x00);//0x01??
|
||||
|
||||
/* initialize the shared_info struct */
|
||||
set_specs();
|
||||
/* log the struct settings */
|
||||
dump_specs();
|
||||
|
||||
/* activate PCI access: b7 = framebuffer, b6 = registers */
|
||||
ISAGRPHW(IFACECTRL, 0xc0);
|
||||
|
||||
/* disable VGA-mode cursor (just to be sure) */
|
||||
ISACRTCW(VGACURCTRL, 0x00);
|
||||
|
||||
/* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */
|
||||
/*if (si->settings.usebios || (result != B_OK)) */return mn_general_bios_to_powergraphics();
|
||||
|
||||
/*power up the PLLs,LUT,DAC*/
|
||||
LOG(2,("INIT: powerup\n"));
|
||||
|
||||
/* turn off both displays and the hardcursor (also disables transfers) */
|
||||
mn_crtc_dpms(false, false, false);
|
||||
mn_crtc_cursor_hide();
|
||||
|
||||
/* setup sequencer clocking mode */
|
||||
ISASEQW(CLKMODE, 0x21);
|
||||
|
||||
/* G100 SGRAM and SDRAM use external pix and dac refs, do *not* activate internals!
|
||||
* (this would create electrical shortcuts,
|
||||
* resulting in extra chip heat and distortions visible on screen */
|
||||
/* set voltage reference - using DAC reference block partly */
|
||||
// DXIW(VREFCTRL,0x03);
|
||||
/* wait for 100ms for voltage reference to stabilize */
|
||||
delay(100000);
|
||||
/* power up the SYSPLL */
|
||||
// CFGW(OPTION,CFGR(OPTION)|0x20);
|
||||
/* power up the PIXPLL */
|
||||
// DXIW(PIXCLKCTRL,0x08);
|
||||
|
||||
/* disable pixelclock oscillations before switching on CLUT */
|
||||
// DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
|
||||
/* disable 15bit mode CLUT-overlay function */
|
||||
// DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
|
||||
/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
|
||||
// DXIW(MISCCTRL,0x1b);
|
||||
// snooze(250);
|
||||
/* re-enable pixelclock oscillations */
|
||||
// DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) & 0xfb));
|
||||
|
||||
/*make sure card is in powergraphics mode*/
|
||||
// VGAW_I(CRTCEXT,3,0x80);
|
||||
|
||||
/*set the system clocks to powergraphics speed*/
|
||||
// LOG(2,("INIT: Setting system PLL to powergraphics speeds\n"));
|
||||
// g100_dac_set_sys_pll();
|
||||
|
||||
/* 'official' RAM initialisation */
|
||||
// LOG(2,("INIT: RAM init\n"));
|
||||
/* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */
|
||||
// ACCW(PLNWT,0x00000000);
|
||||
// ACCW(PLNWT,0xffffffff);
|
||||
/* program memory control waitstates */
|
||||
// ACCW(MCTLWTST,si->ps.mctlwtst_reg);
|
||||
/* set memory configuration including:
|
||||
* - no split framebuffer.
|
||||
* - Mark says b14 (G200) should be done also though not defined for G100 in spec,
|
||||
* - b3 v3_mem_type was included by Mark for memconfig setup: but looks like not defined */
|
||||
// CFGW(OPTION,(CFGR(OPTION)&0xFFFF8FFF) | ((si->ps.v3_mem_type & 0x04) << 10));
|
||||
/* set memory buffer type:
|
||||
* - Mark says: if((v3_mem_type & 0x03) == 0x03) then do not or-in bits in option2;
|
||||
* but looks like v3_mem_type b1 is not defined,
|
||||
* - Mark also says: place v3_mem_type b1 in option2 bit13 (if not 0x03) but b13 = reserved. */
|
||||
// CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFCFFF)|((si->ps.v3_mem_type & 0x01) << 12));
|
||||
/* set RAM read tap delay */
|
||||
// CFGW(OPTION2,(CFGR(OPTION2)&0xFFFFFFF0) | ((si->ps.v3_mem_type & 0xf0) >> 4));
|
||||
/* wait 200uS minimum */
|
||||
// snooze(250);
|
||||
|
||||
/* reset memory (MACCESS is a write only register!) */
|
||||
// ACCW(MACCESS, 0x00000000);
|
||||
/* select JEDEC reset method */
|
||||
// ACCW(MACCESS, 0x00004000);
|
||||
/* perform actual RAM reset */
|
||||
// ACCW(MACCESS, 0x0000c000);
|
||||
// snooze(250);
|
||||
/* start memory refresh */
|
||||
// CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
|
||||
/* set memory control waitstate again AFTER the RAM reset */
|
||||
// ACCW(MCTLWTST,si->ps.mctlwtst_reg);
|
||||
/* end 'official' RAM initialisation. */
|
||||
|
||||
/* Bus parameters: enable retries, use advanced read */
|
||||
// CFGW(OPTION,(CFGR(OPTION)|(1<<22)|(0<<29)));
|
||||
|
||||
/*enable writing to crtc registers*/
|
||||
// VGAW_I(CRTC,0x11,0);
|
||||
|
||||
/* turn on display */
|
||||
mn_crtc_dpms(true, true, true);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t nm_general_output_select()
|
||||
{
|
||||
/* log currently selected output */
|
||||
switch (nm_general_output_read())
|
||||
{
|
||||
case 0x01:
|
||||
LOG(2, ("INIT: external CRT only mode active\n"));
|
||||
break;
|
||||
case 0x02:
|
||||
LOG(2, ("INIT: internal LCD only mode active\n"));
|
||||
break;
|
||||
case 0x03:
|
||||
LOG(2, ("INIT: simultaneous LCD/CRT mode active\n"));
|
||||
break;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
uint8 nm_general_output_read()
|
||||
{
|
||||
uint8 output;
|
||||
|
||||
output = (ISAGRPHR(PANELCTRL1) & 0x03);
|
||||
|
||||
if (output == 0)
|
||||
{
|
||||
/* using 'failsafe' mode: the flatpanel needs all the protection it can get... */
|
||||
LOG(4, ("INIT: illegal outputmode detected, reporting internal mode!\n"));
|
||||
output = 2;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/*busy wait until retrace!*/
|
||||
status_t mn_general_wait_retrace()
|
||||
{
|
||||
while (!(ACCR(STATUS)&0x8));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* basic change of card state from VGA to powergraphics -> should work from BIOS init state*/
|
||||
static
|
||||
status_t mn_general_bios_to_powergraphics()
|
||||
{
|
||||
LOG(2, ("INIT: Skipping card coldstart!\n"));
|
||||
|
||||
/* turn off display */
|
||||
mn_crtc_dpms(false, false, false);
|
||||
|
||||
/* set card to 'enhanced' mode: (only VGA standard registers used for NeoMagic cards) */
|
||||
/* (keep) card enabled, set plain normal memory usage, no old VGA 'tricks' ... */
|
||||
ISACRTCW(MODECTL, 0xc3);
|
||||
/* ... plain sequential memory use, more than 64Kb RAM installed,
|
||||
* switch to graphics mode ... */
|
||||
ISASEQW(MEMMODE, 0x0e);
|
||||
/* ... disable bitplane tweaking ... */
|
||||
ISAGRPHW(ENSETRESET, 0x00);
|
||||
/* ... no logical function tweaking with display data, no data rotation ... */
|
||||
ISAGRPHW(DATAROTATE, 0x00);
|
||||
/* ... reset read map select to plane 0 ... */
|
||||
ISAGRPHW(READMAPSEL, 0x00);
|
||||
/* ... set standard mode ... */
|
||||
ISAGRPHW(MODE, 0x00);
|
||||
/* ... ISA framebuffer mapping is 64Kb window, switch to graphics mode (again),
|
||||
* select standard adressing ... */
|
||||
ISAGRPHW(MISC, 0x05);
|
||||
/* ... disable bit masking ... */
|
||||
ISAGRPHW(BITMASK, 0xff);
|
||||
/* ... attributes are in color, switch to graphics mode (again) ... */
|
||||
ISAATBW(MODECTL, 0x01);
|
||||
/* ... set overscan color to black ... */
|
||||
ISAATBW(OSCANCOLOR, 0x00);
|
||||
/* ... enable all color planes ... */
|
||||
ISAATBW(COLPLANE_EN, 0x0f);
|
||||
/* ... reset horizontal pixelpanning ... */
|
||||
ISAATBW(HORPIXPAN, 0x00);
|
||||
/* ... and reset colorpalette groupselect bits. */
|
||||
ISAATBW(COLSEL, 0x00);
|
||||
|
||||
/* setup sequencer clocking mode */
|
||||
ISASEQW(CLKMODE, 0x21);
|
||||
|
||||
/* enable memory above 256Kb: set b4 (disables adress wraparound at 256Kb boundary) */
|
||||
ISAGRPHW(FBSTADDE, 0x10);
|
||||
|
||||
/* turn on display */
|
||||
mn_crtc_dpms(true, true, true);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* Check if mode virtual_size adheres to the cards _maximum_ contraints, and modify
|
||||
* virtual_size to the nearest valid maximum for the mode on the card if not so.
|
||||
* Then: check if virtual_width adheres to the cards _multiple_ constraints, and
|
||||
* create mode slopspace if not so.
|
||||
* We use acc multiple constraints here if we expect we can use acceleration, because
|
||||
* acc constraints are worse than CRTC constraints.
|
||||
*
|
||||
* Mode slopspace is reflected in fbc->bytes_per_row BTW. */
|
||||
status_t mn_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row)
|
||||
{
|
||||
/* Note:
|
||||
* This routine assumes that the CRTC memory pitch granularity is 'smaller than',
|
||||
* or 'equals' the acceleration engine memory pitch granularity! */
|
||||
|
||||
uint32 video_pitch;
|
||||
uint32 acc_mask, crtc_mask;
|
||||
uint8 depth = 8;
|
||||
|
||||
//fixme: checkout the acc pitch constraints for all cards...
|
||||
/* determine pixel multiple based on 2D/3D engine constraints */
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
/* case G100:
|
||||
switch (target->space)
|
||||
{
|
||||
case B_CMAP8: acc_mask = 0x7f; depth = 8; break;
|
||||
case B_RGB15: acc_mask = 0x3f; depth = 16; break;
|
||||
case B_RGB16: acc_mask = 0x3f; depth = 16; break;
|
||||
case B_RGB24: acc_mask = 0x7f; depth = 24; break;
|
||||
default:
|
||||
LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space));
|
||||
return B_ERROR;
|
||||
}
|
||||
break;
|
||||
*/ default:
|
||||
/* see G100 and up specs:
|
||||
* these cards can do 2D as long as multiples of 32 are used.
|
||||
* (Note: don't mix this up with adress linearisation!) */
|
||||
switch (target->space)
|
||||
{
|
||||
case B_CMAP8: depth = 8; break;
|
||||
case B_RGB15: depth = 16; break;
|
||||
case B_RGB16: depth = 16; break;
|
||||
case B_RGB24: depth = 24; break;
|
||||
default:
|
||||
LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space));
|
||||
return B_ERROR;
|
||||
}
|
||||
//assuming accpitch = 32 for now..
|
||||
acc_mask = 0x1f;
|
||||
break;
|
||||
}
|
||||
|
||||
/* determine pixel multiple based on CRTC memory pitch constraints.
|
||||
* (Note: Don't mix this up with CRTC timing contraints! Those are
|
||||
* multiples of 8 for horizontal, 1 for vertical timing.)
|
||||
*
|
||||
* CRTC pitch constraints are the same for all Neomagic cards */
|
||||
switch (target->space)
|
||||
{
|
||||
case B_CMAP8: crtc_mask = 0x07; break;
|
||||
case B_RGB15: crtc_mask = 0x03; break;
|
||||
case B_RGB16: crtc_mask = 0x03; break;
|
||||
case B_RGB24: crtc_mask = 0x07; break;
|
||||
default:
|
||||
LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/* check if we can setup this mode with acceleration:
|
||||
* Max sizes need to adhere to both the acceleration engine _and_ the CRTC constraints! */
|
||||
si->acc_mode = true;
|
||||
/* check virtual_width */
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
case G100:
|
||||
/* acc constraint: */
|
||||
if (target->virtual_width > 2048) si->acc_mode = false;
|
||||
break;
|
||||
default:
|
||||
/* G200-G550 */
|
||||
/* acc constraint: */
|
||||
if (target->virtual_width > 4096) si->acc_mode = false;
|
||||
/* for 32bit mode a lower CRTC1 restriction applies! */
|
||||
// if ((target->space == B_RGB32_LITTLE) && (target->virtual_width > (4092 & ~acc_mask)))
|
||||
// si->acc_mode = false;
|
||||
break;
|
||||
}
|
||||
/* virtual_height */
|
||||
if (target->virtual_height > 2048) si->acc_mode = false;
|
||||
|
||||
//fixme: (temp)
|
||||
si->acc_mode = false;
|
||||
|
||||
/* now check virtual_size based on CRTC constraints,
|
||||
* making sure virtual_width stays within the 'mask' constraint: which is only
|
||||
* nessesary because of an extra constraint in MIL1/2 cards that exists here. */
|
||||
|
||||
//fixme: checkout cardspecs here!!
|
||||
|
||||
{
|
||||
/* virtual_width */
|
||||
//fixme for CRTC2 (identical on all G400+ cards):
|
||||
//16bit mode: max. virtual_width == 16352 (no extra mask needed);
|
||||
//32bit mode: max. virtual_width == 8176 (no extra mask needed);
|
||||
//other colordepths are unsupported on CRTC2.
|
||||
switch(target->space)
|
||||
{
|
||||
case B_CMAP8:
|
||||
if (target->virtual_width > (16368 & ~crtc_mask))
|
||||
target->virtual_width = (16368 & ~crtc_mask);
|
||||
break;
|
||||
case B_RGB15_LITTLE:
|
||||
case B_RGB16_LITTLE:
|
||||
if (target->virtual_width > (8184 & ~crtc_mask))
|
||||
target->virtual_width = (8184 & ~crtc_mask);
|
||||
break;
|
||||
case B_RGB24_LITTLE:
|
||||
if (target->virtual_width > (5456 & ~crtc_mask))
|
||||
target->virtual_width = (5456 & ~crtc_mask);
|
||||
break;
|
||||
}
|
||||
|
||||
/* virtual_height: The only constraint here is the cards memory size which is
|
||||
* checked later on in ProposeMode: virtual_height is adjusted then if needed.
|
||||
* 'Limiting here' to the variable size that's at least available (uint16). */
|
||||
if (target->virtual_height > 65535) target->virtual_height = 65535;
|
||||
}
|
||||
|
||||
/* OK, now we know that virtual_width is valid, and it's needing no slopspace if
|
||||
* it was confined above, so we can finally calculate safely if we need slopspace
|
||||
* for this mode... */
|
||||
if (si->acc_mode)
|
||||
video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask);
|
||||
else
|
||||
video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
|
||||
|
||||
LOG(2,("INIT: memory pitch will be set to %d pixels for colorspace 0x%08x\n",
|
||||
video_pitch, target->space));
|
||||
if (target->virtual_width != video_pitch)
|
||||
LOG(2,("INIT: effective mode slopspace is %d pixels\n",
|
||||
(video_pitch - target->virtual_width)));
|
||||
|
||||
/* now calculate bytes_per_row for this mode */
|
||||
*bytes_per_row = video_pitch * (depth >> 3);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
/* setup initialisation information for card */
|
||||
/* Authors:
|
||||
Rudolf Cornelissen 4/2003-5/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00002000
|
||||
|
||||
#include "nm_std.h"
|
||||
|
||||
void set_nm2070(void)
|
||||
{
|
||||
/* setup cardspecs */
|
||||
si->ps.f_ref = 14.31818;
|
||||
si->ps.max_system_vco = 65;
|
||||
si->ps.min_system_vco = 11;
|
||||
si->ps.max_pixel_vco = 65;
|
||||
si->ps.min_pixel_vco = 11;
|
||||
si->ps.max_dac1_clock = 65;
|
||||
si->ps.max_dac1_clock_8 = 65;
|
||||
si->ps.max_dac1_clock_16 = 65;
|
||||
/* 24bit color is not supported */
|
||||
si->ps.max_dac1_clock_24 = 0;
|
||||
si->ps.memory_size = 896;
|
||||
si->ps.curmem_size = 2048;
|
||||
si->ps.max_crtc_width = 1024;
|
||||
si->ps.max_crtc_height = 1024;
|
||||
si->ps.std_engine_clock = 0;
|
||||
}
|
||||
|
||||
void set_nm2090_nm2093(void)
|
||||
{
|
||||
/* setup cardspecs */
|
||||
si->ps.f_ref = 14.31818;
|
||||
si->ps.max_system_vco = 80;
|
||||
si->ps.min_system_vco = 11;
|
||||
si->ps.max_pixel_vco = 80;
|
||||
si->ps.min_pixel_vco = 11;
|
||||
si->ps.max_dac1_clock = 80;
|
||||
si->ps.max_dac1_clock_8 = 80;
|
||||
si->ps.max_dac1_clock_16 = 80;
|
||||
si->ps.max_dac1_clock_24 = 65;
|
||||
si->ps.memory_size = 1152;
|
||||
si->ps.curmem_size = 2048;
|
||||
si->ps.max_crtc_width = 1024;
|
||||
si->ps.max_crtc_height = 1024;
|
||||
si->ps.std_engine_clock = 0;
|
||||
}
|
||||
|
||||
void set_nm2097(void)
|
||||
{
|
||||
/* setup cardspecs */
|
||||
si->ps.f_ref = 14.31818;
|
||||
si->ps.max_system_vco = 80;
|
||||
si->ps.min_system_vco = 11;
|
||||
si->ps.max_pixel_vco = 80;
|
||||
si->ps.min_pixel_vco = 11;
|
||||
si->ps.max_dac1_clock = 80;
|
||||
si->ps.max_dac1_clock_8 = 80;
|
||||
si->ps.max_dac1_clock_16 = 80;
|
||||
si->ps.max_dac1_clock_24 = 65;
|
||||
si->ps.memory_size = 1152;
|
||||
si->ps.curmem_size = 1024;
|
||||
si->ps.max_crtc_width = 1024;
|
||||
si->ps.max_crtc_height = 1024;
|
||||
si->ps.std_engine_clock = 0;
|
||||
}
|
||||
|
||||
void set_nm2160(void)
|
||||
{
|
||||
/* setup cardspecs */
|
||||
si->ps.f_ref = 14.31818;
|
||||
si->ps.max_system_vco = 90;
|
||||
si->ps.min_system_vco = 11;
|
||||
si->ps.max_pixel_vco = 90;
|
||||
si->ps.min_pixel_vco = 11;
|
||||
si->ps.max_dac1_clock = 90;
|
||||
si->ps.max_dac1_clock_8 = 90;
|
||||
si->ps.max_dac1_clock_16 = 90;
|
||||
si->ps.max_dac1_clock_24 = 70;
|
||||
si->ps.memory_size = 2048;
|
||||
si->ps.curmem_size = 1024;
|
||||
si->ps.max_crtc_width = 1024;
|
||||
si->ps.max_crtc_height = 1024;
|
||||
si->ps.std_engine_clock = 0;
|
||||
}
|
||||
|
||||
void set_nm2200(void)
|
||||
{
|
||||
/* setup cardspecs */
|
||||
si->ps.f_ref = 14.31818;
|
||||
si->ps.max_system_vco = 110;
|
||||
si->ps.min_system_vco = 11;
|
||||
si->ps.max_pixel_vco = 110;
|
||||
si->ps.min_pixel_vco = 11;
|
||||
si->ps.max_dac1_clock = 110;
|
||||
si->ps.max_dac1_clock_8 = 110;
|
||||
si->ps.max_dac1_clock_16 = 110;
|
||||
si->ps.max_dac1_clock_24 = 90;
|
||||
si->ps.memory_size = 2560;
|
||||
si->ps.curmem_size = 1024;
|
||||
si->ps.max_crtc_width = 1280;
|
||||
si->ps.max_crtc_height = 1024;
|
||||
si->ps.std_engine_clock = 0;
|
||||
}
|
||||
|
||||
void set_nm2230(void)
|
||||
{
|
||||
/* setup cardspecs */
|
||||
si->ps.f_ref = 14.31818;
|
||||
si->ps.max_system_vco = 110;
|
||||
si->ps.min_system_vco = 11;
|
||||
si->ps.max_pixel_vco = 110;
|
||||
si->ps.min_pixel_vco = 11;
|
||||
si->ps.max_dac1_clock = 110;
|
||||
si->ps.max_dac1_clock_8 = 110;
|
||||
si->ps.max_dac1_clock_16 = 110;
|
||||
si->ps.max_dac1_clock_24 = 90;
|
||||
si->ps.memory_size = 3008;
|
||||
si->ps.curmem_size = 1024;
|
||||
si->ps.max_crtc_width = 1280;
|
||||
si->ps.max_crtc_height = 1024;
|
||||
si->ps.std_engine_clock = 0;
|
||||
}
|
||||
|
||||
void set_nm2360(void)
|
||||
{
|
||||
/* setup cardspecs */
|
||||
si->ps.f_ref = 14.31818;
|
||||
si->ps.max_system_vco = 110;
|
||||
si->ps.min_system_vco = 11;
|
||||
si->ps.max_pixel_vco = 110;
|
||||
si->ps.min_pixel_vco = 11;
|
||||
si->ps.max_dac1_clock = 110;
|
||||
si->ps.max_dac1_clock_8 = 110;
|
||||
si->ps.max_dac1_clock_16 = 110;
|
||||
si->ps.max_dac1_clock_24 = 90;
|
||||
si->ps.memory_size = 4096;
|
||||
si->ps.curmem_size = 1024;
|
||||
si->ps.max_crtc_width = 1280;
|
||||
si->ps.max_crtc_height = 1024;
|
||||
si->ps.std_engine_clock = 0;
|
||||
}
|
||||
|
||||
void set_nm2380(void)
|
||||
{
|
||||
/* setup cardspecs */
|
||||
si->ps.f_ref = 14.31818;
|
||||
si->ps.max_system_vco = 110;
|
||||
si->ps.min_system_vco = 11;
|
||||
si->ps.max_pixel_vco = 110;
|
||||
si->ps.min_pixel_vco = 11;
|
||||
si->ps.max_dac1_clock = 110;
|
||||
si->ps.max_dac1_clock_8 = 110;
|
||||
si->ps.max_dac1_clock_16 = 110;
|
||||
si->ps.max_dac1_clock_24 = 90;
|
||||
si->ps.memory_size = 6144;
|
||||
si->ps.curmem_size = 1024;
|
||||
si->ps.max_crtc_width = 1280;
|
||||
si->ps.max_crtc_height = 1024;
|
||||
si->ps.std_engine_clock = 0;
|
||||
}
|
||||
|
||||
void set_specs(void)
|
||||
{
|
||||
uint8 size_outputs, type;
|
||||
|
||||
LOG(8,("INFO: setting cardspecs\n"));
|
||||
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
case NM2070:
|
||||
set_nm2070();
|
||||
break;
|
||||
case NM2090:
|
||||
case NM2093:
|
||||
set_nm2090_nm2093();
|
||||
break;
|
||||
case NM2097:
|
||||
set_nm2097();
|
||||
break;
|
||||
case NM2160:
|
||||
set_nm2160();
|
||||
break;
|
||||
case NM2200:
|
||||
set_nm2200();
|
||||
break;
|
||||
case NM2230:
|
||||
set_nm2230();
|
||||
break;
|
||||
case NM2360:
|
||||
set_nm2360();
|
||||
break;
|
||||
case NM2380:
|
||||
set_nm2380();
|
||||
break;
|
||||
}
|
||||
|
||||
/* get output properties: */
|
||||
/* read panelsize and preselected outputs (via BIOS) */
|
||||
size_outputs = ISAGRPHR(PANELCTRL1);
|
||||
/* read the panel type */
|
||||
type = ISAGRPHR(PANELTYPE);
|
||||
|
||||
/* setup panelspecs */
|
||||
switch ((size_outputs & 0x18) >> 3)
|
||||
{
|
||||
case 0x00 :
|
||||
si->ps.panel_width = 640;
|
||||
si->ps.panel_height = 480;
|
||||
break;
|
||||
case 0x01 :
|
||||
si->ps.panel_width = 800;
|
||||
si->ps.panel_height = 600;
|
||||
break;
|
||||
case 0x02 :
|
||||
si->ps.panel_width = 1024;
|
||||
si->ps.panel_height = 768;
|
||||
break;
|
||||
case 0x03 :
|
||||
/* fixme: 1280x1024 panel support still needs to be done */
|
||||
si->ps.panel_width = 1280;
|
||||
si->ps.panel_height = 1024;
|
||||
}
|
||||
/* make note of paneltype */
|
||||
si->ps.panel_type = (type & 0x12);
|
||||
/* make note of preselected outputs (via BIOS) */
|
||||
si->ps.outputs = (size_outputs & 0x03);
|
||||
/* check for illegal setting */
|
||||
if (si->ps.outputs == 0)
|
||||
{
|
||||
LOG(4, ("INFO: illegal outputmode detected, defaulting to internal mode!\n"));
|
||||
si->ps.outputs = 2;
|
||||
//fixme: then also activate this mode in the card....
|
||||
}
|
||||
}
|
||||
|
||||
void dump_specs(void)
|
||||
{
|
||||
LOG(2,("INFO: cardspecs and settings follow:\n"));
|
||||
LOG(2,("f_ref: %fMhz\n", si->ps.f_ref));
|
||||
LOG(2,("max_system_vco: %dMhz\n", si->ps.max_system_vco));
|
||||
LOG(2,("min_system_vco: %dMhz\n", si->ps.min_system_vco));
|
||||
LOG(2,("max_pixel_vco: %dMhz\n", si->ps.max_pixel_vco));
|
||||
LOG(2,("min_pixel_vco: %dMhz\n", si->ps.min_pixel_vco));
|
||||
LOG(2,("std_engine_clock: %dMhz\n", si->ps.std_engine_clock));
|
||||
LOG(2,("max_dac1_clock: %dMhz\n", si->ps.max_dac1_clock));
|
||||
LOG(2,("max_dac1_clock_8: %dMhz\n", si->ps.max_dac1_clock_8));
|
||||
LOG(2,("max_dac1_clock_16: %dMhz\n", si->ps.max_dac1_clock_16));
|
||||
LOG(2,("max_dac1_clock_24: %dMhz\n", si->ps.max_dac1_clock_24));
|
||||
LOG(2,("card memory_size: %dKbytes\n", si->ps.memory_size));
|
||||
LOG(2,("card curmem_size: %dbytes\n", si->ps.curmem_size));
|
||||
LOG(2,("card max_crtc_width: %d\n", si->ps.max_crtc_width));
|
||||
LOG(2,("card max_crtc_height: %d\n", si->ps.max_crtc_height));
|
||||
switch (si->ps.panel_type)
|
||||
{
|
||||
case 0x00:
|
||||
LOG(2, ("B/W dualscan LCD panel detected\n"));
|
||||
break;
|
||||
case 0x02:
|
||||
LOG(2, ("color dualscan LCD panel detected\n"));
|
||||
break;
|
||||
case 0x10:
|
||||
LOG(2, ("B/W TFT LCD panel detected\n"));
|
||||
break;
|
||||
case 0x12:
|
||||
LOG(2, ("color TFT LCD panel detected\n"));
|
||||
break;
|
||||
}
|
||||
LOG(2,("internal panel width: %d\n", si->ps.panel_width));
|
||||
LOG(2,("internal panel height: %d\n", si->ps.panel_height));
|
||||
switch (si->ps.outputs)
|
||||
{
|
||||
case 0x01:
|
||||
LOG(2, ("external CRT only mode preset\n"));
|
||||
break;
|
||||
case 0x02:
|
||||
LOG(2, ("internal LCD only mode preset\n"));
|
||||
break;
|
||||
case 0x03:
|
||||
LOG(2, ("simultaneous LCD/CRT mode preset\n"));
|
||||
break;
|
||||
}
|
||||
LOG(2,("INFO: end cardspecs and settings.\n"));
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*general card functions*/
|
||||
status_t mn_general_powerup();
|
||||
status_t nm_set_cas_latency();
|
||||
status_t nm_general_output_select();
|
||||
uint8 nm_general_output_read();
|
||||
status_t mn_general_dac_select(int);
|
||||
status_t mn_general_wait_retrace();
|
||||
status_t mn_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row);
|
||||
//status_t mn_general_bios_to_powergraphics();
|
||||
|
||||
/* apsed: logging macros */
|
||||
#define MSG(args) do { /* if needed or si->settings with si NULL */ \
|
||||
nm_log args; \
|
||||
} while (0)
|
||||
#define LOG(level_bit, args) do { \
|
||||
uint32 mod = (si->settings.logmask & 0xfffffff0) & MODULE_BIT; \
|
||||
uint32 lev = (si->settings.logmask & ~0xfffffff0) & level_bit; \
|
||||
if (mod && lev) nm_log args; \
|
||||
} while (0)
|
||||
|
||||
/*support functions*/
|
||||
void delay(bigtime_t i);
|
||||
void nm_log(char *format, ...);
|
||||
|
||||
/*card info functions*/
|
||||
void set_specs(void);
|
||||
void dump_specs(void);
|
||||
|
||||
/*DAC functions*/
|
||||
status_t mn_dac_mode(int,float);
|
||||
status_t mn_dac_palette(uint8*,uint8*,uint8*, uint16);
|
||||
status_t mn_dac_pix_pll_find(display_mode target,float * result,uint8 *,uint8 *,uint8 *);
|
||||
status_t mn_dac_set_pix_pll(display_mode target);
|
||||
|
||||
/*CRTC1 functions*/
|
||||
status_t mn_crtc_validate_timing(
|
||||
uint16 *hd_e,uint16 *hs_s,uint16 *hs_e,uint16 *ht,
|
||||
uint16 *vd_e,uint16 *vs_s,uint16 *vs_e,uint16 *vt
|
||||
);
|
||||
status_t mn_crtc_set_timing(display_mode target, bool crt_only);
|
||||
status_t mn_crtc_depth(int mode);
|
||||
status_t mn_crtc_set_display_start(uint32 startadd,uint8 bpp);
|
||||
status_t mn_crtc_set_display_pitch();
|
||||
status_t mn_crtc_center(display_mode target);
|
||||
|
||||
status_t mn_crtc_dpms(bool, bool, bool);
|
||||
status_t mn_crtc_dpms_fetch(bool*, bool*, bool*);
|
||||
status_t mn_crtc_mem_priority(uint8);
|
||||
|
||||
status_t mn_crtc_cursor_init(); /*Yes, cursor follows CRTC1 - not the DAC!*/
|
||||
status_t mn_crtc_cursor_define(uint8*,uint8*);
|
||||
status_t mn_crtc_cursor_position(uint16 x ,uint16 y);
|
||||
status_t mn_crtc_cursor_show();
|
||||
status_t mn_crtc_cursor_hide();
|
||||
|
||||
/*acceleration functions*/
|
||||
status_t check_acc_capability(uint32 feature);
|
||||
status_t mn_acc_init();
|
||||
status_t mn_acc_rectangle(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint32 col);
|
||||
status_t mn_acc_rectangle_invert(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint32 col);
|
||||
status_t mn_acc_blit(uint16,uint16,uint16, uint16,uint16,uint16 );
|
||||
status_t mn_acc_transparent_blit(uint16,uint16,uint16, uint16,uint16,uint16, uint32);
|
||||
status_t mn_acc_video_blit(uint16 xs,uint16 ys,uint16 ws, uint16 hs,
|
||||
uint16 xd,uint16 yd,uint16 wd,uint16 hd);
|
||||
status_t mn_acc_wait_idle();
|
||||
|
||||
/*backend scaler functions*/
|
||||
status_t check_overlay_capability(uint32 feature);
|
||||
status_t mn_configure_bes
|
||||
(const overlay_buffer *ob, const overlay_window *ow,const overlay_view *ov, int offset);
|
||||
status_t mn_release_bes();
|
||||
|
||||
/*driver structures and enums*/
|
||||
enum{BPP8=0,BPP15=1,BPP16=2,BPP24=3};
|
||||
enum{DS_CRTC1DAC_CRTC2MAVEN, DS_CRTC1MAVEN_CRTC2DAC, DS_CRTC1CON1_CRTC2CON2, DS_CRTC1CON2_CRTC2CON1};
|
||||
@@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <math.h>
|
||||
#include <OS.h>
|
||||
#include "DriverInterface.h"
|
||||
#include "global.h"
|
||||
#include "nm_proto.h"
|
||||
#include "nm_macros.h"
|
||||
@@ -0,0 +1,30 @@
|
||||
/* Some commmon support functions */
|
||||
/* Mark Watson 2/2000 */
|
||||
|
||||
#define MODULE_BIT 0x00000800
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "nm_std.h"
|
||||
|
||||
/*delays in multiple of microseconds*/
|
||||
void delay(bigtime_t i)
|
||||
{
|
||||
bigtime_t start=system_time();
|
||||
while(system_time()-start<i);
|
||||
}
|
||||
|
||||
/*debug logging*/
|
||||
void nm_log(char *fmt, ...)
|
||||
{
|
||||
char buffer[1024];
|
||||
FILE *myhand;
|
||||
va_list args;
|
||||
|
||||
myhand=fopen("/boot/home/" DRIVER_PREFIX ".accelerant.log","a+");
|
||||
if (myhand == NULL) return;
|
||||
|
||||
va_start(args,fmt);
|
||||
vsprintf (buffer, fmt, args);
|
||||
fprintf(myhand, "%s", buffer);
|
||||
fclose(myhand);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
extern int fd;
|
||||
extern shared_info *si;
|
||||
extern area_id shared_info_area;
|
||||
extern area_id regs_area, regs2_area;
|
||||
extern vuint32 *regs, *regs2;
|
||||
extern display_mode *my_mode_list;
|
||||
extern area_id my_mode_list_area;
|
||||
extern int accelerantIsClone;
|
||||
|
||||
extern mn_get_set_pci mn_pci_access;
|
||||
extern mn_in_out_isa mn_isa_access;
|
||||
@@ -0,0 +1,34 @@
|
||||
/*This file can be used to define custom timing for your monitor
|
||||
* The format of each line is:
|
||||
* {
|
||||
* pixel clock frequency (kHz)
|
||||
* width
|
||||
* h-sync pulse start
|
||||
* h-sync pulse end
|
||||
* total pixels in line
|
||||
* height
|
||||
* v-sync pulse start
|
||||
* v-sync pulse end
|
||||
* total lines in frame
|
||||
* sync polarity (0 is -ve,B_POSITIVE_HYSNC,B_POSITIVE_VSYNC)
|
||||
* }
|
||||
*
|
||||
*To use this you must:
|
||||
* Uncomment VALID MODE REQUIRED
|
||||
* Fill in a number of modes that work with your display
|
||||
* Change VALID MODES from three to the no. you defined
|
||||
* run these commands:
|
||||
* touch ProposeDisplayMode.c
|
||||
* make install
|
||||
*/
|
||||
|
||||
//#define VALID_MODE_REQUIRED 1
|
||||
|
||||
#define VALID_MODES 3
|
||||
|
||||
/*note colour depth and mode flags are ignored*/
|
||||
static const display_timing valid_mode_list[] = {
|
||||
{31500,640,648,744,840,480,481,500,500,0},
|
||||
{49500,800,808,888,1056,600,601,620,625,B_POSITIVE_HSYNC|B_POSITIVE_VSYNC},
|
||||
{78750,1024,1032,1128,1312,768,769,788,800,B_POSITIVE_HSYNC|B_POSITIVE_VSYNC}
|
||||
};
|
||||
Reference in New Issue
Block a user