openBeOS_Matrox_V0.14_src
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5541 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
Other authors:
|
||||
Mark Watson;
|
||||
Apsed;
|
||||
Rudolf Cornelissen 10/2002.
|
||||
Rudolf Cornelissen 10/2002-4/2003.
|
||||
*/
|
||||
|
||||
#ifndef DRIVERINTERFACE_H
|
||||
@@ -87,6 +87,7 @@ typedef struct settings { // apsed, see comments in mga.settings
|
||||
uint32 memory;
|
||||
bool usebios;
|
||||
bool hardcursor;
|
||||
bool greensync;
|
||||
} settings;
|
||||
|
||||
/*shared info*/
|
||||
@@ -136,28 +137,33 @@ typedef struct {
|
||||
uint16 width; /* Width and height of the cursor shape (always 16!) */
|
||||
uint16 height;
|
||||
bool is_visible; /* Is the cursor currently displayed? */
|
||||
}cursor;
|
||||
} cursor;
|
||||
|
||||
/*colour lookup table*/
|
||||
uint8 color_data[3 * 256]; /* Colour lookup table - as used by DAC */
|
||||
|
||||
/*more display mode stuff*/
|
||||
display_mode dm; /* current display mode configuration */
|
||||
display_mode dm; /* current display mode configuration: head1 */
|
||||
display_mode dm2; /* current display mode configuration: head2 */
|
||||
bool switched_crtcs; /* dualhead stretch and switch mode info */
|
||||
bool acc_mode; /* signals (non)accelerated mode */
|
||||
bool interlaced_tv_mode;/* signals interlaced CRTC TV output mode */
|
||||
|
||||
/*frame buffer config - for BDirectScreen*/
|
||||
frame_buffer_config fbc; /* bytes_per_row and start of frame buffer */
|
||||
frame_buffer_config fbc; /* bytes_per_row and start of frame buffer: head1 */
|
||||
frame_buffer_config fbc2; /* bytes_per_row and start of frame buffer: head2 */
|
||||
|
||||
/*acceleration engine*/
|
||||
struct {
|
||||
uint32 count; /* last dwgsync slot used */
|
||||
uint32 last_idle; /* last dwgsync slot we *know* the engine was idle after */
|
||||
benaphore lock; /* for serializing access to the acceleration engine */
|
||||
} engine;
|
||||
} engine;
|
||||
|
||||
/* card info - information gathered from PINS (and other sources) */
|
||||
enum
|
||||
{ // card_type in order of date of MGA chip design
|
||||
MILL=0,
|
||||
MIL1 = 0,
|
||||
MYST,
|
||||
MIL2,
|
||||
G100,
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#define MGACFG_AGP_STS 0xf4 // >= MIL2
|
||||
#define MGACFG_AGP_CMD 0xf8 // >= MIL2
|
||||
|
||||
/*VGA registers - these are byte wide*/
|
||||
/* VGA registers - these are byte wide */
|
||||
#define MGAVGA_ATTR_I 0x1FC0 // apsed as SEQ
|
||||
#define MGAVGA_ATTR_D 0x1FC1 // apsed as SEQ
|
||||
#define MGAVGA_MISCW 0x1FC2
|
||||
@@ -45,7 +45,38 @@
|
||||
#define MGAVGA_CRTCEXT_I 0x1FDE
|
||||
#define MGAVGA_CRTCEXT_D 0x1FDF
|
||||
|
||||
/*DAC registers (>= g100) */
|
||||
/* TVP3026 'non-std' DAC registers (>= MIL1) */
|
||||
#define MGADAC_TVP_CUROVRWTADD 0x3c04
|
||||
#define MGADAC_TVP_CUROVRDATA 0x3c05
|
||||
#define MGADAC_TVP_CUROVRRDADD 0x3c07
|
||||
#define MGADAC_TVP_DIRCURCTRL 0x3c09
|
||||
#define MGADAC_TVP_CURRAMDATA 0x3c0b
|
||||
|
||||
/* TVP3026 'non'std' (D)AC (X) (I)ndexed registers (>= MIL1) */
|
||||
#define MGADXI_TVP_SILICONREV 0x01
|
||||
#define MGADXI_TVP_LATCHCTRL 0x0f
|
||||
#define MGADXI_TVP_TCOLCTRL 0x18
|
||||
#define MGADXI_TVP_CLOCKSEL 0x1a
|
||||
#define MGADXI_TVP_PALPAGE 0x1c
|
||||
#define MGADXI_TVP_PLLADDR 0x2c
|
||||
#define MGADXI_TVP_PIXPLLDATA 0x2d
|
||||
#define MGADXI_TVP_MEMPLLDATA 0x2e
|
||||
#define MGADXI_TVP_LOOPLLDATA 0x2f
|
||||
#define MGADXI_TVP_COLKEYOL 0x30
|
||||
#define MGADXI_TVP_COLKEYOH 0x31
|
||||
#define MGADXI_TVP_COLKEYRL 0x32
|
||||
#define MGADXI_TVP_COLKEYRH 0x33
|
||||
#define MGADXI_TVP_COLKEYGL 0x34
|
||||
#define MGADXI_TVP_COLKEYGH 0x35
|
||||
#define MGADXI_TVP_COLKEYBL 0x36
|
||||
#define MGADXI_TVP_COLKEYBH 0x37
|
||||
#define MGADXI_TVP_COLKEYCTRL 0x38
|
||||
#define MGADXI_TVP_MEMCLKCTRL 0x39
|
||||
#define MGADXI_TVP_TESTMODEDATA 0x3b
|
||||
#define MGADXI_TVP_ID 0x3f
|
||||
#define MGADXI_TVP_RESET 0xff
|
||||
|
||||
/* DAC registers (>= G100) */
|
||||
#define MGADAC_PALWTADD 0x3C00
|
||||
#define MGADAC_PALDATA 0x3C01
|
||||
#define MGADAC_PIXRDMSK 0x3C02
|
||||
@@ -56,7 +87,7 @@
|
||||
#define MGADAC_CURSPOSYL 0x3C0E
|
||||
#define MGADAC_CURSPOSYH 0x3C0F
|
||||
|
||||
/*(D)AC (X) (I)ndexed registers (>= g100) */
|
||||
/* (D)AC (X) (I)ndexed registers (>= G100) */
|
||||
#define MGADXI_CURADDL 0x04
|
||||
#define MGADXI_CURADDH 0x05
|
||||
#define MGADXI_CURCTRL 0x06
|
||||
@@ -101,7 +132,7 @@
|
||||
#define MGADXI_PIXPLLSTAT 0x4F
|
||||
#define MGADXI_CURCOLEXT 0x60 /*sequential from CURCOL3->15, RGB*/
|
||||
|
||||
/*(D)AC (X) (I)ndexed registers (>= g200) */
|
||||
/* (D)AC (X) (I)ndexed registers (>= G200) */
|
||||
#define MGADXI_KEYOPMODE 0x51
|
||||
#define MGADXI_COLMSK0RED 0x52
|
||||
#define MGADXI_COLMSK0GREEN 0x53
|
||||
@@ -110,7 +141,7 @@
|
||||
#define MGADXI_COLKEY0GREEN 0x56
|
||||
#define MGADXI_COLKEY0BLUE 0x57
|
||||
|
||||
/*(D)AC (X) (I)ndexed registers (>= g450?) */
|
||||
/* (D)AC (X) (I)ndexed registers (>= G450) */
|
||||
#define MGADXI_TVO_IDX 0x87
|
||||
#define MGADXI_TVO_DATA 0x88
|
||||
#define MGADXI_OUTPUTCONN 0x8A
|
||||
@@ -122,11 +153,10 @@
|
||||
#define MGADXI_PWRCTRL 0xA0
|
||||
#define MGADXI_PANMODE 0xA2
|
||||
|
||||
/*MGA 1st CRTC registers */
|
||||
/* MGA 1st CRTC registers */
|
||||
#define MGACR1_VCOUNT 0x1E20
|
||||
//end rudolf.
|
||||
|
||||
/*MGA 2nd CRTC registers >= ?? TODO */
|
||||
/* MGA 2nd CRTC registers (>= G400) */
|
||||
#define MGACR2_CTL 0x3C10
|
||||
#define MGACR2_HPARAM 0x3C14
|
||||
#define MGACR2_HSYNC 0x3C18
|
||||
@@ -134,12 +164,13 @@
|
||||
#define MGACR2_VSYNC 0x3C20
|
||||
#define MGACR2_PRELOAD 0x3C24
|
||||
#define MGACR2_STARTADD0 0x3C28
|
||||
#define MGACR2_STARTADD1 0x3C2C
|
||||
#define MGACR2_OFFSET 0x3C40
|
||||
#define MGACR2_MISC 0x3C44
|
||||
#define MGACR2_VCOUNT 0x3C48
|
||||
#define MGACR2_DATACTL 0x3C4C
|
||||
|
||||
/*MGA ACCeleration registers*/
|
||||
/* MGA ACCeleration registers */
|
||||
#define MGAACC_DWGCTL 0x1C00
|
||||
#define MGAACC_MACCESS 0x1C04
|
||||
#define MGAACC_MCTLWTST 0x1C08
|
||||
@@ -183,7 +214,7 @@
|
||||
#define MGAACC_SRCORG 0x2CB4 // >= G200
|
||||
#define MGAACC_DSTORG 0x2CB8 // >= G200
|
||||
|
||||
/*MGA BES (Back End Scaler) registers >= TODO */
|
||||
/*MGA BES (Back End Scaler) registers (>= G200) */
|
||||
#define MGABES_A1ORG 0x3D00
|
||||
#define MGABES_A2ORG 0x3D04
|
||||
#define MGABES_B1ORG 0x3D08
|
||||
@@ -213,15 +244,34 @@
|
||||
#define MGABES_GLOBCTL 0x3DC0
|
||||
#define MGABES_STATUS 0x3DC4
|
||||
|
||||
/*MAVEN registers >= TODO */
|
||||
/*MAVEN registers (<= G400) */
|
||||
#define MGAMAV_PGM 0x3E
|
||||
#define MGAMAV_PIXPLLM 0x80
|
||||
#define MGAMAV_PIXPLLN 0x81
|
||||
#define MGAMAV_PIXPLLP 0x82
|
||||
#define MGAMAV_GAMMA1 0x83
|
||||
#define MGAMAV_GAMMA2 0x84
|
||||
#define MGAMAV_GAMMA3 0x85
|
||||
#define MGAMAV_GAMMA4 0x86
|
||||
#define MGAMAV_GAMMA5 0x87
|
||||
#define MGAMAV_GAMMA6 0x88
|
||||
#define MGAMAV_GAMMA7 0x89
|
||||
#define MGAMAV_GAMMA8 0x8A
|
||||
#define MGAMAV_GAMMA9 0x8B
|
||||
#define MGAMAV_MONSET 0x8C
|
||||
#define MGAMAV_TEST 0x8D
|
||||
#define MGAMAV_WREG_0X8E_L 0x8E
|
||||
#define MGAMAV_WREG_0X8E_H 0x8F
|
||||
#define MGAMAV_HSCALETV 0x90
|
||||
#define MGAMAV_TSCALETVL 0x91
|
||||
#define MGAMAV_TSCALETVH 0x92
|
||||
#define MGAMAV_FFILTER 0x93
|
||||
#define MGAMAV_MONEN 0x94
|
||||
#define MGAMAV_RESYNC 0x95
|
||||
#define MGAMAV_LASTLINEL 0x96
|
||||
#define MGAMAV_LASTLINEH 0x97
|
||||
#define MGAMAV_WREG_0X98_L 0x98
|
||||
#define MGAMAV_WREG_0X98_H 0x99
|
||||
#define MGAMAV_HSYNCLENL 0x9A
|
||||
#define MGAMAV_HSYNCLENH 0x9B
|
||||
#define MGAMAV_HSYNCSTRL 0x9C
|
||||
@@ -242,56 +292,60 @@
|
||||
#define MGAMAV_HVIDRSTH 0xAB
|
||||
#define MGAMAV_VVIDRSTL 0xAC
|
||||
#define MGAMAV_VVIDRSTH 0xAD
|
||||
#define MGAMAV_VSOMETHINGL 0xAE
|
||||
#define MGAMAV_VSOMETHINGH 0xAF
|
||||
#define MGAMAV_OUTMODE 0xB0
|
||||
#define MGAMAV_LOCK 0xB3
|
||||
#define MGAMAV_LUMA 0xB9
|
||||
#define MGAMAV_VDISPLAYTV 0xBE
|
||||
#define MGAMAV_STABLE 0xBF
|
||||
#define MGAMAV_HDISPLAYTV 0xC2
|
||||
#define MGAMAV_BREG_0XC6 0xC6
|
||||
|
||||
/*Macros for convenient accesses to the G400*/
|
||||
/* Macros for convenient accesses to the MGA chips */
|
||||
|
||||
#define MGA_REG8(r_) ((vuint8 *)regs)[(r_)]
|
||||
#define MGA_REG32(r_) ((vuint32 *)regs)[(r_) >> 2]
|
||||
|
||||
/*read and write to PCI config space*/
|
||||
/* read and write to PCI config space */
|
||||
#define CFGR(A) (gx00_pci_access.offset=MGACFG_##A, ioctl(fd,GX00_GET_PCI, &gx00_pci_access,sizeof(gx00_pci_access)), gx00_pci_access.value)
|
||||
#define CFGW(A,B) (gx00_pci_access.offset=MGACFG_##A, gx00_pci_access.value = B, ioctl(fd,GX00_SET_PCI,&gx00_pci_access,sizeof(gx00_pci_access)))
|
||||
|
||||
/*read and write from the dac registers*/
|
||||
/* read and write from the dac registers */
|
||||
#define DACR(A) (MGA_REG8(MGADAC_##A))
|
||||
#define DACW(A,B) (MGA_REG8(MGADAC_##A)=B)
|
||||
|
||||
/*read and write from the dac index register*/
|
||||
/* read and write from the dac index register */
|
||||
#define DXIR(A) (DACW(PALWTADD,MGADXI_##A),DACR(X_DATAREG))
|
||||
#define DXIW(A,B) (DACW(PALWTADD,MGADXI_##A),DACW(X_DATAREG,B))
|
||||
|
||||
/*read and write from the vga registers*/
|
||||
/* read and write from the vga registers */
|
||||
#define VGAR(A) (MGA_REG8(MGAVGA_##A))
|
||||
#define VGAW(A,B) (MGA_REG8(MGAVGA_##A)=B)
|
||||
|
||||
/*read and write from the indexed vga registers*/
|
||||
/* read and write from the indexed vga registers */
|
||||
#define VGAR_I(A,B) (VGAW(A##_I,B),VGAR(A##_D))
|
||||
#define VGAW_I(A,B,C) (VGAW(A##_I,B),VGAW(A##_D,C))
|
||||
|
||||
/*read and write from the powergraphics registers*/
|
||||
/* read and write from the powergraphics registers */
|
||||
#define ACCR(A) (MGA_REG32(MGAACC_##A))
|
||||
#define ACCW(A,B) (MGA_REG32(MGAACC_##A)=B)
|
||||
#define ACCGO(A,B) (MGA_REG32(MGAACC_##A + 0x0100)=B)
|
||||
|
||||
/*read and write from the backend scaler registers*/
|
||||
/* read and write from the backend scaler registers */
|
||||
#define BESR(A) (MGA_REG32(MGABES_##A))
|
||||
#define BESW(A,B) (MGA_REG32(MGABES_##A)=B)
|
||||
|
||||
/*read and write from first CRTC*/
|
||||
/* read and write from first CRTC */
|
||||
#define CR1R(A) (MGA_REG32(MGACR1_##A))
|
||||
#define CR1W(A,B) (MGA_REG32(MGACR1_##A)=B)
|
||||
|
||||
/*read and write from second CRTC*/
|
||||
/* read and write from second CRTC */
|
||||
#define CR2R(A) (MGA_REG32(MGACR2_##A))
|
||||
#define CR2W(A,B) (MGA_REG32(MGACR2_##A)=B)
|
||||
|
||||
/*read and write from maven*/
|
||||
/* read and write from maven (<= G400) */
|
||||
#define MAVR(A) (i2c_maven_read (MGAMAV_##A ))
|
||||
#define MAVW(A,B) (i2c_maven_write(MGAMAV_##A ,B))
|
||||
#define MAVRW(A) (i2c_maven_read (MGAMAV_##A )|(i2c_maven_read(MGAMAV_##A +1)<<8))
|
||||
#define MAVWW(A,B) (i2c_maven_write(MGAMAV_##A ,B &0xFF),i2c_maven_write(MGAMAV_##A +1,B >>8))
|
||||
#define MAVWWP(A,B) (i2c_maven_write(A ,B &0xFF),i2c_maven_write(A +1,B >>8))
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
|
||||
Other authors:
|
||||
Mark Watson,
|
||||
Apsed.
|
||||
Apsed,
|
||||
Rudolf Cornelissen 2/2003.
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x40000000
|
||||
@@ -33,19 +34,27 @@ void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count) {
|
||||
}
|
||||
}
|
||||
|
||||
//Not possible with G400 AFAIK (if anyone knows otherwise then please contact me)
|
||||
//void SCREEN_TO_SCREEN_SCALED_FILTERED_BLIT(engine_token *et, scaled_blit_params *list, uint32 count) {
|
||||
//typedef struct {
|
||||
// uint16 src_left; /* guaranteed constrained to virtual width and height */
|
||||
// uint16 src_top;
|
||||
// uint16 src_width; /* 0 to N, where zero means one pixel, one means two pixels, etc. */
|
||||
// uint16 src_height; /* 0 to M, where zero means one line, one means two lines, etc. */
|
||||
// uint16 dest_left;
|
||||
// uint16 dest_top;
|
||||
// uint16 dest_width; /* 0 to N, where zero means one pixel, one means two pixels, etc. */
|
||||
// uint16 dest_height; /* 0 to M, where zero means one line, one means two lines, etc. */
|
||||
//} scaled_blit_params;
|
||||
//}
|
||||
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--)
|
||||
{
|
||||
gx00_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;
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
|
||||
Other authors:
|
||||
Mark Watson
|
||||
Mark Watson,
|
||||
Rudolf Cornelissen 4/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x20000000
|
||||
|
||||
/*DUALHEAD notes -
|
||||
No hardware cursor possible:(
|
||||
No hardware cursor possible on the secondary head :(
|
||||
Reasons:
|
||||
CRTC1 has a cursor, can be displayed on DAC or MAVEN
|
||||
CRTC2 has no cursor
|
||||
@@ -54,48 +55,96 @@ void MOVE_CURSOR(uint16 x, uint16 y)
|
||||
uint16 h_adjust;
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
si->cursor.x = x;
|
||||
si->cursor.y = y;
|
||||
|
||||
/*set up minimum amount to scroll*/
|
||||
switch(si->dm.space)
|
||||
if (si->dm.flags & DUALHEAD_BITS)
|
||||
{
|
||||
case B_CMAP8:
|
||||
h_adjust=7;
|
||||
break;
|
||||
case B_RGB15_LITTLE:case B_RGB16_LITTLE:
|
||||
h_adjust=3;
|
||||
break;
|
||||
case B_RGB32_LITTLE:
|
||||
h_adjust=1;
|
||||
break;
|
||||
default:
|
||||
h_adjust=7;
|
||||
switch(si->dm.space)
|
||||
{
|
||||
case B_RGB16_LITTLE:
|
||||
h_adjust = 0x1f;
|
||||
break;
|
||||
case B_RGB32_LITTLE:
|
||||
h_adjust = 0x0f;
|
||||
break;
|
||||
default:
|
||||
h_adjust = 0x1f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(si->dm.space)
|
||||
{
|
||||
case B_CMAP8:
|
||||
h_adjust = 0x07;
|
||||
break;
|
||||
case B_RGB15_LITTLE:case B_RGB16_LITTLE:
|
||||
h_adjust = 0x03;
|
||||
break;
|
||||
case B_RGB32_LITTLE:
|
||||
h_adjust = 0x01;
|
||||
break;
|
||||
default:
|
||||
h_adjust = 0x07;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* adjust h/v_display_start to move cursor onto screen */
|
||||
if (x >= (si->dm.timing.h_display + hds))
|
||||
hds = ((x - si->dm.timing.h_display) + 1 + h_adjust) & ~h_adjust;
|
||||
else if (x < hds)
|
||||
hds = x & ~h_adjust;
|
||||
switch (si->dm.flags & DUALHEAD_BITS)
|
||||
{
|
||||
case DUALHEAD_ON:
|
||||
case DUALHEAD_SWITCH:
|
||||
if (x >= ((si->dm.timing.h_display * 2) + hds))
|
||||
{
|
||||
hds = ((x - (si->dm.timing.h_display * 2)) + 1 + h_adjust) & ~h_adjust;
|
||||
/* make sure we stay within the display! */
|
||||
if ((hds + (si->dm.timing.h_display * 2)) > si->dm.virtual_width)
|
||||
hds -= (h_adjust + 1);
|
||||
}
|
||||
else if (x < hds)
|
||||
hds = x & ~h_adjust;
|
||||
break;
|
||||
default:
|
||||
if (x >= (si->dm.timing.h_display + hds))
|
||||
{
|
||||
hds = ((x - si->dm.timing.h_display) + 1 + h_adjust) & ~h_adjust;
|
||||
/* make sure we stay within the display! */
|
||||
if ((hds + si->dm.timing.h_display) > si->dm.virtual_width)
|
||||
hds -= (h_adjust + 1);
|
||||
}
|
||||
else if (x < hds)
|
||||
hds = x & ~h_adjust;
|
||||
break;
|
||||
}
|
||||
|
||||
if (y >= (si->dm.timing.v_display + vds))
|
||||
vds = y - si->dm.timing.v_display + 1;
|
||||
else if (y < vds)
|
||||
vds = y;
|
||||
|
||||
/* reposition the desktop on the display if required */
|
||||
/* 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 */
|
||||
x -= hds + si->cursor.hot_x;
|
||||
y -= vds + si->cursor.hot_y;
|
||||
|
||||
/* account for switched CRTC's */
|
||||
if (si->switched_crtcs) x -= si->dm.timing.h_display;
|
||||
|
||||
/* position the cursor on the display */
|
||||
gx00_crtc_cursor_position(x,y);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Other authors:
|
||||
Mark Watson,
|
||||
Rudolf Cornelissen 10/2002
|
||||
Rudolf Cornelissen 10/2002-4/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x08000000
|
||||
@@ -12,7 +12,6 @@
|
||||
#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
|
||||
@@ -20,26 +19,30 @@ 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.
|
||||
|
||||
*/
|
||||
|
||||
void * get_accelerant_hook(uint32 feature, void *data) {
|
||||
switch (feature) {
|
||||
/*
|
||||
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; // apsed
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
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);
|
||||
@@ -67,7 +70,7 @@ initialization process.
|
||||
HOOK(SET_DPMS_MODE);
|
||||
|
||||
/* cursor managment */
|
||||
HRDC(SET_CURSOR_SHAPE); // apsed
|
||||
HRDC(SET_CURSOR_SHAPE);
|
||||
HRDC(MOVE_CURSOR);
|
||||
HRDC(SHOW_CURSOR);
|
||||
|
||||
@@ -79,6 +82,13 @@ initialization process.
|
||||
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);
|
||||
@@ -90,31 +100,36 @@ initialization process.
|
||||
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.
|
||||
*/
|
||||
/* 2D acceleration */
|
||||
HOOK(SCREEN_TO_SCREEN_BLIT);
|
||||
HOOK(FILL_RECTANGLE);
|
||||
HOOK(INVERT_RECTANGLE);
|
||||
HOOK(FILL_SPAN);
|
||||
HOOK(SCREEN_TO_SCREEN_TRANSPARENT_BLIT);//remove for pre R5
|
||||
/*
|
||||
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.
|
||||
|
||||
/*HOOK(SCREEN_TO_SCREEN_SCALED_FILTERED_BLIT;
|
||||
Does the G400 support this? I can only think of using texture mapped rectangles, but these seem to have too many restrictions to do this:( e.g. I would need to blit offscreen, into texture format...
|
||||
*/
|
||||
#undef HOOK
|
||||
#undef ZERO
|
||||
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 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)
|
||||
{
|
||||
@@ -155,21 +170,71 @@ status_t check_overlay_capability(uint32 feature)
|
||||
break;
|
||||
}
|
||||
|
||||
switch(si->ps.card_type)
|
||||
if (si->ps.card_type >= G200)
|
||||
{
|
||||
case G200:
|
||||
case G400:
|
||||
case G400MAX:
|
||||
case G450: /* is also G550 in accelerant for now */
|
||||
case G550: /* not used in accelerant yet */
|
||||
/* 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:
|
||||
/* do not export video overlay functions */
|
||||
LOG(4, ("Overlay: Not exporting hook %s.\n", msg));
|
||||
return B_ERROR;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Other authors:
|
||||
Mark Watson,
|
||||
Rudolf Cornelissen 10/2002.
|
||||
Rudolf Cornelissen 10/2002-3/2003.
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00800000
|
||||
@@ -40,7 +40,8 @@ static status_t init_common(int the_fd) {
|
||||
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));
|
||||
LOG(4,("init_common: logmask 0x%08x, memory %dMB, hardcursor %d, usebios %d, greensync %d\n",
|
||||
si->settings.logmask, si->settings.memory, si->settings.hardcursor, si->settings.usebios, si->settings.greensync));
|
||||
|
||||
/*Check for R4.5.0 and if it is running, use work around*/
|
||||
{
|
||||
@@ -151,8 +152,11 @@ status_t INIT_ACCELERANT(int the_fd) {
|
||||
info in a frame_buffer_config structure to make it convienient to return
|
||||
to the app_server later.
|
||||
*/
|
||||
//don't reserve memory at the start of the fb, because this doesn't work on the G100 (no SRCORG/DSTORG)
|
||||
pointer_reservation = si->settings.hardcursor? 1024: 0; // apsed TODO with G100, see before
|
||||
pointer_reservation = 0;
|
||||
/* MIL 1/2 cards have a seperate buffer for the cursorbitmap inside the DAC */
|
||||
if ((si->ps.card_type >= G100) && si->settings.hardcursor)
|
||||
pointer_reservation = 1024;
|
||||
|
||||
si->fbc.frame_buffer = (void *)((char *)si->framebuffer+pointer_reservation);
|
||||
si->fbc.frame_buffer_dma = (void *)((char *)si->framebuffer_pci+pointer_reservation);
|
||||
|
||||
@@ -260,6 +264,8 @@ status_t CLONE_ACCELERANT(void *data) {
|
||||
if (result < B_OK) goto error2;
|
||||
|
||||
/* all done */
|
||||
LOG(4,("CLONE_ACCELERANT: cloning was succesfull.\n"));
|
||||
|
||||
result = B_OK;
|
||||
goto error0;
|
||||
|
||||
@@ -273,7 +279,13 @@ error0:
|
||||
return result;
|
||||
}
|
||||
|
||||
void UNINIT_ACCELERANT(void) {
|
||||
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);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Written by Rudolf Cornelissen 05/10-2002 */
|
||||
/* 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'
|
||||
@@ -106,6 +106,9 @@ const overlay_buffer *ALLOCATE_OVERLAY_BUFFER(color_space cs, uint16 width, uint
|
||||
/* 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;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Other authors for MGA driver:
|
||||
Mark Watson,
|
||||
Rudolf Cornelissen 9/2002
|
||||
Rudolf Cornelissen 9/2002-4/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00400000
|
||||
@@ -12,7 +12,8 @@
|
||||
#include "acc_std.h"
|
||||
|
||||
#define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC)
|
||||
#define MODE_FLAGS (B_SCROLL | B_8_BIT_DAC | B_HARDWARE_CURSOR | B_PARALLEL_ACCESS)
|
||||
/* 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*/
|
||||
@@ -36,8 +37,8 @@ static const display_mode mode_list[] = {
|
||||
{ { 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) */
|
||||
{ { 108000, 1152, 1216, 1344, 1550, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */
|
||||
{ { 120000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(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) */
|
||||
{ { 120000, 1152, 1216, 1344, 1568, 864, 865, 868, 911, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(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) */
|
||||
{ { 135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1280X1024X8.Z1) */
|
||||
@@ -50,56 +51,32 @@ static const display_mode mode_list[] = {
|
||||
{ { 229500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS} /* Vesa_Monitor_@85Hz_(1600X1200X8.Z1) */
|
||||
};
|
||||
|
||||
// apsed, adjust virtual width for CRTC offset constraints
|
||||
// PB with MIl2 800*600 with bpp < 32
|
||||
static status_t adjust_width (display_mode *target, bool want_same_width)
|
||||
{
|
||||
uint32 video_pitch = target->virtual_width;
|
||||
uint32 multiple;
|
||||
|
||||
if (si->ps.card_type < G100) switch (target->space & 0x0fff) { // MIL2
|
||||
case B_CMAP8: multiple = 128; break;
|
||||
case B_RGB15: multiple = 64; break;
|
||||
case B_RGB16: multiple = 64; break;
|
||||
case B_RGB24: multiple = 128; break;
|
||||
case B_RGB32: multiple = 32; break;
|
||||
default:
|
||||
LOG(8,("PROPOSEMODE: unknown color space: 0x%08x\n", target->space));
|
||||
return B_ERROR;
|
||||
} else switch (target->space & 0x0fff) { // G100, G200, G400
|
||||
case B_CMAP8: multiple = 16; break;
|
||||
case B_RGB15: multiple = 8; break;
|
||||
case B_RGB16: multiple = 8; break;
|
||||
case B_RGB24: multiple = 16; break;
|
||||
case B_RGB32: multiple = 4; break;
|
||||
default:
|
||||
LOG(8,("PROPOSEMODE: unknown color space: 0x%08x\n", target->space));
|
||||
return B_ERROR;
|
||||
}
|
||||
video_pitch = (video_pitch+multiple-1)/multiple;
|
||||
video_pitch *= multiple;
|
||||
if (target->virtual_width != video_pitch) {
|
||||
LOG(2,("PROPOSEMODE: color space 0x%08x, virtual_width %d adjusted to %d \n",
|
||||
target->space, target->virtual_width, video_pitch));
|
||||
target->virtual_width = video_pitch;
|
||||
if (want_same_width) target->timing.h_display = video_pitch;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*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
|
||||
/*
|
||||
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;
|
||||
status_t status = B_OK;
|
||||
float pix_clock_found;
|
||||
uint8 m,n,p;
|
||||
status_t result = B_OK;
|
||||
uint32 row_bytes, limit_clock, max_vclk;
|
||||
status_t result;
|
||||
uint32 max_vclk, row_bytes, pointer_reservation;
|
||||
double target_refresh = ((double)target->timing.pixel_clock * 1000.0) /
|
||||
(
|
||||
(double)target->timing.h_total *
|
||||
@@ -109,9 +86,8 @@ status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, con
|
||||
want_same_width = target->timing.h_display == target->virtual_width,
|
||||
want_same_height = target->timing.v_display == target->virtual_height;
|
||||
|
||||
// // apsed, adjust virtual width for CRTC offset constraints
|
||||
// status = adjust_width (target, want_same_width);
|
||||
// if (status != B_OK) return status;
|
||||
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)
|
||||
@@ -132,6 +108,8 @@ status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, con
|
||||
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++)
|
||||
@@ -155,16 +133,14 @@ status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, con
|
||||
|
||||
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
|
||||
);
|
||||
((double)target->timing.h_total * (double)target->timing.v_total);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -175,113 +151,149 @@ status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, con
|
||||
&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) return result;
|
||||
|
||||
/*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)
|
||||
) result = B_BAD_VALUE;
|
||||
|
||||
/*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) || // apsed
|
||||
(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)
|
||||
) result = B_BAD_VALUE;
|
||||
|
||||
//rudolf
|
||||
/* 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 */
|
||||
if (si->ps.card_type >= G100)
|
||||
if (result == B_ERROR)
|
||||
{
|
||||
/* calculate settings, but do not actually test anything (that costs too much time!) */
|
||||
status = gx00_dac_pix_pll_find(*target,&pix_clock_found,&m,&n,&p,0);
|
||||
LOG(4, ("PROPOSEMODE: could not validate timing, aborted.\n"));
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
//fixme: implement pixelclock limits check (and modify if needed) for target mode inside mil2_find routine!
|
||||
//temp until then:
|
||||
limit_clock = si->ps.max_dac1_clock * 1000;
|
||||
if (target->timing.pixel_clock > limit_clock) target->timing.pixel_clock = limit_clock;
|
||||
|
||||
status = mil2_dac_pix_pll_find((float)target->timing.pixel_clock/1000.0,&pix_clock_found,&m,&n,&p);
|
||||
}
|
||||
target->timing.pixel_clock = pix_clock_found*1000;
|
||||
//end rudolf
|
||||
|
||||
/* note if we fell outside the limits */
|
||||
if (
|
||||
(target->timing.pixel_clock < low->timing.pixel_clock) ||
|
||||
(target->timing.pixel_clock > high->timing.pixel_clock)
|
||||
) result = B_BAD_VALUE;
|
||||
|
||||
/* 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;
|
||||
if (target->virtual_width > 4096)
|
||||
target->virtual_width = 4096;
|
||||
if (target->virtual_height > 2048)
|
||||
target->virtual_height = 2048;
|
||||
|
||||
/* adjust virtual width for engine limitations - must be multiple of 8 */
|
||||
target->virtual_width = (target->virtual_width + 7) & ~7;
|
||||
if (
|
||||
(target->virtual_width < low->virtual_width) ||
|
||||
(target->virtual_width > high->virtual_width)
|
||||
) result = B_BAD_VALUE;
|
||||
|
||||
// apsed, adjust virtual width for CRTC offset constraints
|
||||
status = adjust_width (target, want_same_width);
|
||||
if (status != B_OK) return status;
|
||||
|
||||
/* calculate rowbytes after we've nailed the virtual width */
|
||||
switch (target->space & 0x0fff) {
|
||||
case B_CMAP8:
|
||||
row_bytes = 1;
|
||||
break;
|
||||
case B_RGB15:
|
||||
case B_RGB16:
|
||||
row_bytes = 2;
|
||||
break;
|
||||
case B_RGB32:
|
||||
row_bytes = 4;
|
||||
break;
|
||||
default:
|
||||
/* no amount of adjusting will fix not being able to support the pixel format */
|
||||
LOG(8,("PROPOSEMODE: unknown target space: 0x%08x\n", target->space));
|
||||
return B_ERROR;
|
||||
/* nail virtual size and 'subsequently' calculate rowbytes */
|
||||
result = gx00_general_validate_pic_size (target, &row_bytes);
|
||||
if (result == B_ERROR)
|
||||
{
|
||||
LOG(4, ("PROPOSEMODE: could not validate virtual picture size, aborted.\n"));
|
||||
return result;
|
||||
}
|
||||
row_bytes *= target->virtual_width;
|
||||
|
||||
/*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 */
|
||||
/* calculate settings, but do not actually test anything (that costs too much time!) */
|
||||
result = gx00_dac_pix_pll_find(*target,&pix_clock_found,&m,&n,&p,0);
|
||||
/* 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;
|
||||
/* MIL 1/2 cards have a seperate buffer for the cursorbitmap inside the DAC */
|
||||
if ((si->ps.card_type >= G100) && si->settings.hardcursor) pointer_reservation = 1024;
|
||||
/* memory requirement for frame buffer */
|
||||
if ((row_bytes * target->virtual_height) > (si->ps.memory_size * 1024 * 1024))
|
||||
target->virtual_height = (si->ps.memory_size * 1024 * 1024) / row_bytes;
|
||||
if ((row_bytes * target->virtual_height) >
|
||||
((si->ps.memory_size * 1024 * 1024) - pointer_reservation))
|
||||
{
|
||||
target->virtual_height =
|
||||
((si->ps.memory_size * 1024 * 1024) - pointer_reservation) / row_bytes;
|
||||
}
|
||||
if (target->virtual_height < target->timing.v_display)
|
||||
{
|
||||
LOG(8,("PROPOSEMODE: virtual_height required %d < %d\n", target->virtual_height, target->timing.v_display));
|
||||
LOG(4,("PROPOSEMODE: not enough memory for current mode, aborted.\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
else if (
|
||||
(target->virtual_height < low->virtual_height) ||
|
||||
(target->virtual_height > high->virtual_height)
|
||||
) result = B_BAD_VALUE;
|
||||
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). */
|
||||
target->flags &=
|
||||
~(DUALHEAD_CAPABLE | TV_CAPABLE | B_SUPPORTS_OVERLAYS | B_HARDWARE_CURSOR | 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. */
|
||||
//fixme: secondary head does not support DPMS...
|
||||
target->flags |= (B_PARALLEL_ACCESS | B_8_BIT_DAC | B_DPMS | B_SCROLL);
|
||||
|
||||
/* determine the 'would be' max. pixelclock for the second DAC for the current videomode if dualhead were activated */
|
||||
switch (target->space)
|
||||
@@ -305,43 +317,68 @@ status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, con
|
||||
break;
|
||||
}
|
||||
|
||||
/*clear DUALHEAD_CAPABLE if any problems*/
|
||||
if
|
||||
(
|
||||
((target->flags)& DUALHEAD_CAPABLE ) &&
|
||||
(
|
||||
(!si->ps.secondary_head) ||
|
||||
((1024 + (row_bytes * (target->virtual_height+1) * 2)) > (si->ps.memory_size * 1024 * 1024)) || /*note: extra line for maven vblank!*/
|
||||
(target->space == B_CMAP8) ||
|
||||
(target->space == B_RGB15_LITTLE) ||
|
||||
(target->timing.pixel_clock > (max_vclk * 1000))
|
||||
)
|
||||
)
|
||||
/* set DUALHEAD_CAPABLE if suitable */
|
||||
//fixme: update for independant secondary head use! (reserve fixed memory then)
|
||||
if (si->ps.secondary_head &&
|
||||
(((si->ps.memory_size * 1024 * 1024) - pointer_reservation) >=
|
||||
/* note: extra line for maven vblank included here! */
|
||||
(row_bytes * (target->virtual_height + 1) * 2)) &&
|
||||
((target->space == B_RGB16_LITTLE) || (target->space == B_RGB32_LITTLE)) &&
|
||||
(target->timing.pixel_clock <= (max_vclk * 1000)))
|
||||
{
|
||||
target->flags&=~DUALHEAD_CAPABLE;
|
||||
target->flags |= DUALHEAD_CAPABLE;
|
||||
}
|
||||
|
||||
/*set tv capable suitable*/
|
||||
if (target->flags&DUALHEAD_CAPABLE)
|
||||
/* set TV_CAPABLE if suitable: pixelclock is not important (defined by TVstandard) */
|
||||
//fixme: modify for G100 and G200 TVout later on...
|
||||
if (target->flags & DUALHEAD_CAPABLE)
|
||||
{
|
||||
if ((target->timing.pixel_clock <= 120000 ) && (target->timing.pixel_clock >= 40000))
|
||||
if (si->ps.secondary_tvout &&
|
||||
(target->timing.h_display <= 1024) &&
|
||||
(target->timing.v_display <= 768))
|
||||
{
|
||||
target->flags|=TV_CAPABLE;
|
||||
target->flags |= TV_CAPABLE;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
/* 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 >= G200)
|
||||
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 setup sync_on_green flag according to
|
||||
* mga.settings options file */
|
||||
target->timing.flags &= ~(B_BLANK_PEDESTAL | B_TIMING_INTERLACED | B_SYNC_ON_GREEN);
|
||||
if (si->settings.greensync)
|
||||
target->timing.flags |= 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) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
@@ -366,7 +403,7 @@ status_t create_mode_list(void) {
|
||||
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("G400 accelerant mode info", (void **)&my_mode_list, B_ANY_ADDRESS, max_size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
||||
create_area("MGA 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 */
|
||||
@@ -380,22 +417,25 @@ status_t create_mode_list(void) {
|
||||
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 */
|
||||
high.virtual_width = 4096;
|
||||
/* '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 for single head (propose will return if capable)*/
|
||||
/* set target values */
|
||||
*dst = *src;
|
||||
/* poke the specific space*/
|
||||
/* poke the specific space */
|
||||
dst->space = low.space = high.space = spaces[j];
|
||||
dst->flags |= DUALHEAD_CAPABLE;
|
||||
|
||||
dst->flags |= B_SUPPORTS_OVERLAYS;
|
||||
//fixme: we need to distinquish somehow between head 1 and head 2, as overlay only works on head 1...
|
||||
|
||||
/* ask for a compatible mode */
|
||||
if (PROPOSE_DISPLAY_MODE(dst, &low, &high) != B_ERROR) {
|
||||
/* 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++;
|
||||
|
||||
@@ -5,15 +5,13 @@
|
||||
Other authors:
|
||||
Mark Watson,
|
||||
Apsed,
|
||||
Rudolf Cornelissen 11-12/2002
|
||||
Rudolf Cornelissen 11/2002-4/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00200000
|
||||
|
||||
#include "acc_std.h"
|
||||
|
||||
#include "matroxfb_maven_hack.h" //a port of the matroxfb code to do TVout - used with permission
|
||||
|
||||
/*
|
||||
Enable/Disable interrupts. Just a wrapper around the
|
||||
ioctl() to the kernel driver.
|
||||
@@ -32,155 +30,188 @@ static void interrupt_enable(bool flag) {
|
||||
/* 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)
|
||||
{
|
||||
display_mode bounds, target;
|
||||
/* 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=32;
|
||||
uint8 colour_depth1 = 32;
|
||||
status_t result;
|
||||
uint32 startadd,startadd_right;
|
||||
// apsed TODO startadd is 19 bits if < g200
|
||||
|
||||
uint8 display,h,v;
|
||||
|
||||
struct my_timming tv_timing;
|
||||
struct mavenregs tv_regs;
|
||||
|
||||
bool switched_crtcs = false;
|
||||
si->switched_crtcs = false;
|
||||
|
||||
/* Adjust mode to valid one and fail if invalid */
|
||||
target = bounds = *mode_to_set;
|
||||
target /*= bounds*/ = *mode_to_set;
|
||||
/* show the mode bits */
|
||||
LOG(1, ("SetDisplayMode - initial flags: %x\n", target.flags));
|
||||
LOG(1, ("SetDisplayMode - %20s %08x %d\n", "timing.pixel_clock", mode_to_set->timing.pixel_clock, mode_to_set->timing.pixel_clock));
|
||||
LOG(1, ("SetDisplayMode - %20s %08x %d\n", "virtual_width", mode_to_set->virtual_width, mode_to_set->virtual_width));
|
||||
LOG(1, ("SetDisplayMode - %20s %08x %d\n", "virtual_height", mode_to_set->virtual_height, mode_to_set->virtual_height));
|
||||
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));
|
||||
|
||||
if (PROPOSE_DISPLAY_MODE(&target, &bounds, &bounds) == B_ERROR)
|
||||
return B_ERROR;
|
||||
/* See BOUNDS WARNING above... */
|
||||
if (PROPOSE_DISPLAY_MODE(&target, &target, &target) == B_ERROR) return B_ERROR;
|
||||
|
||||
/* if not dualhead capable be sure mode is set to single head */
|
||||
if ((!si->ps.secondary_head) || (!(target.flags&DUALHEAD_CAPABLE)))
|
||||
/* if not dualhead capable card clear dualhead flags */
|
||||
if (!(target.flags & DUALHEAD_CAPABLE))
|
||||
{
|
||||
target.flags&=~DUALHEAD_BITS;
|
||||
target.flags&=~TV_BITS;
|
||||
target.flags &= ~DUALHEAD_BITS;
|
||||
}
|
||||
else if (!(target.flags&TV_CAPABLE))
|
||||
/* if not TVout capable card clear TVout flags */
|
||||
if (!(target.flags & TV_CAPABLE))
|
||||
{
|
||||
target.flags&=~TV_BITS;
|
||||
target.flags &= ~TV_BITS;
|
||||
}
|
||||
|
||||
LOG(1, ("SetDisplayMode - validated flags: %x\n", target.flags));
|
||||
LOG(1, ("SETMODE: (CONT.) validated command modeflags: $%08x\n", target.flags));
|
||||
|
||||
/* disable interrupts using the kernel driver */
|
||||
interrupt_enable(false);
|
||||
|
||||
/*find current DPMS state, then turn off screen*/
|
||||
/* find current DPMS state, then turn off screen(s) */
|
||||
gx00_crtc_dpms_fetch(&display,&h,&v);
|
||||
gx00_crtc_dpms(0,0,0);
|
||||
if (si->ps.card_type >= G400) // apsed TODO when g200 pixrdmsk is broken
|
||||
g400_crtc2_dpms(0,0,0);
|
||||
if (si->ps.secondary_head)
|
||||
gx00_maven_dpms(0,0,0);
|
||||
if (si->ps.secondary_head) g400_crtc2_dpms(0,0,0);
|
||||
|
||||
/*where in framebuffer the screen is (should this be dependant on previous MOVEDISPLAY?)*/
|
||||
startadd=(si->fbc.frame_buffer)-(si->framebuffer);
|
||||
startadd = si->fbc.frame_buffer - si->framebuffer;
|
||||
|
||||
/* calculate and set new mode bytes_per_row */
|
||||
gx00_general_validate_pic_size (&target, &si->fbc.bytes_per_row);
|
||||
|
||||
/*Perform the very long mode switch!*/
|
||||
LOG(1,("DUALHEAD: %d\n",target.flags&DUALHEAD_BITS));
|
||||
if ((target.flags&DUALHEAD_BITS)) /*if some dualhead mode*/
|
||||
if (target.flags & DUALHEAD_BITS) /*if some dualhead mode*/
|
||||
{
|
||||
uint16 crtc1_vdisplay, crtc2_vdisplay;
|
||||
uint8 colour_depth2 = colour_depth1;
|
||||
|
||||
/*set the pixel clock PLL(s)*/
|
||||
if (gx00_dac_set_pix_pll(target)==B_ERROR)
|
||||
LOG(8,("SET: error setting pixel clock (internal DAC)\n"));
|
||||
if (si->ps.secondary_head)
|
||||
/* init display mode for secondary head */
|
||||
display_mode target2 = target;
|
||||
|
||||
LOG(1,("SETMODE: setting DUALHEAD mode\n"));
|
||||
|
||||
/* validate flags for secondary TVout */
|
||||
if ((i2c_sec_tv_adapter() != B_OK) && (target2.flags & TV_BITS))
|
||||
{
|
||||
if (gx00_maven_set_pix_pll((target.timing.pixel_clock)/1000.0)==B_ERROR)
|
||||
LOG(8,("SET: error setting pixel clock (MAVEN)\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(8,("SET: not setting maven clock (G450?)\n"));
|
||||
target.flags &= ~TV_BITS;//still needed for some routines...
|
||||
target2.flags &= ~TV_BITS;
|
||||
LOG(1,("SETMODE: blocking TVout: no TVout cable connected!\n"));
|
||||
}
|
||||
|
||||
/*set the colour depth for CRTC1, CRTC2, the DAC and the MAVEN */
|
||||
/* set the pixel clock PLL(s) */
|
||||
LOG(8,("SETMODE: target clock %dkHz\n",target.timing.pixel_clock));
|
||||
if (gx00_dac_set_pix_pll(target) == B_ERROR)
|
||||
LOG(8,("SETMODE: error setting pixel clock (internal DAC)\n"));
|
||||
|
||||
/* we do not need to set the pixelclock here for a head that's in TVout mode */
|
||||
if (!(target2.flags & TV_BITS))
|
||||
{
|
||||
LOG(8,("SETMODE: target2 clock %dkHz\n",target2.timing.pixel_clock));
|
||||
if (gx00_maven_set_vid_pll(target2) == B_ERROR)
|
||||
LOG(8,("SETMODE: error setting pixel clock (MAVEN)\n"));
|
||||
}
|
||||
|
||||
/*set the colour depth for CRTC1 and the DAC */
|
||||
switch(target.space)
|
||||
{
|
||||
case B_RGB16_LITTLE:
|
||||
colour_depth=16;
|
||||
colour_depth1 = 16;
|
||||
gx00_dac_mode(BPP16, 1.0);
|
||||
gx00_maven_mode(BPP16, 1.0);
|
||||
gx00_crtc_depth(BPP16);
|
||||
break;
|
||||
case B_RGB32_LITTLE:
|
||||
colour_depth1 = 32;
|
||||
gx00_dac_mode(BPP32, 1.0);
|
||||
gx00_crtc_depth(BPP32);
|
||||
break;
|
||||
}
|
||||
/*set the colour depth for CRTC2 and the MAVEN */
|
||||
switch(target2.space)
|
||||
{
|
||||
case B_RGB16_LITTLE:
|
||||
colour_depth2 = 16;
|
||||
gx00_maven_mode(BPP16, 1.0);
|
||||
g400_crtc2_depth(BPP16);
|
||||
break;
|
||||
case B_RGB32_LITTLE:
|
||||
colour_depth=32;
|
||||
gx00_dac_mode(BPP32, 1.0);
|
||||
colour_depth2 = 32;
|
||||
gx00_maven_mode(BPP32DIR, 1.0);
|
||||
gx00_crtc_depth(BPP32);
|
||||
g400_crtc2_depth(BPP32DIR);
|
||||
break;
|
||||
default:
|
||||
LOG(8,("SET: Invalid dualhead colour depth 0x%08x - should never happen!\n", target.space));
|
||||
}
|
||||
|
||||
/* check if we are doing interlaced TVout mode */
|
||||
si->interlaced_tv_mode = false;
|
||||
if ((target2.flags & TV_BITS) && (si->ps.card_type >= G450))
|
||||
si->interlaced_tv_mode = true;
|
||||
|
||||
/*set the display(s) pitches*/
|
||||
gx00_crtc_set_display_pitch (target.virtual_width, colour_depth);
|
||||
g400_crtc2_set_display_pitch (target.virtual_width, colour_depth);
|
||||
gx00_crtc_set_display_pitch ();
|
||||
//fixme: seperate for real dualhead modes:
|
||||
//we need a secondary si->fbc!
|
||||
g400_crtc2_set_display_pitch ();
|
||||
|
||||
/*work out where the "right" screen starts*/
|
||||
startadd_right=startadd+(target.timing.h_display*(colour_depth>>3));
|
||||
startadd_right=startadd+(target.timing.h_display * (colour_depth1 >> 3));
|
||||
|
||||
/* calculate needed MAVEN-CRTC delay: formula valid for straight-through CRTC's */
|
||||
si->crtc_delay = 44 + 0 * (colour_depth == 16);
|
||||
si->crtc_delay = 44 + 0 * (colour_depth2 == 16);
|
||||
|
||||
/* setup vertical timing adjust for crtc1 and crtc2 for straight-through CRTC's */
|
||||
crtc1_vdisplay = target.timing.v_display;
|
||||
/* (extra "blanking" line for MAVEN) */
|
||||
crtc2_vdisplay = target.timing.v_display + 1;
|
||||
target2.timing.v_display++;
|
||||
|
||||
/* set the outputs */
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
case G400:
|
||||
case G400MAX:
|
||||
switch (target.flags&DUALHEAD_BITS)
|
||||
switch (target.flags & DUALHEAD_BITS)
|
||||
{
|
||||
case DUALHEAD_ON:
|
||||
case DUALHEAD_CLONE:
|
||||
gx00_general_dac_select(DS_CRTC1DAC_CRTC2MAVEN);
|
||||
switched_crtcs = false;
|
||||
si->switched_crtcs = false;
|
||||
break;
|
||||
case DUALHEAD_SWITCH:
|
||||
if (i2c_sec_tv_adapter() == B_OK)
|
||||
{
|
||||
/* Don't switch CRTC's because MAVEN YUV is impossible then,
|
||||
* and primary head output will be limited to 135Mhz pixelclock. */
|
||||
LOG(4,("SET: secondary TV-adapter detected, switching buffers\n"));
|
||||
LOG(4,("SETMODE: secondary TV-adapter detected, switching buffers\n"));
|
||||
gx00_general_dac_select(DS_CRTC1DAC_CRTC2MAVEN);
|
||||
switched_crtcs = true;
|
||||
si->switched_crtcs = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This limits the pixelclocks on both heads to 135Mhz,
|
||||
* but you can use overlay on the other output now. */
|
||||
LOG(4,("SET: no secondary TV-adapter detected, switching CRTCs\n"));
|
||||
LOG(4,("SETMODE: no secondary TV-adapter detected, switching CRTCs\n"));
|
||||
gx00_general_dac_select(DS_CRTC1MAVEN_CRTC2DAC);
|
||||
switched_crtcs = false;
|
||||
si->switched_crtcs = false;
|
||||
/* re-calculate MAVEN-CRTC delay: formula valid for crossed CRTC's */
|
||||
si->crtc_delay = 17 + 4 * (colour_depth == 16);
|
||||
si->crtc_delay = 17 + 4 * (colour_depth1 == 16);
|
||||
/* re-setup vertical timing adjust for crtc1 and crtc2 for crossed CRTC's */
|
||||
/* (extra "blanking" line for MAVEN) */
|
||||
crtc1_vdisplay = target.timing.v_display + 1;
|
||||
crtc2_vdisplay = target.timing.v_display;
|
||||
target.timing.v_display++;
|
||||
target2.timing.v_display--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
//fixme:
|
||||
//use current SETMODE MAVEN programming only on G400/G400MAX;
|
||||
//and copy & modify/resetup this stuff for G450(?)/G550 cards!
|
||||
//warning:
|
||||
//setup crtc_delay and vertical timing adjust for G450(?)/G550,
|
||||
//and remove the '+1' in crtc2 vertical timing(?)
|
||||
case G450:
|
||||
@@ -189,29 +220,29 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
/* output connector use is always 'straight-through' */
|
||||
//fixme: re-evaluate when DVI is setup...
|
||||
{
|
||||
switch (target.flags&DUALHEAD_BITS)
|
||||
switch (target.flags & DUALHEAD_BITS)
|
||||
{
|
||||
case DUALHEAD_ON:
|
||||
case DUALHEAD_CLONE:
|
||||
gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2);
|
||||
switched_crtcs = false;
|
||||
si->switched_crtcs = false;
|
||||
break;
|
||||
case DUALHEAD_SWITCH:
|
||||
if (i2c_sec_tv_adapter() == B_OK)
|
||||
{
|
||||
/* Don't switch CRTC's because MAVEN YUV and TVout is impossible then,
|
||||
* and primary head output will be limited to 235Mhz pixelclock. */
|
||||
LOG(4,("SET: secondary TV-adapter detected, switching buffers\n"));
|
||||
LOG(4,("SETMODE: secondary TV-adapter detected, switching buffers\n"));
|
||||
gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2);
|
||||
switched_crtcs = true;
|
||||
si->switched_crtcs = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This limits the pixelclocks on both heads to 235Mhz,
|
||||
* but you can use overlay on the other output now. */
|
||||
LOG(4,("SET: no secondary TV-adapter detected, switching CRTCs\n"));
|
||||
LOG(4,("SETMODE: no secondary TV-adapter detected, switching CRTCs\n"));
|
||||
gx00_general_dac_select(DS_CRTC1CON2_CRTC2CON1);
|
||||
switched_crtcs = false;
|
||||
si->switched_crtcs = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -220,21 +251,21 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
/* output connector use is cross-linked if no TV cable connected! */
|
||||
//fixme: re-evaluate when DVI is setup...
|
||||
{
|
||||
switch (target.flags&DUALHEAD_BITS)
|
||||
switch (target.flags & DUALHEAD_BITS)
|
||||
{
|
||||
case DUALHEAD_ON:
|
||||
case DUALHEAD_CLONE:
|
||||
if (i2c_sec_tv_adapter() == B_OK)
|
||||
{
|
||||
gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2);
|
||||
switched_crtcs = false;
|
||||
si->switched_crtcs = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This limits the pixelclocks on both heads to 235Mhz,
|
||||
* but you can use overlay on the other output now. */
|
||||
gx00_general_dac_select(DS_CRTC1CON2_CRTC2CON1);
|
||||
switched_crtcs = false;
|
||||
si->switched_crtcs = false;
|
||||
}
|
||||
break;
|
||||
case DUALHEAD_SWITCH:
|
||||
@@ -242,15 +273,15 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
{
|
||||
/* Don't switch CRTC's because MAVEN YUV and TVout is impossible then,
|
||||
* and primary head output will be limited to 235Mhz pixelclock. */
|
||||
LOG(4,("SET: secondary TV-adapter detected, switching buffers\n"));
|
||||
LOG(4,("SETMODE: secondary TV-adapter detected, switching buffers\n"));
|
||||
gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2);
|
||||
switched_crtcs = true;
|
||||
si->switched_crtcs = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(4,("SET: no secondary TV-adapter detected, switching CRTCs\n"));
|
||||
LOG(4,("SETMODE: no secondary TV-adapter detected, switching CRTCs\n"));
|
||||
gx00_general_dac_select(DS_CRTC1CON1_CRTC2CON2);
|
||||
switched_crtcs = false;
|
||||
si->switched_crtcs = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -260,149 +291,87 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
break;
|
||||
}
|
||||
|
||||
if (switched_crtcs)
|
||||
if (si->switched_crtcs)
|
||||
{
|
||||
int temp = startadd;
|
||||
uint32 temp = startadd;
|
||||
startadd = startadd_right;
|
||||
startadd_right = temp;
|
||||
}
|
||||
|
||||
/*Tell card what memory to display*/
|
||||
switch (target.flags&DUALHEAD_BITS)
|
||||
switch (target.flags & DUALHEAD_BITS)
|
||||
{
|
||||
case DUALHEAD_ON:
|
||||
case DUALHEAD_SWITCH:
|
||||
gx00_crtc_set_display_start(startadd,colour_depth);
|
||||
g400_crtc2_set_display_start(startadd_right,colour_depth);
|
||||
gx00_crtc_set_display_start(startadd,colour_depth1);
|
||||
g400_crtc2_set_display_start(startadd_right,colour_depth2);
|
||||
break;
|
||||
case DUALHEAD_CLONE:
|
||||
gx00_crtc_set_display_start(startadd,colour_depth);
|
||||
g400_crtc2_set_display_start(startadd,colour_depth);
|
||||
gx00_crtc_set_display_start(startadd,colour_depth1);
|
||||
g400_crtc2_set_display_start(startadd,colour_depth2);
|
||||
break;
|
||||
}
|
||||
|
||||
/*set the timing*/
|
||||
/* set the timing */
|
||||
result = gx00_crtc_set_timing /*crtc1*/
|
||||
(
|
||||
target.timing.h_display,
|
||||
target.timing.h_sync_start,
|
||||
target.timing.h_sync_end,
|
||||
target.timing.h_total,
|
||||
crtc1_vdisplay,
|
||||
target.timing.v_display,
|
||||
target.timing.v_sync_start,
|
||||
target.timing.v_sync_end,
|
||||
target.timing.v_total,
|
||||
target.timing.flags&B_POSITIVE_HSYNC,
|
||||
target.timing.flags&B_POSITIVE_VSYNC
|
||||
);
|
||||
/* we do not need to setup CRTC2 here for a head that's in TVout mode */
|
||||
if (!(target2.flags & TV_BITS)) result = g400_crtc2_set_timing(target2);
|
||||
|
||||
result = g400_crtc2_set_timing
|
||||
(
|
||||
target.timing.h_display,
|
||||
target.timing.h_sync_start,
|
||||
target.timing.h_sync_end,
|
||||
target.timing.h_total,
|
||||
crtc2_vdisplay,
|
||||
target.timing.v_sync_start,
|
||||
target.timing.v_sync_end,
|
||||
target.timing.v_total,
|
||||
target.timing.flags&B_POSITIVE_HSYNC,
|
||||
target.timing.flags&B_POSITIVE_VSYNC
|
||||
);
|
||||
if (si->ps.secondary_head)
|
||||
/* TVout support: setup CRTC2 and it's pixelclock */
|
||||
if (si->ps.secondary_tvout && (target2.flags & TV_BITS))
|
||||
{
|
||||
result = gx00_maven_set_timing /*maven*/
|
||||
(
|
||||
target.timing.h_display,
|
||||
target.timing.h_sync_start,
|
||||
target.timing.h_sync_end,
|
||||
target.timing.h_total,
|
||||
(target.timing.v_display+1), /* The extra "blanking" line */
|
||||
target.timing.v_sync_start,
|
||||
target.timing.v_sync_end,
|
||||
target.timing.v_total,
|
||||
target.timing.flags&B_POSITIVE_HSYNC,
|
||||
target.timing.flags&B_POSITIVE_VSYNC
|
||||
);
|
||||
}
|
||||
|
||||
/*turn screen one on and screen two on*/
|
||||
gx00_crtc_dpms(display,h,v);
|
||||
g400_crtc2_dpms(display,h,v);
|
||||
if (si->ps.secondary_head)
|
||||
gx00_maven_dpms(display,h,v);
|
||||
|
||||
/*TVout support*/
|
||||
if (si->ps.secondary_tvout && (target.flags&TV_BITS))
|
||||
{
|
||||
//fixme: re-tune if needed, checkout cross and straight crtc's seperately..
|
||||
si->crtc_delay+=5;
|
||||
|
||||
/*create a my tim(m)ing structure... for tvout*/
|
||||
tv_timing.pixclock = target.timing.pixel_clock;
|
||||
tv_timing.HDisplay = target.timing.h_display;
|
||||
tv_timing.HSyncStart = target.timing.h_sync_start;
|
||||
tv_timing.HSyncEnd = target.timing.h_sync_end;
|
||||
tv_timing.HTotal = target.timing.h_total;
|
||||
tv_timing.VDisplay = target.timing.v_display;
|
||||
tv_timing.VSyncStart = target.timing.v_sync_start;
|
||||
tv_timing.VSyncEnd = target.timing.v_sync_end;
|
||||
tv_timing.VTotal = target.timing.v_total;
|
||||
tv_timing.delay=si->crtc_delay;
|
||||
|
||||
if (target.flags&TV_PAL)
|
||||
{
|
||||
LOG(2, ("OUTMODE: PAL\n"));
|
||||
maven_set_mode(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(2, ("OUTMODE: NTSC\n"));
|
||||
maven_set_mode(2);
|
||||
}
|
||||
|
||||
maven_out_compute(&tv_timing, &tv_regs);
|
||||
maven_out_program(&tv_regs);
|
||||
maven_out_start();
|
||||
si->crtc_delay += 5;
|
||||
maventv_init(target2);
|
||||
}
|
||||
}
|
||||
else /*single head mode*/
|
||||
else /* single head mode */
|
||||
{
|
||||
status_t status;
|
||||
int colour_mode = BPP32;
|
||||
int colour_mode = BPP32;
|
||||
|
||||
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_RGB32_LITTLE: colour_depth = 32; colour_mode = BPP32; break;
|
||||
case B_CMAP8: colour_depth1 = 8; colour_mode = BPP8; break;
|
||||
case B_RGB15_LITTLE: colour_depth1 = 16; colour_mode = BPP15; break;
|
||||
case B_RGB16_LITTLE: colour_depth1 = 16; colour_mode = BPP16; break;
|
||||
case B_RGB32_LITTLE: colour_depth1 = 32; colour_mode = BPP32; break;
|
||||
default:
|
||||
LOG(8,("SET: Invalid singlehead colour depth 0x%08x\n", target.space));
|
||||
LOG(8,("SETMODE: Invalid singlehead colour depth 0x%08x\n", target.space));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/*set the pixel clock PLL*/
|
||||
/* set the pixel clock PLL */
|
||||
if (si->ps.card_type >= G100)
|
||||
status = gx00_dac_set_pix_pll(target);
|
||||
else status = mil2_dac_set_pix_pll((target.timing.pixel_clock)/1000.0, colour_depth);
|
||||
else
|
||||
{
|
||||
status = mil2_dac_set_pix_pll((target.timing.pixel_clock)/1000.0, colour_depth1);
|
||||
}
|
||||
if (status==B_ERROR)
|
||||
LOG(8,("CRTC: error setting pixel clock (internal DAC)\n"));
|
||||
|
||||
/*set the colour depth for CRTC1 and the DAC*/
|
||||
if (si->ps.card_type >= G100) gx00_dac_mode(colour_mode,1.0);
|
||||
else mil2_dac_mode(colour_mode,1.0,
|
||||
target.timing.flags&B_POSITIVE_HSYNC,
|
||||
target.timing.flags&B_POSITIVE_VSYNC,
|
||||
target.timing.flags&B_SYNC_ON_GREEN);
|
||||
|
||||
/* set the colour depth for CRTC1 and the DAC */
|
||||
gx00_dac_mode(colour_mode,1.0);
|
||||
gx00_crtc_depth(colour_mode);
|
||||
|
||||
/*set the display pitch*/
|
||||
gx00_crtc_set_display_pitch (target.virtual_width, colour_depth);
|
||||
/* set the display pitch */
|
||||
gx00_crtc_set_display_pitch();
|
||||
|
||||
/* tell the card what memory to display */
|
||||
gx00_crtc_set_display_start(startadd,colour_depth1);
|
||||
|
||||
/*tell the card what memory to display*/
|
||||
gx00_crtc_set_display_start(startadd,colour_depth);
|
||||
/* enable primary analog output */
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
@@ -421,7 +390,7 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
break;
|
||||
}
|
||||
|
||||
/*set the timing*/
|
||||
/* set the timing */
|
||||
result = gx00_crtc_set_timing /*crtc1*/
|
||||
(
|
||||
target.timing.h_display,
|
||||
@@ -436,33 +405,32 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set)
|
||||
target.timing.flags&B_POSITIVE_VSYNC
|
||||
);
|
||||
|
||||
/*turn screen one on and screen two off*/
|
||||
gx00_crtc_dpms(display,h,v);
|
||||
if (si->ps.card_type >= G400) // apsed TODO when g200 pixrdmsk is broken
|
||||
g400_crtc2_dpms(0,0,0);
|
||||
if (si->ps.secondary_head)
|
||||
gx00_maven_dpms(0,0,0);
|
||||
//fixme: shut-off the videoPLL if it exists...
|
||||
}
|
||||
|
||||
/*update driver's mode store*/
|
||||
si->dm=target;
|
||||
si->fbc.bytes_per_row=target.virtual_width*(colour_depth>>3);
|
||||
/* update driver's mode store */
|
||||
si->dm = target;
|
||||
|
||||
/*set up acceleration for this mode*/
|
||||
si->dm.virtual_height+=1;//for clipping!
|
||||
/* turn screen one on */
|
||||
gx00_crtc_dpms(display,h,v);
|
||||
/* turn screen two on if a dualhead mode is active */
|
||||
if (target.flags & DUALHEAD_BITS) g400_crtc2_dpms(display,h,v);
|
||||
|
||||
/* set up acceleration for this mode */
|
||||
si->dm.virtual_height += 1;//for clipping!
|
||||
gx00_acc_init();
|
||||
si->dm.virtual_height-=1;
|
||||
si->dm.virtual_height -= 1;
|
||||
|
||||
/*clear line at bottom of screen (For maven) if dualhead mode*/
|
||||
/* clear line at bottom of screen (for maven) if dualhead mode */
|
||||
gx00_acc_rectangle(0,si->dm.virtual_width+1,si->dm.virtual_height,1,0);
|
||||
|
||||
MSG(("INIT_ACCELERANT: booted since %f ms\n", system_time()/1000.0));
|
||||
MSG(("SETMODE: booted since %f mS\n", system_time()/1000.0));
|
||||
|
||||
/* enable interrupts using the kernel driver */
|
||||
interrupt_enable(true);
|
||||
|
||||
/* optimize memory-access if needed */
|
||||
gx00_crtc_mem_priority(colour_depth);
|
||||
gx00_crtc_mem_priority(colour_depth1);
|
||||
|
||||
/* Tune RAM CAS-latency if needed. Must be done *here*! */
|
||||
mga_set_cas_latency();
|
||||
@@ -486,7 +454,7 @@ status_t MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start) {
|
||||
*/
|
||||
|
||||
/* reset lower bits, don't return an error! */
|
||||
if (si->dm.flags&DUALHEAD_BITS)
|
||||
if (si->dm.flags & DUALHEAD_BITS)
|
||||
{
|
||||
switch(si->dm.space)
|
||||
{
|
||||
@@ -525,8 +493,18 @@ status_t MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start) {
|
||||
}
|
||||
|
||||
/* do not run past end of display */
|
||||
if ((si->dm.timing.h_display + h_display_start) > si->dm.virtual_width)
|
||||
return B_ERROR;
|
||||
switch (si->dm.flags & DUALHEAD_BITS)
|
||||
{
|
||||
case DUALHEAD_ON:
|
||||
case DUALHEAD_SWITCH:
|
||||
if (((si->dm.timing.h_display * 2) + h_display_start) > si->dm.virtual_width)
|
||||
return B_ERROR;
|
||||
break;
|
||||
default:
|
||||
if ((si->dm.timing.h_display + h_display_start) > si->dm.virtual_width)
|
||||
return B_ERROR;
|
||||
break;
|
||||
}
|
||||
if ((si->dm.timing.v_display + v_display_start) > si->dm.virtual_height)
|
||||
return B_ERROR;
|
||||
|
||||
@@ -535,16 +513,26 @@ status_t MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start) {
|
||||
si->dm.v_display_start = v_display_start;
|
||||
|
||||
/* actually set the registers */
|
||||
startadd=v_display_start*(si->dm.virtual_width*colour_depth)>>3;
|
||||
startadd+=h_display_start;
|
||||
startadd+=(si->fbc.frame_buffer)-(si->framebuffer);
|
||||
startadd_right=startadd+si->dm.timing.h_display*(colour_depth>>3);
|
||||
//fixme: seperate both heads: we need a secondary si->fbc!
|
||||
startadd = v_display_start * si->fbc.bytes_per_row;
|
||||
startadd += h_display_start * (colour_depth >> 3);
|
||||
startadd += si->fbc.frame_buffer - si->framebuffer;
|
||||
startadd_right = startadd + si->dm.timing.h_display * (colour_depth >> 3);
|
||||
|
||||
/* account for switched CRTC's */
|
||||
if (si->switched_crtcs)
|
||||
{
|
||||
uint32 temp = startadd;
|
||||
startadd = startadd_right;
|
||||
startadd_right = temp;
|
||||
}
|
||||
|
||||
interrupt_enable(false);
|
||||
|
||||
switch (si->dm.flags&DUALHEAD_BITS)
|
||||
{
|
||||
case DUALHEAD_ON:
|
||||
case DUALHEAD_SWITCH:
|
||||
gx00_crtc_set_display_start(startadd,colour_depth);
|
||||
g400_crtc2_set_display_start(startadd_right,colour_depth);
|
||||
break;
|
||||
@@ -555,10 +543,6 @@ status_t MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start) {
|
||||
gx00_crtc_set_display_start(startadd,colour_depth);
|
||||
g400_crtc2_set_display_start(startadd,colour_depth);
|
||||
break;
|
||||
case DUALHEAD_SWITCH:
|
||||
g400_crtc2_set_display_start(startadd,colour_depth);
|
||||
gx00_crtc_set_display_start(startadd_right,colour_depth);
|
||||
break;
|
||||
}
|
||||
|
||||
interrupt_enable(true);
|
||||
@@ -587,8 +571,7 @@ void SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags
|
||||
b[i]=*color_data++;
|
||||
i++;
|
||||
}
|
||||
if (si->ps.card_type >= G100) gx00_dac_palette(r,g,b);
|
||||
else mil2_dac_palette(r,g,b);
|
||||
gx00_dac_palette(r,g,b);
|
||||
}
|
||||
|
||||
|
||||
@@ -600,9 +583,7 @@ enum {
|
||||
BITSMASK = H_SYNC_OFF | V_SYNC_OFF | DISPLAY_OFF
|
||||
};
|
||||
|
||||
/*
|
||||
Put the display into one of the Display Power Management modes.
|
||||
*/
|
||||
/* Put the display into one of the Display Power Management modes. */
|
||||
status_t SET_DPMS_MODE(uint32 dpms_flags) {
|
||||
interrupt_enable(false);
|
||||
|
||||
@@ -614,27 +595,19 @@ status_t SET_DPMS_MODE(uint32 dpms_flags) {
|
||||
{
|
||||
case B_DPMS_ON: /* H: on, V: on */
|
||||
gx00_crtc_dpms(1,1,1);
|
||||
g400_crtc2_dpms(1,1,1);
|
||||
if (si->ps.secondary_head)
|
||||
gx00_maven_dpms(1,1,1);
|
||||
if (si->ps.secondary_head) g400_crtc2_dpms(1,1,1);
|
||||
break;
|
||||
case B_DPMS_STAND_BY:
|
||||
gx00_crtc_dpms(0,0,1);
|
||||
g400_crtc2_dpms(0,0,1);
|
||||
if (si->ps.secondary_head)
|
||||
gx00_maven_dpms(0,0,1);
|
||||
if (si->ps.secondary_head) g400_crtc2_dpms(0,0,1);
|
||||
break;
|
||||
case B_DPMS_SUSPEND:
|
||||
gx00_crtc_dpms(0,1,0);
|
||||
g400_crtc2_dpms(0,1,0);
|
||||
if (si->ps.secondary_head)
|
||||
gx00_maven_dpms(0,1,0);
|
||||
if (si->ps.secondary_head) g400_crtc2_dpms(0,1,0);
|
||||
break;
|
||||
case B_DPMS_OFF: /* H: off, V: off, display off */
|
||||
gx00_crtc_dpms(0,0,0);
|
||||
g400_crtc2_dpms(0,0,0);
|
||||
if (si->ps.secondary_head)
|
||||
gx00_maven_dpms(0,0,0);
|
||||
if (si->ps.secondary_head) g400_crtc2_dpms(0,0,0);
|
||||
break;
|
||||
default:
|
||||
LOG(8,("SET: Invalid DPMS settings (DH) 0x%08x\n", dpms_flags));
|
||||
|
||||
@@ -5,7 +5,6 @@ UsePrivateHeaders [ FDirName graphics matrox ] ;
|
||||
UseHeaders [ FDirName $(SUBDIR) .. ] ;
|
||||
|
||||
StaticLibrary matrox_engine :
|
||||
matroxfb_maven_hack.c
|
||||
mga_acc.c
|
||||
mga_bes.c
|
||||
mga_crtc.c
|
||||
@@ -15,6 +14,7 @@ StaticLibrary matrox_engine :
|
||||
mga_i2c.c
|
||||
mga_info.c
|
||||
mga_maven.c
|
||||
mga_maventv.c
|
||||
mga_support.c
|
||||
tvp3026.c
|
||||
;
|
||||
|
||||
@@ -1,879 +0,0 @@
|
||||
#define MODULE_BIT 0x00100000
|
||||
|
||||
#include "mga_std.h"
|
||||
#include "matroxfb_maven_hack.h"
|
||||
|
||||
#define MODE_PAL 1
|
||||
#define MODE_NTSC 2
|
||||
#define MODE_TV(x) (((x) == MODE_PAL) || ((x) == MODE_NTSC))
|
||||
#define MODE_MONITOR 128
|
||||
|
||||
static int mode = MODE_PAL;
|
||||
|
||||
static const struct matrox_pll_features maven_pll = {
|
||||
50000,
|
||||
27000,
|
||||
4, 127,
|
||||
2, 31,
|
||||
3
|
||||
};
|
||||
|
||||
static const struct matrox_pll_features2 maven1000_pll = {
|
||||
50000000,
|
||||
300000000,
|
||||
5, 128,
|
||||
3, 32,
|
||||
3
|
||||
};
|
||||
|
||||
static const struct matrox_pll_ctl maven_PAL = {
|
||||
540000,
|
||||
50
|
||||
};
|
||||
|
||||
static const struct matrox_pll_ctl maven_NTSC = {
|
||||
450450, /* 27027000/60 == 27000000/59.94005994 */
|
||||
60
|
||||
};
|
||||
|
||||
|
||||
int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int freq, unsigned int fmax,
|
||||
unsigned int* in, unsigned int* feed, unsigned int* post) {
|
||||
unsigned int bestdiff = ~0;
|
||||
unsigned int bestvco = 0;
|
||||
unsigned int fxtal = pll->ref_freq;
|
||||
unsigned int fwant;
|
||||
unsigned int p;
|
||||
|
||||
LOG(4,("PLL_calcclock"));
|
||||
|
||||
fwant = freq;
|
||||
|
||||
for (p = 1; p <= pll->post_shift_max; p++) {
|
||||
if (fwant * 2 > fmax)
|
||||
break;
|
||||
fwant *= 2;
|
||||
}
|
||||
if (fwant < pll->vco_freq_min) fwant = pll->vco_freq_min;
|
||||
if (fwant > fmax) fwant = fmax;
|
||||
for (; p-- > 0; fwant >>= 1, bestdiff >>= 1) {
|
||||
unsigned int m;
|
||||
|
||||
if (fwant < pll->vco_freq_min) break;
|
||||
for (m = pll->in_div_min; m <= pll->in_div_max; m++) {
|
||||
unsigned int diff, fvco;
|
||||
unsigned int n;
|
||||
|
||||
n = (fwant * (m + 1) + (fxtal >> 1)) / fxtal - 1;
|
||||
if (n > pll->feed_div_max)
|
||||
break;
|
||||
if (n < pll->feed_div_min)
|
||||
n = pll->feed_div_min;
|
||||
fvco = (fxtal * (n + 1)) / (m + 1);
|
||||
if (fvco < fwant)
|
||||
diff = fwant - fvco;
|
||||
else
|
||||
diff = fvco - fwant;
|
||||
if (diff < bestdiff) {
|
||||
bestdiff = diff;
|
||||
*post = p;
|
||||
*in = m;
|
||||
*feed = n;
|
||||
bestvco = fvco;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG(4,("clk: %x %x %x %d %d %d\n", *in, *feed, *post, fxtal, bestvco, fwant));
|
||||
return bestvco;
|
||||
}
|
||||
|
||||
int matroxfb_PLL_mavenclock(const struct matrox_pll_features2* pll,
|
||||
const struct matrox_pll_ctl* ctl,
|
||||
unsigned int htotal, unsigned int vtotal,
|
||||
unsigned int* in, unsigned int* feed, unsigned int* post,
|
||||
unsigned int* h2) {
|
||||
unsigned int besth2 = 0;
|
||||
unsigned int fxtal = ctl->ref_freq;
|
||||
unsigned int fmin = pll->vco_freq_min / ctl->den;
|
||||
unsigned int fwant;
|
||||
unsigned int p;
|
||||
unsigned int scrlen;
|
||||
unsigned int fmax;
|
||||
|
||||
LOG(4,("PLL_calcclock"));
|
||||
|
||||
scrlen = htotal * (vtotal - 1);
|
||||
fwant = htotal * vtotal;
|
||||
fmax = pll->vco_freq_max / ctl->den;
|
||||
|
||||
LOG(2, ("FVMAB:want: %x, xtal: %x, h: %x, v: %x, fmax: %x\n",
|
||||
fwant, fxtal, htotal, vtotal, fmax));
|
||||
for (p = 1; p <= pll->post_shift_max; p++) {
|
||||
if (fwant * 2 > fmax)
|
||||
break;
|
||||
fwant *= 2;
|
||||
}
|
||||
if (fwant > fmax)
|
||||
return 0;
|
||||
for (; p-- > 0; fwant >>= 1) {
|
||||
unsigned int m;
|
||||
|
||||
if (fwant < fmin) break;
|
||||
for (m = pll->in_div_min; m <= pll->in_div_max; m++) {
|
||||
unsigned int n;
|
||||
unsigned int dvd;
|
||||
unsigned int ln;
|
||||
|
||||
n = (fwant * m) / fxtal;
|
||||
if (n < pll->feed_div_min)
|
||||
continue;
|
||||
if (n > pll->feed_div_max)
|
||||
break;
|
||||
|
||||
ln = fxtal * n;
|
||||
dvd = m << p;
|
||||
|
||||
if (ln % dvd)
|
||||
continue;
|
||||
ln = ln / dvd;
|
||||
|
||||
if (ln < scrlen + 2)
|
||||
continue;
|
||||
ln = ln - scrlen;
|
||||
if (ln > htotal)
|
||||
continue;
|
||||
LOG(2,("FBMAV:Match: %x / %x / %x / %x\n", n, m, p, ln));
|
||||
if (ln > besth2) {
|
||||
LOG(2, ("FBMAV:Better...\n"));
|
||||
*h2 = besth2 = ln;
|
||||
*post = p;
|
||||
*in = m;
|
||||
*feed = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (besth2 < 2)
|
||||
return 0;
|
||||
LOG(4,("FBMAV:clk: %x %x %x %d %d\n", *in, *feed, *post, fxtal, fwant));
|
||||
return fxtal * (*feed) / (*in) * ctl->den;
|
||||
}
|
||||
|
||||
unsigned int matroxfb_mavenclock(const struct matrox_pll_ctl* ctl,
|
||||
unsigned int htotal, unsigned int vtotal,
|
||||
unsigned int* in, unsigned int* feed, unsigned int* post,
|
||||
unsigned int* htotal2) {
|
||||
unsigned int fvco;
|
||||
unsigned int p;
|
||||
|
||||
fvco = matroxfb_PLL_mavenclock(&maven1000_pll, ctl, htotal, vtotal, in, feed, &p, htotal2);
|
||||
if (!fvco)
|
||||
return -EINVAL;
|
||||
p = (1 << p) - 1;
|
||||
if (fvco <= 100000000)
|
||||
;
|
||||
else if (fvco <= 140000000)
|
||||
p |= 0x08;
|
||||
else if (fvco <= 180000000)
|
||||
p |= 0x10;
|
||||
else
|
||||
p |= 0x18;
|
||||
*post = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DAC1064_calcclock(unsigned int freq, unsigned int fmax,
|
||||
unsigned int* in, unsigned int* feed, unsigned int* post) {
|
||||
unsigned int fvco;
|
||||
unsigned int p;
|
||||
|
||||
fvco = matroxfb_PLL_calcclock(&maven_pll, freq, fmax, in, feed, &p);
|
||||
p = (1 << p) - 1;
|
||||
if (fvco <= 100000)
|
||||
;
|
||||
else if (fvco <= 140000)
|
||||
p |= 0x08;
|
||||
else if (fvco <= 180000)
|
||||
p |= 0x10;
|
||||
else
|
||||
p |= 0x18;
|
||||
*post = p;
|
||||
return;
|
||||
}
|
||||
|
||||
void maven_init_TVdata
|
||||
(
|
||||
struct mavenregs* data
|
||||
)
|
||||
{
|
||||
static struct mavenregs palregs = { {
|
||||
0x2A, 0x09, 0x8A, 0xCB, /* 00: chroma subcarrier */
|
||||
0x00,
|
||||
0x00, /* ? not written */
|
||||
0x00, /* modified by code (F9 written...) */
|
||||
0x00, /* ? not written */
|
||||
0x7E, /* 08 */
|
||||
0x44, /* 09 */
|
||||
0x9C, /* 0A */
|
||||
0x2E, /* 0B */
|
||||
0x21, /* 0C */
|
||||
0x00, /* ? not written */
|
||||
0x3F, 0x03, /* 0E-0F */
|
||||
0x3F, 0x03, /* 10-11 */
|
||||
0x1A, /* 12 */
|
||||
0x2A, /* 13 */
|
||||
0x1C, 0x3D, 0x14, /* 14-16 */
|
||||
0x9C, 0x01, /* 17-18 */
|
||||
0x00, /* 19 */
|
||||
0xFE, /* 1A */
|
||||
0x7E, /* 1B */
|
||||
0x60, /* 1C */
|
||||
0x05, /* 1D */
|
||||
0x89, 0x03, /* 1E-1F */
|
||||
0x72, /* 20 */
|
||||
0x07, /* 21 */
|
||||
0x72, /* 22 */
|
||||
0x00, /* 23 */
|
||||
0x00, /* 24 */
|
||||
0x00, /* 25 */
|
||||
0x08, /* 26 */
|
||||
0x04, /* 27 */
|
||||
0x00, /* 28 */
|
||||
0x1A, /* 29 */
|
||||
0x55, 0x01, /* 2A-2B */
|
||||
0x26, /* 2C */
|
||||
0x07, 0x7E, /* 2D-2E */
|
||||
0x02, 0x54, /* 2F-30 */
|
||||
0xB0, 0x00, /* 31-32 */
|
||||
0x14, /* 33 */
|
||||
0x49, /* 34 */
|
||||
0x00, /* 35 written multiple times */
|
||||
0x00, /* 36 not written */
|
||||
0xA3, /* 37 */
|
||||
0xC8, /* 38 */
|
||||
0x22, /* 39 */
|
||||
0x02, /* 3A */
|
||||
0x22, /* 3B */
|
||||
0x3F, 0x03, /* 3C-3D */
|
||||
0x00, /* 3E written multiple times */
|
||||
0x00, /* 3F not written */
|
||||
}, MODE_PAL, 625, 50 };
|
||||
static struct mavenregs ntscregs = { {
|
||||
0x21, 0xF0, 0x7C, 0x1F, /* 00: chroma subcarrier */
|
||||
0x00,
|
||||
0x00, /* ? not written */
|
||||
0x00, /* modified by code (F9 written...) */
|
||||
0x00, /* ? not written */
|
||||
0x7E, /* 08 */
|
||||
0x43, /* 09 */
|
||||
0x7E, /* 0A */
|
||||
0x3D, /* 0B */
|
||||
0x00, /* 0C */
|
||||
0x00, /* ? not written */
|
||||
0x41, 0x00, /* 0E-0F */
|
||||
0x3C, 0x00, /* 10-11 */
|
||||
0x17, /* 12 */
|
||||
0x21, /* 13 */
|
||||
0x1B, 0x1B, 0x24, /* 14-16 */
|
||||
0x83, 0x01, /* 17-18 */
|
||||
0x00, /* 19 */
|
||||
0x0F, /* 1A */
|
||||
0x0F, /* 1B */
|
||||
0x60, /* 1C */
|
||||
0x05, /* 1D */
|
||||
0x89, 0x02, /* 1E-1F */
|
||||
0x5F, /* 20 */
|
||||
0x04, /* 21 */
|
||||
0x5F, /* 22 */
|
||||
0x01, /* 23 */
|
||||
0x02, /* 24 */
|
||||
0x00, /* 25 */
|
||||
0x0A, /* 26 */
|
||||
0x05, /* 27 */
|
||||
0x00, /* 28 */
|
||||
0x10, /* 29 */
|
||||
0xFF, 0x03, /* 2A-2B */
|
||||
0x24, /* 2C */
|
||||
0x0F, 0x78, /* 2D-2E */
|
||||
0x00, 0x00, /* 2F-30 */
|
||||
0xB2, 0x04, /* 31-32 */
|
||||
0x14, /* 33 */
|
||||
0x02, /* 34 */
|
||||
0x00, /* 35 written multiple times */
|
||||
0x00, /* 36 not written */
|
||||
0xA3, /* 37 */
|
||||
0xC8, /* 38 */
|
||||
0x15, /* 39 */
|
||||
0x05, /* 3A */
|
||||
0x3B, /* 3B */
|
||||
0x3C, 0x00, /* 3C-3D */
|
||||
0x00, /* 3E written multiple times */
|
||||
0x00, /* never written */
|
||||
}, MODE_NTSC, 525, 60 };
|
||||
|
||||
if (mode & MODE_PAL)
|
||||
*data = palregs;
|
||||
else
|
||||
*data = ntscregs;
|
||||
|
||||
data->regs[0x93] = 0xA2;
|
||||
|
||||
/* gamma correction registers */
|
||||
data->regs[0x83] = 0x00;
|
||||
data->regs[0x84] = 0x00;
|
||||
data->regs[0x85] = 0x00;
|
||||
data->regs[0x86] = 0x1F;
|
||||
data->regs[0x87] = 0x10;
|
||||
data->regs[0x88] = 0x10;
|
||||
data->regs[0x89] = 0x10;
|
||||
data->regs[0x8A] = 0x64; /* 100 */
|
||||
data->regs[0x8B] = 0xC8; /* 200 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#define LR(x) i2c_maven_write((x), m->regs[(x)])
|
||||
#define LRP(x) MAVWWP((x), (m->regs[(x)]|m->regs[(x+1)]<<8))
|
||||
void maven_init_TV
|
||||
(
|
||||
const struct mavenregs* m
|
||||
)
|
||||
{
|
||||
int val;
|
||||
|
||||
|
||||
i2c_maven_write( 0x3E, 0x01);
|
||||
i2c_maven_read( 0x82); /* fetch oscillator state? */
|
||||
i2c_maven_write( 0x8C, 0x00);
|
||||
i2c_maven_read( 0x94); /* get 0x82 */
|
||||
i2c_maven_write( 0x94, 0xA2);
|
||||
/* xmiscctrl */
|
||||
|
||||
MAVWWP(0x8E, 0x1EFF);
|
||||
i2c_maven_write( 0xC6, 0x01);
|
||||
|
||||
/* removed code... */
|
||||
|
||||
i2c_maven_read( 0x06);
|
||||
i2c_maven_write( 0x06, 0xF9); /* or read |= 0xF0 ? */
|
||||
|
||||
/* removed code here... */
|
||||
|
||||
/* real code begins here? */
|
||||
/* chroma subcarrier */
|
||||
LR(0x00); LR(0x01); LR(0x02); LR(0x03);
|
||||
|
||||
LR(0x04);
|
||||
|
||||
LR(0x2C);
|
||||
LR(0x08);
|
||||
LR(0x0A);
|
||||
LR(0x09);
|
||||
LR(0x29);
|
||||
LRP(0x31);
|
||||
LRP(0x17);
|
||||
LR(0x0B);
|
||||
LR(0x0C);
|
||||
if (m->mode & MODE_PAL) {
|
||||
i2c_maven_write( 0x35, 0x10); /* ... */
|
||||
} else {
|
||||
i2c_maven_write( 0x35, 0x0F); /* ... */
|
||||
}
|
||||
|
||||
LRP(0x10);
|
||||
|
||||
LRP(0x0E);
|
||||
LRP(0x1E);
|
||||
|
||||
LR(0x20); /* saturation #1 */
|
||||
LR(0x22); /* saturation #2 */
|
||||
LR(0x25); /* hue */
|
||||
LR(0x34);
|
||||
LR(0x33);
|
||||
LR(0x19);
|
||||
LR(0x12);
|
||||
LR(0x3B);
|
||||
LR(0x13);
|
||||
LR(0x39);
|
||||
LR(0x1D);
|
||||
LR(0x3A);
|
||||
LR(0x24);
|
||||
LR(0x14);
|
||||
LR(0x15);
|
||||
LR(0x16);
|
||||
LRP(0x2D);
|
||||
LRP(0x2F);
|
||||
LR(0x1A);
|
||||
LR(0x1B);
|
||||
LR(0x1C);
|
||||
LR(0x23);
|
||||
LR(0x26);
|
||||
LR(0x28);
|
||||
LR(0x27);
|
||||
LR(0x21);
|
||||
LRP(0x2A);
|
||||
if (m->mode & MODE_PAL)
|
||||
i2c_maven_write( 0x35, 0x1D); /* ... */
|
||||
else
|
||||
i2c_maven_write( 0x35, 0x1C);
|
||||
|
||||
LRP(0x3C);
|
||||
LR(0x37);
|
||||
LR(0x38);
|
||||
i2c_maven_write( 0xB3, 0x01);
|
||||
|
||||
i2c_maven_read( 0xB0); /* read 0x80 */
|
||||
i2c_maven_write( 0xB0, 0x08); /* ugh... */
|
||||
i2c_maven_read( 0xB9); /* read 0x7C */
|
||||
i2c_maven_write( 0xB9, 0x78);
|
||||
i2c_maven_read( 0xBF); /* read 0x00 */
|
||||
i2c_maven_write( 0xBF, 0x02);
|
||||
i2c_maven_read( 0x94); /* read 0x82 */
|
||||
i2c_maven_write( 0x94, 0xB3);
|
||||
|
||||
LR(0x80); /* 04 1A 91 or 05 21 91 */
|
||||
LR(0x81);
|
||||
LR(0x82);
|
||||
|
||||
i2c_maven_write( 0x8C, 0x20);
|
||||
i2c_maven_read( 0x8D);
|
||||
i2c_maven_write( 0x8D, 0x10);
|
||||
|
||||
LR(0x90); /* 4D 50 52 or 4E 05 45 */
|
||||
LR(0x91);
|
||||
LR(0x92);
|
||||
|
||||
LRP(0x9A); /* 0049 or 004F */
|
||||
LRP(0x9C); /* 0004 or 0004 */
|
||||
LRP(0x9E); /* 0458 or 045E */
|
||||
LRP(0xA0); /* 05DA or 051B */
|
||||
LRP(0xA2); /* 00CC or 00CF */
|
||||
LRP(0xA4); /* 007D or 007F */
|
||||
LRP(0xA6); /* 007C or 007E */
|
||||
LRP(0xA8); /* 03CB or 03CE */
|
||||
LRP(0x98); /* 0000 or 0000 */
|
||||
LRP(0xAE); /* 0044 or 003A */
|
||||
LRP(0x96); /* 05DA or 051B */
|
||||
LRP(0xAA); /* 04BC or 046A */
|
||||
LRP(0xAC); /* 004D or 004E */
|
||||
|
||||
LR(0xBE);
|
||||
LR(0xC2);
|
||||
|
||||
i2c_maven_read( 0x8D);
|
||||
i2c_maven_write( 0x8D, 0x00);
|
||||
|
||||
LR(0x20); /* saturation #1 */
|
||||
LR(0x22); /* saturation #2 */
|
||||
LR(0x93); /* whoops */
|
||||
LR(0x20); /* oh, saturation #1 again */
|
||||
LR(0x22); /* oh, saturation #2 again */
|
||||
LR(0x25); /* hue */
|
||||
LRP(0x0E);
|
||||
LRP(0x1E);
|
||||
LRP(0x0E); /* problems with memory? */
|
||||
LRP(0x1E); /* yes, matrox must have problems in memory area... */
|
||||
|
||||
/* load gamma correction stuff */
|
||||
LR(0x83);
|
||||
LR(0x84);
|
||||
LR(0x85);
|
||||
LR(0x86);
|
||||
LR(0x87);
|
||||
LR(0x88);
|
||||
LR(0x89);
|
||||
LR(0x8A);
|
||||
LR(0x8B);
|
||||
|
||||
val = i2c_maven_read( 0x8D);
|
||||
val &= 0x10; /* 0x10 or anything ored with it */
|
||||
i2c_maven_write( 0x8D, val);
|
||||
|
||||
LR(0x33);
|
||||
LR(0x19);
|
||||
LR(0x12);
|
||||
LR(0x3B);
|
||||
LR(0x13);
|
||||
LR(0x39);
|
||||
LR(0x1D);
|
||||
LR(0x3A);
|
||||
LR(0x24);
|
||||
LR(0x14);
|
||||
LR(0x15);
|
||||
LR(0x16);
|
||||
LRP(0x2D);
|
||||
LRP(0x2F);
|
||||
LR(0x1A);
|
||||
LR(0x1B);
|
||||
LR(0x1C);
|
||||
LR(0x23);
|
||||
LR(0x26);
|
||||
LR(0x28);
|
||||
LR(0x27);
|
||||
LR(0x21);
|
||||
LRP(0x2A);
|
||||
if (m->mode & MODE_PAL)
|
||||
i2c_maven_write( 0x35, 0x1D);
|
||||
else
|
||||
i2c_maven_write( 0x35, 0x1C);
|
||||
LRP(0x3C);
|
||||
LR(0x37);
|
||||
LR(0x38);
|
||||
|
||||
i2c_maven_read( 0xB0);
|
||||
LR(0xB0); /* output mode */
|
||||
LR(0x90);
|
||||
LR(0xBE);
|
||||
LR(0xC2);
|
||||
|
||||
LRP(0x9A);
|
||||
LRP(0xA2);
|
||||
LRP(0x9E);
|
||||
LRP(0xA6);
|
||||
LRP(0xAA);
|
||||
LRP(0xAC);
|
||||
i2c_maven_write( 0x3E, 0x00);
|
||||
i2c_maven_write( 0x95, 0x20);
|
||||
}
|
||||
|
||||
int maven_find_exact_clocks(unsigned int ht, unsigned int vt,
|
||||
struct mavenregs* m) {
|
||||
unsigned int x;
|
||||
unsigned int err = ~0;
|
||||
|
||||
/* 1:1 */
|
||||
m->regs[0x80] = 0x0F;
|
||||
m->regs[0x81] = 0x07;
|
||||
m->regs[0x82] = 0x81;
|
||||
|
||||
for (x = 0; x < 8; x++) {
|
||||
unsigned int a, b, c, h2;
|
||||
unsigned int h = ht + 2 + x;
|
||||
|
||||
if (!matroxfb_mavenclock((m->mode & MODE_PAL) ? &maven_PAL : &maven_NTSC, h, vt, &a, &b, &c, &h2)) {
|
||||
unsigned int diff = h - h2;
|
||||
|
||||
if (diff < err) {
|
||||
err = diff;
|
||||
m->regs[0x80] = a - 1;
|
||||
m->regs[0x81] = b - 1;
|
||||
m->regs[0x82] = c | 0x80;
|
||||
m->hcorr = h2 - 2;
|
||||
m->htotal = h - 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return err != ~0U;
|
||||
}
|
||||
|
||||
//called from main access points...
|
||||
inline int maven_compute_timing
|
||||
(
|
||||
struct my_timming* mt,
|
||||
struct mavenregs* m
|
||||
)
|
||||
{
|
||||
unsigned int tmpi;
|
||||
unsigned int a, bv, c;
|
||||
|
||||
m->mode = mode;
|
||||
if (MODE_TV(mode)) {
|
||||
unsigned int lmargin;
|
||||
unsigned int umargin;
|
||||
unsigned int vslen;
|
||||
unsigned int hcrt;
|
||||
unsigned int slen;
|
||||
|
||||
maven_init_TVdata(m);
|
||||
|
||||
if (maven_find_exact_clocks(mt->HTotal, mt->VTotal, m) == 0)
|
||||
return -EINVAL;
|
||||
|
||||
lmargin = mt->HTotal - mt->HSyncEnd;
|
||||
slen = mt->HSyncEnd - mt->HSyncStart;
|
||||
hcrt = mt->HTotal - slen - mt->delay;
|
||||
umargin = mt->VTotal - mt->VSyncEnd;
|
||||
vslen = mt->VSyncEnd - mt->VSyncStart;
|
||||
|
||||
if (m->hcorr < mt->HTotal)
|
||||
hcrt += m->hcorr;
|
||||
if (hcrt > mt->HTotal)
|
||||
hcrt -= mt->HTotal;
|
||||
if (hcrt + 2 > mt->HTotal)
|
||||
hcrt = 0; /* or issue warning? */
|
||||
|
||||
/* last (first? middle?) line in picture can have different length */
|
||||
/* hlen - 2 */
|
||||
m->regs[0x96] = m->hcorr;
|
||||
m->regs[0x97] = m->hcorr >> 8;
|
||||
/* ... */
|
||||
m->regs[0x98] = 0x00; m->regs[0x99] = 0x00;
|
||||
/* hblanking end */
|
||||
m->regs[0x9A] = lmargin; /* 100% */
|
||||
m->regs[0x9B] = lmargin >> 8; /* 100% */
|
||||
/* who knows */
|
||||
m->regs[0x9C] = 0x04;
|
||||
m->regs[0x9D] = 0x00;
|
||||
/* htotal - 2 */
|
||||
m->regs[0xA0] = m->htotal;
|
||||
m->regs[0xA1] = m->htotal >> 8;
|
||||
/* vblanking end */
|
||||
m->regs[0xA2] = mt->VTotal - mt->VSyncStart - 1; /* stop vblanking */
|
||||
m->regs[0xA3] = (mt->VTotal - mt->VSyncStart - 1) >> 8;
|
||||
/* something end... [A6]+1..[A8] */
|
||||
m->regs[0xA4] = 0x01;
|
||||
m->regs[0xA5] = 0x00;
|
||||
/* something start... 0..[A4]-1 */
|
||||
m->regs[0xA6] = 0x00;
|
||||
m->regs[0xA7] = 0x00;
|
||||
/* vertical line count - 1 */
|
||||
m->regs[0xA8] = mt->VTotal - 1;
|
||||
m->regs[0xA9] = (mt->VTotal - 1) >> 8;
|
||||
/* horizontal vidrst pos */
|
||||
m->regs[0xAA] = hcrt; /* 0 <= hcrt <= htotal - 2 */
|
||||
m->regs[0xAB] = hcrt >> 8;
|
||||
/* vertical vidrst pos */
|
||||
m->regs[0xAC] = mt->VTotal - 2;
|
||||
m->regs[0xAD] = (mt->VTotal - 2) >> 8;
|
||||
/* moves picture up/down and so on... */
|
||||
m->regs[0xAE] = 0x01; /* Fix this... 0..VTotal */
|
||||
m->regs[0xAF] = 0x00;
|
||||
{
|
||||
int hdec;
|
||||
int hlen;
|
||||
unsigned int ibmin = 4 + lmargin + mt->HDisplay;
|
||||
unsigned int ib;
|
||||
int i;
|
||||
|
||||
/* Verify! */
|
||||
/* Where 94208 came from? */
|
||||
if (mt->HTotal)
|
||||
hdec = 94208 / (mt->HTotal);
|
||||
else
|
||||
hdec = 0x81;
|
||||
if (hdec > 0x81)
|
||||
hdec = 0x81;
|
||||
if (hdec < 0x41)
|
||||
hdec = 0x41;
|
||||
hdec--;
|
||||
hlen = 98304 - 128 - ((lmargin + mt->HDisplay - 8) * hdec);
|
||||
if (hlen < 0)
|
||||
hlen = 0;
|
||||
hlen = hlen >> 8;
|
||||
if (hlen > 0xFF)
|
||||
hlen = 0xFF;
|
||||
/* Now we have to compute input buffer length.
|
||||
If you want any picture, it must be between
|
||||
4 + lmargin + xres
|
||||
and
|
||||
94208 / hdec
|
||||
If you want perfect picture even on the top
|
||||
of screen, it must be also
|
||||
0x3C0000 * i / hdec + Q - R / hdec
|
||||
where
|
||||
R Qmin Qmax
|
||||
0x07000 0x5AE 0x5BF
|
||||
0x08000 0x5CF 0x5FF
|
||||
0x0C000 0x653 0x67F
|
||||
0x10000 0x6F8 0x6FF
|
||||
*/
|
||||
i = 1;
|
||||
do {
|
||||
ib = ((0x3C0000 * i - 0x8000)/ hdec + 0x05E7) >> 8;
|
||||
i++;
|
||||
} while (ib < ibmin);
|
||||
if (ib >= m->htotal + 2) {
|
||||
ib = ibmin;
|
||||
}
|
||||
|
||||
m->regs[0x90] = hdec; /* < 0x40 || > 0x80 is bad... 0x80 is questionable */
|
||||
m->regs[0xC2] = hlen;
|
||||
/* 'valid' input line length */
|
||||
m->regs[0x9E] = ib;
|
||||
m->regs[0x9F] = ib >> 8;
|
||||
}
|
||||
{
|
||||
int vdec;
|
||||
int vlen;
|
||||
|
||||
if (mt->VTotal) {
|
||||
double f1;
|
||||
uint32 a;
|
||||
uint32 b;
|
||||
|
||||
// Unsure of how to do 64-bit integer maths on Be, so use FPU!
|
||||
a = m->vlines * (m->htotal + 2);
|
||||
b = (mt->VTotal - 1) * (m->htotal + 2) + m->hcorr + 2;
|
||||
f1 = (double)a * (double)32768;
|
||||
f1 /= (double) b;
|
||||
vdec = (uint32) f1;
|
||||
} else
|
||||
vdec = 0x8000;
|
||||
if (vdec > 0x8000)
|
||||
vdec = 0x8000;
|
||||
vlen = (vslen + umargin + mt->VDisplay) * vdec;
|
||||
vlen = (vlen >> 16) - 146; /* FIXME: 146?! */
|
||||
if (vlen < 0)
|
||||
vlen = 0;
|
||||
if (vlen > 0xFF)
|
||||
vlen = 0xFF;
|
||||
vdec--;
|
||||
m->regs[0x91] = vdec;
|
||||
m->regs[0x92] = vdec >> 8;
|
||||
m->regs[0xBE] = vlen;
|
||||
}
|
||||
m->regs[0xB0] = 0x08; /* output: SVideo/Composite */
|
||||
return 0;
|
||||
}
|
||||
|
||||
DAC1064_calcclock(mt->pixclock, 450000, &a, &bv, &c);
|
||||
m->regs[0x80] = a;
|
||||
m->regs[0x81] = bv;
|
||||
m->regs[0x82] = c | 0x80;
|
||||
|
||||
m->regs[0xB3] = 0x01;
|
||||
m->regs[0x94] = 0xB2;
|
||||
|
||||
/* htotal... */
|
||||
m->regs[0x96] = mt->HTotal;
|
||||
m->regs[0x97] = mt->HTotal >> 8;
|
||||
/* ?? */
|
||||
m->regs[0x98] = 0x00;
|
||||
m->regs[0x99] = 0x00;
|
||||
/* hsync len */
|
||||
tmpi = mt->HSyncEnd - mt->HSyncStart;
|
||||
m->regs[0x9A] = tmpi;
|
||||
m->regs[0x9B] = tmpi >> 8;
|
||||
/* hblank end */
|
||||
tmpi = mt->HTotal - mt->HSyncStart;
|
||||
m->regs[0x9C] = tmpi;
|
||||
m->regs[0x9D] = tmpi >> 8;
|
||||
/* hblank start */
|
||||
tmpi += mt->HDisplay;
|
||||
m->regs[0x9E] = tmpi;
|
||||
m->regs[0x9F] = tmpi >> 8;
|
||||
/* htotal + 1 */
|
||||
tmpi = mt->HTotal + 1;
|
||||
m->regs[0xA0] = tmpi;
|
||||
m->regs[0xA1] = tmpi >> 8;
|
||||
/* vsync?! */
|
||||
tmpi = mt->VSyncEnd - mt->VSyncStart - 1;
|
||||
m->regs[0xA2] = tmpi;
|
||||
m->regs[0xA3] = tmpi >> 8;
|
||||
/* ignored? */
|
||||
tmpi = mt->VTotal - mt->VSyncStart;
|
||||
m->regs[0xA4] = tmpi;
|
||||
m->regs[0xA5] = tmpi >> 8;
|
||||
/* ignored? */
|
||||
tmpi = mt->VTotal - 1;
|
||||
m->regs[0xA6] = tmpi;
|
||||
m->regs[0xA7] = tmpi >> 8;
|
||||
/* vtotal - 1 */
|
||||
m->regs[0xA8] = tmpi;
|
||||
m->regs[0xA9] = tmpi >> 8;
|
||||
/* hor vidrst */
|
||||
tmpi = mt->HTotal - mt->delay;
|
||||
m->regs[0xAA] = tmpi;
|
||||
m->regs[0xAB] = tmpi >> 8;
|
||||
/* vert vidrst */
|
||||
tmpi = mt->VTotal - 2;
|
||||
m->regs[0xAC] = tmpi;
|
||||
m->regs[0xAD] = tmpi >> 8;
|
||||
/* ignored? */
|
||||
m->regs[0xAE] = 0x00;
|
||||
m->regs[0xAF] = 0x00;
|
||||
|
||||
m->regs[0xB0] = 0x03; /* output: monitor */
|
||||
m->regs[0xB1] = 0xA0; /* ??? */
|
||||
m->regs[0x8C] = 0x20; /* must be set... */
|
||||
m->regs[0x8D] = 0x00; /* defaults to 0x10: test signal */
|
||||
m->regs[0xB9] = 0x1A; /* defaults to 0x2C: too bright */
|
||||
m->regs[0xBF] = 0x22; /* makes picture stable */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int maven_program_timing
|
||||
(
|
||||
const struct mavenregs* m
|
||||
)
|
||||
{
|
||||
if (m->mode & MODE_MONITOR) {
|
||||
LR(0x80);
|
||||
LR(0x81);
|
||||
LR(0x82);
|
||||
|
||||
LR(0xB3);
|
||||
LR(0x94);
|
||||
|
||||
LRP(0x96);
|
||||
LRP(0x98);
|
||||
LRP(0x9A);
|
||||
LRP(0x9C);
|
||||
LRP(0x9E);
|
||||
LRP(0xA0);
|
||||
LRP(0xA2);
|
||||
LRP(0xA4);
|
||||
LRP(0xA6);
|
||||
LRP(0xA8);
|
||||
LRP(0xAA);
|
||||
LRP(0xAC);
|
||||
LRP(0xAE);
|
||||
|
||||
LR(0xB0); /* output: monitor */
|
||||
LR(0xB1); /* ??? */
|
||||
LR(0x8C); /* must be set... */
|
||||
LR(0x8D); /* defaults to 0x10: test signal */
|
||||
LR(0xB9); /* defaults to 0x2C: too bright */
|
||||
LR(0xBF); /* makes picture stable */
|
||||
} else {
|
||||
maven_init_TV(m);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int maven_resync()
|
||||
{
|
||||
i2c_maven_write( 0x95, 0x20); /* start whole thing */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//Main entry points... - sequence is compute, program, start
|
||||
int maven_set_mode(int mod)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case MODE_NTSC:
|
||||
case MODE_PAL:
|
||||
case MODE_MONITOR:
|
||||
mode = mod;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int maven_out_compute(struct my_timming* mt, struct mavenregs* maven)
|
||||
{
|
||||
return maven_compute_timing(mt, maven);
|
||||
}
|
||||
|
||||
int maven_out_program(const struct mavenregs* maven)
|
||||
{
|
||||
return maven_program_timing(maven);
|
||||
}
|
||||
|
||||
int maven_out_start()
|
||||
{
|
||||
return maven_resync();
|
||||
}
|
||||
|
||||
/* ************************** */
|
||||
//Used with Petr's permission (many thanks)
|
||||
//Any bugs with this code contact me ([email protected]) not Petr
|
||||
//-----------------------------------------------
|
||||
//MODULE_AUTHOR("(c) 1999,2000 Petr Vandrovec <[email protected]>");
|
||||
//MODULE_DESCRIPTION("Matrox G200/G400 Matrox MGA-TVO driver");
|
||||
@@ -1,88 +0,0 @@
|
||||
struct matrox_pll_features {
|
||||
unsigned int vco_freq_min;
|
||||
unsigned int ref_freq;
|
||||
unsigned int feed_div_min;
|
||||
unsigned int feed_div_max;
|
||||
unsigned int in_div_min;
|
||||
unsigned int in_div_max;
|
||||
unsigned int post_shift_max;
|
||||
};
|
||||
|
||||
struct matrox_pll_features2 {
|
||||
unsigned int vco_freq_min;
|
||||
unsigned int vco_freq_max;
|
||||
unsigned int feed_div_min;
|
||||
unsigned int feed_div_max;
|
||||
unsigned int in_div_min;
|
||||
unsigned int in_div_max;
|
||||
unsigned int post_shift_max;
|
||||
};
|
||||
|
||||
struct matrox_pll_ctl {
|
||||
unsigned int ref_freq;
|
||||
unsigned int den;
|
||||
};
|
||||
|
||||
struct mavenregs {
|
||||
uint8 regs[256];
|
||||
int mode;
|
||||
int vlines;
|
||||
int xtal;
|
||||
int fv;
|
||||
|
||||
uint16 htotal;
|
||||
uint16 hcorr;
|
||||
};
|
||||
|
||||
struct my_timming {
|
||||
unsigned int pixclock;
|
||||
unsigned int HDisplay;
|
||||
unsigned int HSyncStart;
|
||||
unsigned int HSyncEnd;
|
||||
unsigned int HTotal;
|
||||
unsigned int VDisplay;
|
||||
unsigned int VSyncStart;
|
||||
unsigned int VSyncEnd;
|
||||
unsigned int VTotal;
|
||||
unsigned int sync;
|
||||
int dblscan;
|
||||
int interlaced;
|
||||
unsigned int delay; /* CRTC delay */
|
||||
};
|
||||
|
||||
int matroxfb_PLL_mavenclock(const struct matrox_pll_features2* pll,
|
||||
const struct matrox_pll_ctl* ctl,
|
||||
unsigned int htotal, unsigned int vtotal,
|
||||
unsigned int* in, unsigned int* feed, unsigned int* post,
|
||||
unsigned int* h2);
|
||||
|
||||
unsigned int matroxfb_mavenclock(const struct matrox_pll_ctl* ctl,
|
||||
unsigned int htotal, unsigned int vtotal,
|
||||
unsigned int* in, unsigned int* feed, unsigned int* post,
|
||||
unsigned int* htotal2);
|
||||
|
||||
void DAC1064_calcclock(unsigned int freq, unsigned int fmax,
|
||||
unsigned int* in, unsigned int* feed, unsigned int* post);
|
||||
|
||||
void maven_init_TVdata ( struct mavenregs* data);
|
||||
void maven_init_TV ( const struct mavenregs* m);
|
||||
|
||||
int maven_find_exact_clocks(unsigned int ht, unsigned int vt,
|
||||
struct mavenregs* m);
|
||||
|
||||
int maven_compute_timing ( struct my_timming* mt, struct mavenregs* m) ;
|
||||
|
||||
|
||||
int maven_program_timing ( const struct mavenregs* m);
|
||||
|
||||
int maven_resync();
|
||||
|
||||
|
||||
//MY INTERFACE
|
||||
int maven_set_mode(int mode);
|
||||
|
||||
int maven_out_compute(struct my_timming* mt, struct mavenregs* mr) ;
|
||||
|
||||
int maven_out_program(const struct mavenregs* mr) ;
|
||||
|
||||
int maven_out_start() ;
|
||||
@@ -1,7 +1,7 @@
|
||||
/* MGA Acceleration functions */
|
||||
/* Authors:
|
||||
Mark Watson 2/2000,
|
||||
Rudolf Cornelissen 10-12/2002
|
||||
Rudolf Cornelissen 10/2002-4/2003.
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00080000
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
/*acceleration notes*/
|
||||
|
||||
/*functions Be needs:
|
||||
/*functions Be's app_server uses:
|
||||
fill span (horizontal only)
|
||||
fill rectangle (these 2 are very similar)
|
||||
invert rectangle
|
||||
@@ -19,12 +19,14 @@ 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 MIL2 in 800x600 8bpp
|
||||
/* needed by MIL 1/2 because of adress linearisation constraints */
|
||||
#define ACCW_YDSTLEN(dst, len) do { \
|
||||
/* if (si->ylin) { */ \
|
||||
if ((si->ps.card_type==MIL2) && (si->dm.space==B_CMAP8)) { \
|
||||
ACCW(YDST,((dst)*si->dm.virtual_width) >> 5); \
|
||||
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)
|
||||
@@ -39,52 +41,120 @@ status_t gx00_acc_wait_idle()
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*AFAIK this must be done for every new screenmode*/
|
||||
/* AFAIK this must be done for every new screenmode.
|
||||
* Engine required init. */
|
||||
status_t gx00_acc_init()
|
||||
{
|
||||
ACCW(OPMODE,0); // cleanup bitblt
|
||||
/* used for convenience: MACCESS is a write only register! */
|
||||
uint32 maccess = 0x00000000;
|
||||
/* if we were unable to read PINS, we have to assume something (keeping bit6 zero) */
|
||||
if ((si->ps.card_type >= G450) && (si->ps.pins_status = B_OK))
|
||||
{
|
||||
/* b7 v5_mem_type = done by Mark Watson. fixme: still confirm! (unknown bits) */
|
||||
maccess |= ((((uint32)si->ps.v5_mem_type) & 0x80) >> 1);
|
||||
}
|
||||
|
||||
/* 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) */
|
||||
if (si->ps.card_type>=G100) ACCW(ZORG,0);
|
||||
ACCW(ZORG,0);
|
||||
|
||||
/* Set pixel width */
|
||||
switch(si->dm.space)
|
||||
{
|
||||
case B_CMAP8:
|
||||
ACCW(MACCESS, ((ACCR(MACCESS) & 0xfffffffc) | 0x00));
|
||||
ACCW(MACCESS, ((maccess & 0xfffffffc) | 0x00));
|
||||
depth = 8;
|
||||
break;
|
||||
case B_RGB15_LITTLE:case B_RGB16_LITTLE:
|
||||
ACCW(MACCESS, ((ACCR(MACCESS) & 0xfffffffc) | 0x01));
|
||||
ACCW(MACCESS, ((maccess & 0xfffffffc) | 0x01));
|
||||
depth = 16;
|
||||
break;
|
||||
case B_RGB32_LITTLE:case B_RGBA32_LITTLE:
|
||||
ACCW(MACCESS, ((ACCR(MACCESS) & 0xfffffffc) | 0x02));
|
||||
ACCW(MACCESS, ((maccess & 0xfffffffc) | 0x02));
|
||||
depth = 32;
|
||||
break;
|
||||
default:
|
||||
LOG(8,("ACC: init, invalid bit depth\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/*PITCH*/
|
||||
// TODO apsed 3-129 32 or 64 following depth (or 128 if MIl2)
|
||||
if (si->dm.virtual_width&0x1F)
|
||||
/* setup PITCH: very cardtype specific! */
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
LOG(8,("ACC: can not accelerate, pitch is not multiple of 32 pixels\n"));
|
||||
return B_ERROR;
|
||||
case MIL1:
|
||||
switch (si->fbc.bytes_per_row / (depth >> 3))
|
||||
{
|
||||
case 640:
|
||||
case 768:
|
||||
case 800:
|
||||
case 960:
|
||||
case 1024:
|
||||
case 1152:
|
||||
case 1280:
|
||||
case 1600:
|
||||
case 1920:
|
||||
case 2048:
|
||||
/* we are using hardware adress linearisation */
|
||||
break;
|
||||
default:
|
||||
/* we are using software adress linearisation */
|
||||
y_lin = 0x01;
|
||||
LOG(8,("ACC: using software adress linearisation\n"));
|
||||
break;
|
||||
}
|
||||
ACCW(PITCH, (y_lin << 15) | ((si->fbc.bytes_per_row / (depth >> 3)) & 0x0FFF));
|
||||
break;
|
||||
case MIL2:
|
||||
switch (si->fbc.bytes_per_row / (depth >> 3))
|
||||
{
|
||||
case 512:
|
||||
case 640:
|
||||
case 768:
|
||||
case 800:
|
||||
case 832:
|
||||
case 960:
|
||||
case 1024:
|
||||
case 1152:
|
||||
case 1280:
|
||||
case 1600:
|
||||
case 1664:
|
||||
case 1920:
|
||||
case 2048:
|
||||
/* we are using hardware adress linearisation */
|
||||
break;
|
||||
default:
|
||||
/* we are using software adress linearisation */
|
||||
y_lin = 0x01;
|
||||
LOG(8,("ACC: using software adress linearisation\n"));
|
||||
break;
|
||||
}
|
||||
ACCW(PITCH, (y_lin << 15) | ((si->fbc.bytes_per_row / (depth >> 3)) & 0x0FFF));
|
||||
break;
|
||||
case G100:
|
||||
/* always using hardware adress linearisation, because 2D/3D
|
||||
* engine works on every pitch multiple of 32 */
|
||||
ACCW(PITCH, ((si->fbc.bytes_per_row / (depth >> 3)) & 0x0FFF));
|
||||
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;
|
||||
}
|
||||
if (si->ps.card_type>=G200)
|
||||
ACCW(PITCH,(si->dm.virtual_width)&0x1FFF); /* use hardware Y decoding */
|
||||
else
|
||||
ACCW(PITCH,(si->dm.virtual_width)&0x0FFF); /* use hardware Y decoding */
|
||||
|
||||
if ((si->ps.card_type==MIL2) && (si->dm.space==B_CMAP8)) {
|
||||
// ylin shall be 1 if 800x600
|
||||
ACCW(PITCH, (1<<15) | (si->dm.virtual_width&0x0FFF));
|
||||
}
|
||||
/* 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) {
|
||||
if (si->ps.card_type >= G200) {
|
||||
/*DSTORG - location of active screen in framebuffer*/
|
||||
ACCW(DSTORG,(si->fbc.frame_buffer)-(si->framebuffer));
|
||||
|
||||
@@ -92,11 +162,12 @@ if ((si->ps.card_type==MIL2) && (si->dm.space==B_CMAP8)) {
|
||||
ACCW(SRCORG,(si->fbc.frame_buffer)-(si->framebuffer));
|
||||
}
|
||||
|
||||
/* init YDSTORG - apsed, if not inited, BitBlts may fails on g200 */
|
||||
/* 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 */
|
||||
/* <= 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)
|
||||
@@ -120,25 +191,27 @@ if ((si->ps.card_type==MIL2) && (si->dm.space==B_CMAP8)) {
|
||||
|
||||
/* clipping */
|
||||
/* i.e. highest and lowest X pixel adresses */
|
||||
ACCW(CXBNDRY,((si->dm.virtual_width - 1) << 16) | (0));
|
||||
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->dm.virtual_width) + src_dst);
|
||||
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*/
|
||||
/* screen to screen blit - i.e. move windows around.
|
||||
* Engine function bitblit, paragraph 4.5.7.2 */
|
||||
status_t gx00_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->dm.virtual_width;
|
||||
offset = (si->fbc.bytes_per_row / (depth >> 3));
|
||||
|
||||
t_end = t_start = xs + (offset*ys) + src_dst;
|
||||
t_end += w;
|
||||
@@ -146,6 +219,9 @@ status_t gx00_acc_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint16 w,uint16 h
|
||||
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))
|
||||
{
|
||||
@@ -189,12 +265,13 @@ status_t gx00_acc_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint16 w,uint16 h
|
||||
ACCW(FXBNDRY,((xd+w)<<16)|xd);
|
||||
|
||||
/*do the blit*/
|
||||
ACCGO(DWGCTL,0x040C4018);
|
||||
ACCGO(DWGCTL,0x040C4018); // atype RSTR
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*screen to screen tranparent blit - not sure what uses this...*/
|
||||
/* screen to screen tranparent blit - not sure what uses this.
|
||||
* Engine function bitblit, paragraph 4.5.7.2 */
|
||||
status_t gx00_acc_transparent_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint16 w,uint16 h,uint32 colour)
|
||||
{
|
||||
uint32 t_start,t_end,offset;
|
||||
@@ -203,7 +280,7 @@ status_t gx00_acc_transparent_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint1
|
||||
return B_ERROR;
|
||||
|
||||
/*find where the top,bottom and offset are*/
|
||||
offset = si->dm.virtual_width;
|
||||
offset = (si->fbc.bytes_per_row / (depth >> 3));
|
||||
|
||||
t_end = t_start = xs + (offset*ys) + src_dst;
|
||||
t_end += w;
|
||||
@@ -211,6 +288,9 @@ status_t gx00_acc_transparent_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint1
|
||||
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))
|
||||
{
|
||||
@@ -256,11 +336,12 @@ status_t gx00_acc_transparent_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint1
|
||||
/*do the blit*/
|
||||
ACCW(FCOL,colour);
|
||||
ACCW(BCOL,0xffffffff);
|
||||
ACCGO(DWGCTL,0x440C4018);
|
||||
ACCGO(DWGCTL,0x440C4018); // atype RSTR
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*rectangle fill*/
|
||||
/* rectangle fill.
|
||||
* Engine function rectangle_fill: paragraph 4.5.5.2 */
|
||||
/*colorIndex,fill_rect_params,count*/
|
||||
status_t gx00_acc_rectangle(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint32 col)
|
||||
{
|
||||
@@ -276,6 +357,9 @@ status_t gx00_acc_rectangle(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint32 col)
|
||||
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 || si->ps.sdram)
|
||||
{
|
||||
ACCGO(DWGCTL,0x400C7814); // atype RSTR
|
||||
@@ -287,7 +371,8 @@ status_t gx00_acc_rectangle(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint32 col)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*rectangle invert*/
|
||||
/* rectangle invert.
|
||||
* Engine function rectangle_fill: paragraph 4.5.5.2 */
|
||||
/*colorIndex,fill_rect_params,count*/
|
||||
status_t gx00_acc_rectangle_invert(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint32 col)
|
||||
{
|
||||
@@ -306,7 +391,8 @@ status_t gx00_acc_rectangle_invert(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint3
|
||||
ACCW_YDSTLEN(ys,yl); /*set y start and length*/
|
||||
ACCW(FCOL,col); /*set colour*/
|
||||
|
||||
ACCGO(DWGCTL,0x40057814); /*draw it! top nibble is c is clipping enabled*/
|
||||
/*draw it! top nibble is c is clipping enabled*/
|
||||
ACCGO(DWGCTL,0x40057814); // atype RSTR
|
||||
|
||||
/*pseudo_dma version!*/
|
||||
//MGAACC_DWGCTL =0x1C00,
|
||||
@@ -339,3 +425,14 @@ status_t gx00_acc_rectangle_invert(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint3
|
||||
|
||||
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 gx00_acc_video_blit(uint16 xs,uint16 ys,uint16 ws, uint16 hs,
|
||||
uint16 xd,uint16 yd,uint16 wd,uint16 hd)
|
||||
{
|
||||
//fixme: implement. Used for G450/G550 Desktop TVout...
|
||||
//fixme: see if MIL1 - G200 support this function as well...
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
/* G200-G550 Back End Scaler functions */
|
||||
/* Written by Rudolf Cornelissen 05/11-2002 */
|
||||
/* Written by Rudolf Cornelissen 05/2002-04/2003 */
|
||||
|
||||
#define MODULE_BIT 0x00000200
|
||||
|
||||
#include "mga_std.h"
|
||||
|
||||
//fixme: implement: (used for virtual screens!)
|
||||
//void move_overlay(uint16 hdisp_start, uint16 vdisp_start);
|
||||
|
||||
status_t gx00_configure_bes
|
||||
(const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov, int offset)
|
||||
{
|
||||
@@ -29,7 +32,7 @@ status_t gx00_configure_bes
|
||||
/* misc used variables */
|
||||
uint16 temp1, temp2;
|
||||
/* interval representation, used for scaling calculations */
|
||||
uint16 intrep;
|
||||
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 */
|
||||
@@ -84,6 +87,20 @@ status_t gx00_configure_bes
|
||||
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;
|
||||
/* make dualhead switch mode with TVout enabled work while we're at it.. */
|
||||
if (si->switched_crtcs)
|
||||
{
|
||||
crtc_hstart += si->dm.timing.h_display;
|
||||
}
|
||||
/* horizontal end is the first position beyond the displayed range on the CRTC */
|
||||
crtc_hend = crtc_hstart + si->dm.timing.h_display;
|
||||
crtc_vstart = si->dm.v_display_start;
|
||||
/* vertical end is the first position beyond the displayed range on the CRTC */
|
||||
crtc_vend = crtc_vstart + si->dm.timing.v_display;
|
||||
|
||||
|
||||
/****************************************
|
||||
*** setup all edges of output window ***
|
||||
@@ -93,22 +110,22 @@ status_t gx00_configure_bes
|
||||
hcoordv = 0;
|
||||
/* left edge coordinate of output window, must be inside desktop */
|
||||
/* clipping on the left side */
|
||||
if (ow->h_start < 0)
|
||||
if (ow->h_start < crtc_hstart)
|
||||
{
|
||||
temp1 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clipping on the right side */
|
||||
if (ow->h_start >= (si->dm.virtual_width - 1))
|
||||
if (ow->h_start >= (crtc_hend - 1))
|
||||
{
|
||||
/* width < 2 is not allowed */
|
||||
temp1 = (si->dm.virtual_width - 2) & 0x7ff;
|
||||
temp1 = (crtc_hend - crtc_hstart - 2) & 0x7ff;
|
||||
}
|
||||
else
|
||||
/* no clipping here */
|
||||
{
|
||||
temp1 = (uint16)ow->h_start & 0x7ff;
|
||||
temp1 = (ow->h_start - crtc_hstart) & 0x7ff;
|
||||
}
|
||||
}
|
||||
hcoordv |= temp1 << 16;
|
||||
@@ -121,14 +138,14 @@ status_t gx00_configure_bes
|
||||
else
|
||||
{
|
||||
/* clipping on the right side */
|
||||
if ((ow->h_start + ow->width - 1) > (si->dm.virtual_width - 1))
|
||||
if ((ow->h_start + ow->width - 1) > (crtc_hend - 1))
|
||||
{
|
||||
temp2 = (si->dm.virtual_width - 1) & 0x7ff;
|
||||
temp2 = (crtc_hend - crtc_hstart - 1) & 0x7ff;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clipping on the left side */
|
||||
if ((ow->h_start + ow->width - 1) < 1)
|
||||
if ((ow->h_start + ow->width - 1) < (crtc_hstart + 1))
|
||||
{
|
||||
/* width < 2 is not allowed */
|
||||
temp2 = 1;
|
||||
@@ -136,33 +153,33 @@ status_t gx00_configure_bes
|
||||
else
|
||||
/* no clipping here */
|
||||
{
|
||||
temp2 = ((uint16)(ow->h_start + ow->width - 1)) & 0x7ff;
|
||||
temp2 = ((uint16)(ow->h_start + ow->width - crtc_hstart - 1)) & 0x7ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
hcoordv |= temp2 << 0;
|
||||
LOG(4,("Overlay: left-edge output %d, right-edge output %d\n",temp1, temp2));
|
||||
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 < 0)
|
||||
if (ow->v_start < crtc_vstart)
|
||||
{
|
||||
temp1 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clipping on the bottom side */
|
||||
if (ow->v_start >= (si->dm.virtual_height - 1))
|
||||
if (ow->v_start >= (crtc_vend - 1))
|
||||
{
|
||||
/* height < 2 is not allowed */
|
||||
temp1 = (si->dm.virtual_height - 2) & 0x7ff;
|
||||
temp1 = (crtc_vend - crtc_vstart - 2) & 0x7ff;
|
||||
}
|
||||
else
|
||||
/* no clipping here */
|
||||
{
|
||||
temp1 = (uint16)ow->v_start & 0x7ff;
|
||||
temp1 = (ow->v_start - crtc_vstart) & 0x7ff;
|
||||
}
|
||||
}
|
||||
vcoordv |= temp1 << 16;
|
||||
@@ -175,14 +192,14 @@ status_t gx00_configure_bes
|
||||
else
|
||||
{
|
||||
/* clipping on the bottom side */
|
||||
if ((ow->v_start + ow->height - 1) > (si->dm.virtual_height - 1))
|
||||
if ((ow->v_start + ow->height - 1) > (crtc_vend - 1))
|
||||
{
|
||||
temp2 = (si->dm.virtual_height - 1) & 0x7ff;
|
||||
temp2 = (crtc_vend - crtc_vstart - 1) & 0x7ff;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clipping on the top side */
|
||||
if ((ow->v_start + ow->height - 1) < 1)
|
||||
if ((ow->v_start + ow->height - 1) < (crtc_vstart + 1))
|
||||
{
|
||||
/* height < 2 is not allowed */
|
||||
temp2 = 1;
|
||||
@@ -190,12 +207,12 @@ status_t gx00_configure_bes
|
||||
else
|
||||
/* no clipping here */
|
||||
{
|
||||
temp2 = ((uint16)(ow->v_start + ow->height - 1)) & 0x7ff;
|
||||
temp2 = ((uint16)(ow->v_start + ow->height - crtc_vstart - 1)) & 0x7ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
vcoordv |= temp2 << 0;
|
||||
LOG(4,("Overlay: top-edge output %d, bottom-edge output %d\n",temp1, temp2));
|
||||
LOG(4,("Overlay: CRTC top-edge output %d, bottom-edge output %d\n",temp1, temp2));
|
||||
|
||||
|
||||
/*********************************************
|
||||
@@ -274,14 +291,13 @@ status_t gx00_configure_bes
|
||||
* 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 < 0)
|
||||
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) < 1)
|
||||
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);
|
||||
@@ -289,7 +305,7 @@ status_t gx00_configure_bes
|
||||
else
|
||||
{
|
||||
/* increase 'first contributing pixel' with actual number of dest. clipping pixels */
|
||||
hsrcstv += (0 - ow->h_start);
|
||||
hsrcstv += (crtc_hstart - ow->h_start);
|
||||
}
|
||||
LOG(4,("Overlay: clipping left...\n"));
|
||||
|
||||
@@ -314,11 +330,11 @@ status_t gx00_configure_bes
|
||||
|
||||
hsrcendv = 0;
|
||||
/* check for destination horizontal clipping at right side */
|
||||
if ((ow->h_start + ow->width - 1) > (si->dm.virtual_width - 1))
|
||||
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 > (si->dm.virtual_width - 2))
|
||||
if (ow->h_start > (crtc_hend - 2))
|
||||
{
|
||||
/* increase 'number of clipping pixels' with 'fixed value': (total dest. width - 2) */
|
||||
hsrcendv += (ow->width - 2);
|
||||
@@ -326,7 +342,7 @@ status_t gx00_configure_bes
|
||||
else
|
||||
{
|
||||
/* increase 'number of clipping pixels' with actual number of dest. clipping pixels */
|
||||
hsrcendv += ((ow->h_start + ow->width - 1) - (si->dm.virtual_width - 1));
|
||||
hsrcendv += ((ow->h_start + ow->width - 1) - (crtc_hend - 1));
|
||||
}
|
||||
LOG(4,("Overlay: clipping right...\n"));
|
||||
|
||||
@@ -435,11 +451,11 @@ status_t gx00_configure_bes
|
||||
/* calculate origin adress */
|
||||
LOG(4,("Overlay: topleft corner of input bitmap (cardRAM offset) $%08x\n",a1orgv));
|
||||
/* check for destination vertical clipping at top side */
|
||||
if (ow->v_start < 0)
|
||||
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) < 1)
|
||||
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)) *
|
||||
@@ -452,8 +468,8 @@ status_t gx00_configure_bes
|
||||
/* increase source buffer origin with:
|
||||
* (integer part of (number of destination picture clipping pixels * inverse scaling factor)) *
|
||||
* bytes per row source picture */
|
||||
a1orgv += ((((0 - ow->v_start) * ifactor) >> 16) * ob->bytes_per_row);
|
||||
weight = (0 - ow->v_start) * ifactor;
|
||||
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"));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/* Authors:
|
||||
Mark Watson 2/2000,
|
||||
Apsed,
|
||||
Rudolf Cornelissen 11-12/2002
|
||||
Rudolf Cornelissen 11/2002-4/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00040000
|
||||
@@ -196,6 +196,30 @@ status_t gx00_crtc_depth(int mode)
|
||||
viddelay = 2<<3; // for 8 to 16Mb of memory
|
||||
} while (0);
|
||||
|
||||
/* setup green_sync if requested */
|
||||
if (si->settings.greensync)
|
||||
{
|
||||
/* enable sync_on_green: ctrl bit polarity was reversed for Gxxx cards! */
|
||||
if (si->ps.card_type <= MIL2)
|
||||
DXIW(GENCTRL, (DXIR(GENCTRL) | 0x20));
|
||||
else
|
||||
DXIW(GENCTRL, (DXIR(GENCTRL) & ~0x20));
|
||||
/* select horizontal _and_ vertical sync */
|
||||
viddelay |= 0x40;
|
||||
|
||||
LOG(4,("CRTC: sync_on_green enabled\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* disable sync_on_green: ctrl bit polarity was reversed for Gxxx cards! */
|
||||
if (si->ps.card_type <= MIL2)
|
||||
DXIW(GENCTRL, (DXIR(GENCTRL) & ~0x20));
|
||||
else
|
||||
DXIW(GENCTRL, (DXIR(GENCTRL) | 0x20));
|
||||
|
||||
LOG(4,("CRTC: sync_on_green disabled\n"));
|
||||
}
|
||||
|
||||
/*set VCLK scaling*/
|
||||
switch(mode)
|
||||
{
|
||||
@@ -238,16 +262,17 @@ status_t gx00_crtc_dpms_fetch(uint8 * display,uint8 * h,uint8 * v) // MIL2
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t gx00_crtc_set_display_pitch(uint32 pitch,uint8 bpp)
|
||||
status_t gx00_crtc_set_display_pitch()
|
||||
{
|
||||
uint32 offset;
|
||||
|
||||
LOG(4,("CRTC: setting card pitch (offset between lines)\n"));
|
||||
|
||||
/*figure out offset value hardware needs*/
|
||||
offset = (pitch*bpp)/128;
|
||||
/* figure out offset value hardware needs:
|
||||
* same for MIL1-G550 cards assuming MIL1/2 uses the TVP3026 64-bits DAC etc. */
|
||||
offset = si->fbc.bytes_per_row / 16;
|
||||
|
||||
LOG(2,("CRTC: offset: 0x%04x\n",offset));
|
||||
LOG(2,("CRTC: offset register: 0x%04x\n",offset));
|
||||
|
||||
/*program the card!*/
|
||||
VGAW_I(CRTC,0x13,(offset&0xFF));
|
||||
@@ -268,6 +293,20 @@ status_t gx00_crtc_set_display_start(uint32 startadd,uint8 bpp)
|
||||
LOG(2,("CRTC: frameRAM: %x\n",si->framebuffer));
|
||||
LOG(2,("CRTC: framebuffer: %x\n",si->fbc.frame_buffer));
|
||||
|
||||
/* make sure we are in retrace on MIL cards (if possible), because otherwise
|
||||
* distortions might occur during our reprogramming them (no double buffering) */
|
||||
if (si->ps.card_type < G100)
|
||||
{
|
||||
/* we might have no retraces during setmode! */
|
||||
uint32 timeout = 0;
|
||||
/* wait 25mS max. for retrace to occur (refresh > 40Hz) */
|
||||
while ((!(ACCR(STATUS) & 0x08)) && (timeout < (25000/4)))
|
||||
{
|
||||
snooze(4);
|
||||
timeout++;
|
||||
}
|
||||
}
|
||||
|
||||
/*set standard registers*/
|
||||
VGAW_I(CRTC,0xD,startadd&0xFF);
|
||||
VGAW_I(CRTC,0xC,(startadd&0xFF00)>>8);
|
||||
@@ -389,43 +428,91 @@ status_t gx00_crtc_mem_priority(uint8 colordepth)
|
||||
status_t gx00_crtc_cursor_init()
|
||||
{
|
||||
int i;
|
||||
uint32 * fb;
|
||||
/* cursor bitmap will be stored at the start of the framebuffer */
|
||||
const uint32 curadd = 0;
|
||||
|
||||
/* set cursor bitmap adress ... */
|
||||
DXIW(CURADDL,curadd >> 10);
|
||||
DXIW(CURADDH,curadd >> 18);
|
||||
/* ... and repeat that: G100 requires other programming order than other cards!?! */
|
||||
DXIW(CURADDL,curadd >> 10);
|
||||
DXIW(CURADDH,curadd >> 18);
|
||||
if (si->ps.card_type >= G100)
|
||||
{
|
||||
uint32 * fb;
|
||||
/* cursor bitmap will be stored at the start of the framebuffer on >= G100 */
|
||||
const uint32 curadd = 0;
|
||||
|
||||
/* set cursor bitmap adress ... */
|
||||
DXIW(CURADDL,curadd >> 10);
|
||||
DXIW(CURADDH,curadd >> 18);
|
||||
/* ... and repeat that: G100 requires other programming order than later cards!?! */
|
||||
DXIW(CURADDL,curadd >> 10);
|
||||
DXIW(CURADDH,curadd >> 18);
|
||||
|
||||
/*set cursor colour*/
|
||||
DXIW(CURCOL0RED,0XFF);
|
||||
DXIW(CURCOL0GREEN,0xFF);
|
||||
DXIW(CURCOL0BLUE,0xFF);
|
||||
DXIW(CURCOL1RED,0);
|
||||
DXIW(CURCOL1GREEN,0);
|
||||
DXIW(CURCOL1BLUE,0);
|
||||
DXIW(CURCOL2RED,0);
|
||||
DXIW(CURCOL2GREEN,0);
|
||||
DXIW(CURCOL2BLUE,0);
|
||||
|
||||
/*clear cursor*/
|
||||
fb = (uint32 *) si->framebuffer + curadd;
|
||||
for (i=0;i<(1024/4);i++)
|
||||
{
|
||||
fb[i]=0;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* <= G100 cards have serial cursor color registers,
|
||||
* and dedicated cursor bitmap RAM (in TVP3026 DAC)
|
||||
*/
|
||||
{
|
||||
/* select first colorRAM adress */
|
||||
DACW(TVP_CUROVRWTADD,0x00);
|
||||
/* overscan/border color is black, order of colors set is R,G,B */
|
||||
DACW(TVP_CUROVRDATA,0xff);
|
||||
DACW(TVP_CUROVRDATA,0xff);
|
||||
DACW(TVP_CUROVRDATA,0xff);
|
||||
/* set sursor color 0 */
|
||||
DACW(TVP_CUROVRDATA,0xff);
|
||||
DACW(TVP_CUROVRDATA,0xff);
|
||||
DACW(TVP_CUROVRDATA,0xff);
|
||||
/* set sursor color 1 */
|
||||
DACW(TVP_CUROVRDATA,0x00);
|
||||
DACW(TVP_CUROVRDATA,0x00);
|
||||
DACW(TVP_CUROVRDATA,0x00);
|
||||
/* set sursor color 2 */
|
||||
DACW(TVP_CUROVRDATA,0x00);
|
||||
DACW(TVP_CUROVRDATA,0x00);
|
||||
DACW(TVP_CUROVRDATA,0x00);
|
||||
|
||||
/* select first cursor pattern DAC-internal RAM adress, and
|
||||
* make sure indirect cursor control register is selected as active register */
|
||||
DXIW(CURCTRL,(DXIR(CURCTRL) & 0x73));
|
||||
DACW(PALWTADD,0x00);
|
||||
/* now clear it, auto-incrementing the adress */
|
||||
for(i=0;i<1024;i++)
|
||||
{
|
||||
DACW(TVP_CURRAMDATA,0x00);
|
||||
}
|
||||
}
|
||||
|
||||
/* activate hardware cursor */
|
||||
DXIW(CURCTRL,1);
|
||||
|
||||
/*set cursor colour*/
|
||||
DXIW(CURCOL0RED,0XFF);
|
||||
DXIW(CURCOL0GREEN,0xFF);
|
||||
DXIW(CURCOL0BLUE,0xFF);
|
||||
DXIW(CURCOL1RED,0);
|
||||
DXIW(CURCOL1GREEN,0);
|
||||
DXIW(CURCOL1BLUE,0);
|
||||
DXIW(CURCOL2RED,0);
|
||||
DXIW(CURCOL2GREEN,0);
|
||||
DXIW(CURCOL2BLUE,0);
|
||||
|
||||
/*clear cursor*/
|
||||
fb = (uint32 *) si->framebuffer + curadd;
|
||||
for (i=0;i<(1024/4);i++)
|
||||
{
|
||||
fb[i]=0;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t gx00_crtc_cursor_show()
|
||||
{
|
||||
DXIW(CURCTRL,1);
|
||||
if ((si->ps.card_type < G100) && (si->dm.timing.h_total > 2048))
|
||||
{
|
||||
/* MIL1/2 DAC needs to be told if h_total for the active mode gets above 2048 */
|
||||
DXIW(CURCTRL, 0x11);
|
||||
}
|
||||
else
|
||||
{
|
||||
DXIW(CURCTRL, 0x01);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -438,19 +525,56 @@ status_t gx00_crtc_cursor_hide()
|
||||
/*set up cursor shape*/
|
||||
status_t gx00_crtc_cursor_define(uint8* andMask,uint8* xorMask)
|
||||
{
|
||||
uint8 * cursor;
|
||||
int y;
|
||||
|
||||
/*get a pointer to the cursor*/
|
||||
cursor = (uint8*) si->framebuffer;
|
||||
|
||||
/*draw the cursor*/
|
||||
for(y=0;y<16;y++)
|
||||
if(si->ps.card_type >= G100)
|
||||
{
|
||||
cursor[y*16+7]=~*andMask++;
|
||||
cursor[y*16+15]=*xorMask++;
|
||||
cursor[y*16+6]=~*andMask++;
|
||||
cursor[y*16+14]=*xorMask++;
|
||||
uint8 * cursor;
|
||||
|
||||
/*get a pointer to the cursor*/
|
||||
cursor = (uint8*) si->framebuffer;
|
||||
|
||||
/*draw the cursor*/
|
||||
for(y=0;y<16;y++)
|
||||
{
|
||||
cursor[y*16+7]=~*andMask++;
|
||||
cursor[y*16+15]=*xorMask++;
|
||||
cursor[y*16+6]=~*andMask++;
|
||||
cursor[y*16+14]=*xorMask++;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* <= G100 cards have dedicated cursor bitmap RAM (in TVP3026 DAC) */
|
||||
{
|
||||
uint8 curctrl;
|
||||
|
||||
/* disable the cursor to prevent distortions in screen output */
|
||||
curctrl = (DXIR(CURCTRL));
|
||||
DXIW(CURCTRL, (curctrl & 0xfc));
|
||||
/* select first cursor pattern DAC-internal RAM adress for plane 0 */
|
||||
DXIW(CURCTRL, (DXIR(CURCTRL) & ~0x0c));
|
||||
DACW(PALWTADD, 0x00);
|
||||
/* now fill it, partly auto-incrementing the adress */
|
||||
for(y = 0; y < 16; y++)
|
||||
{
|
||||
DACW(PALWTADD, (y * 8));
|
||||
DACW(TVP_CURRAMDATA, ~*andMask++);
|
||||
DACW(TVP_CURRAMDATA, ~*andMask++);
|
||||
}
|
||||
/* select first cursor pattern DAC-internal RAM adress for plane 1 */
|
||||
DXIW(CURCTRL, (DXIR(CURCTRL) | 0x08));
|
||||
DACW(PALWTADD, 0x00);
|
||||
/* now fill it, partly auto-incrementing the adress */
|
||||
for(y = 0; y < 16; y++)
|
||||
{
|
||||
DACW(PALWTADD, y*8);
|
||||
DACW(TVP_CURRAMDATA, *xorMask++);
|
||||
DACW(TVP_CURRAMDATA, *xorMask++);
|
||||
}
|
||||
/* delay restoring the cursor to prevent distortions in screen output */
|
||||
snooze(5);
|
||||
/* restore the cursor */
|
||||
DXIW(CURCTRL, curctrl);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@@ -460,7 +584,6 @@ status_t gx00_crtc_cursor_define(uint8* andMask,uint8* xorMask)
|
||||
status_t gx00_crtc_cursor_position(uint16 x ,uint16 y)
|
||||
{
|
||||
int i=64;
|
||||
// LOG(4,("DAC: cursor-> %d %d\n",x,y));
|
||||
|
||||
x+=i;
|
||||
y+=i;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Authors:
|
||||
Mark Watson 6/2000,
|
||||
Rudolf Cornelissen 12/2002
|
||||
Rudolf Cornelissen 12/2002 - 4/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00020000
|
||||
@@ -10,37 +10,139 @@
|
||||
#include "mga_std.h"
|
||||
|
||||
/*set a mode line - inputs are in pixels/scanlines*/
|
||||
status_t g400_crtc2_set_timing(
|
||||
uint32 hdisp_e,uint32 hsync_s,uint32 hsync_e,uint32 htotal,
|
||||
uint32 vdisp_e,uint32 vsync_s,uint32 vsync_e,uint32 vtotal,
|
||||
uint8 hsync_pos,uint8 vsync_pos
|
||||
)
|
||||
status_t g400_crtc2_set_timing(display_mode target)
|
||||
{
|
||||
uint32 temp;
|
||||
|
||||
LOG(4,("CRTC2: setting timing\n"));
|
||||
|
||||
/*check horizontal timing parameters are to nearest 8 pixels*/
|
||||
if ((hdisp_e&7)|(hsync_s&7)|(hsync_e&7)|(htotal&7))
|
||||
if ((!(target.flags & TV_BITS)) || (si->ps.card_type <= G400MAX))
|
||||
{
|
||||
LOG(8,("CRTC2:Horizontal timings are not multiples of 8 pixels\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
/* G450/G550 monitor mode, and all modes on older cards */
|
||||
|
||||
/*program the second CRTC*/
|
||||
CR2W(HPARAM, ((((hdisp_e - 8) & 0x0fff) << 16) | ((htotal - 8) & 0x0fff)));
|
||||
CR2W(HSYNC, ((((hsync_e - 8) & 0x0fff) << 16) | ((hsync_s - 8) & 0x0fff)));
|
||||
CR2W(VPARAM, ((((vdisp_e - 1) & 0x0fff) << 16) | ((vtotal - 1) & 0x0fff)));
|
||||
CR2W(VSYNC, ((((vsync_e - 1) & 0x0fff) << 16) | ((vsync_s - 1) & 0x0fff)));
|
||||
//Mark: (wrong AFAIK, warning: SETMODE MAVEN-CRTC delay is now tuned to new setup!!)
|
||||
//CR2W(PRELOAD, (((vsync_s & 0x0fff) << 16) | (hsync_s & 0x0fff)));
|
||||
CR2W(PRELOAD, ((((vsync_s - 1) & 0x0fff) << 16) | ((hsync_s - 8) & 0x0fff)));
|
||||
CR2W(MISC, ((0xfff << 16) | (((!hsync_pos) & 0x01) << 8) | (((!vsync_pos) & 0x01) << 9)));
|
||||
/* check horizontal timing parameters are to nearest 8 pixels */
|
||||
if ((target.timing.h_display & 0x07) | (target.timing.h_sync_start & 0x07) |
|
||||
(target.timing.h_sync_end & 0x07) | (target.timing.h_total & 0x07))
|
||||
{
|
||||
LOG(8,("CRTC2: Horizontal timings are not multiples of 8 pixels\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/* make sure NTSC clock killer circuitry is disabled */
|
||||
CR2W(DATACTL, (CR2R(DATACTL) & ~0x00000010));
|
||||
|
||||
/* make sure CRTC2 is set to progressive scan for monitor mode */
|
||||
CR2W(CTL, (CR2R(CTL) & ~0x02001000));
|
||||
|
||||
/* program the second CRTC */
|
||||
CR2W(HPARAM, ((((target.timing.h_display - 8) & 0x0fff) << 16) |
|
||||
((target.timing.h_total - 8) & 0x0fff)));
|
||||
CR2W(HSYNC, ((((target.timing.h_sync_end - 8) & 0x0fff) << 16) |
|
||||
((target.timing.h_sync_start - 8) & 0x0fff)));
|
||||
CR2W(VPARAM, ((((target.timing.v_display - 1) & 0x0fff) << 16) |
|
||||
((target.timing.v_total - 1) & 0x0fff)));
|
||||
CR2W(VSYNC, ((((target.timing.v_sync_end - 1) & 0x0fff) << 16) |
|
||||
((target.timing.v_sync_start - 1) & 0x0fff)));
|
||||
//Mark: (wrong AFAIK, warning: SETMODE MAVEN-CRTC delay is now tuned to new setup!!)
|
||||
//CR2W(PRELOAD, (((target.timing.v_sync_start & 0x0fff) << 16) |
|
||||
// (target.timing.h_sync_start & 0x0fff)));
|
||||
CR2W(PRELOAD, ((((target.timing.v_sync_start - 1) & 0x0fff) << 16) |
|
||||
((target.timing.h_sync_start - 8) & 0x0fff)));
|
||||
|
||||
temp = (0xfff << 16);
|
||||
if (!(target.timing.flags & B_POSITIVE_HSYNC)) temp |= (0x01 << 8);
|
||||
if (!(target.timing.flags & B_POSITIVE_VSYNC)) temp |= (0x01 << 9);
|
||||
CR2W(MISC, temp);
|
||||
|
||||
/* On <= G400MAX dualhead cards we need to send a copy to the MAVEN;
|
||||
* unless TVout is active */
|
||||
if ((si->ps.secondary_head) && (!(target.flags & TV_BITS)))
|
||||
gx00_maven_set_timing(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* G450/G550 TVout mode */
|
||||
display_mode tv_mode = target;
|
||||
uint8 frame;
|
||||
unsigned int vcount, prev_vcount;
|
||||
|
||||
LOG(4,("CRTC2: setting up G450/G550 TVout mode\n"));
|
||||
|
||||
/* check horizontal timing parameters are to nearest 8 pixels */
|
||||
if ((tv_mode.timing.h_display & 0x07) | (tv_mode.timing.h_sync_start & 0x07) |
|
||||
(tv_mode.timing.h_sync_end & 0x07))
|
||||
{
|
||||
LOG(8,("CRTC2: Horizontal timings are not multiples of 8 pixels\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/* disable NTSC clock killer circuitry */
|
||||
CR2W(DATACTL, (CR2R(DATACTL) & ~0x00000010));
|
||||
|
||||
if (tv_mode.timing.h_total & 0x07)
|
||||
{
|
||||
/* we rely on this for both PAL and NTSC modes if h_total is 'illegal' */
|
||||
LOG(4,("CRTC2: enabling clock killer circuitry\n"));
|
||||
CR2W(DATACTL, (CR2R(DATACTL) | 0x00000010));
|
||||
}
|
||||
|
||||
/* make sure h_total is valid for TVout mode */
|
||||
tv_mode.timing.h_total &= ~0x07;
|
||||
|
||||
/* modify tv_mode for interlaced use */
|
||||
tv_mode.timing.v_display >>= 1;
|
||||
tv_mode.timing.v_sync_start >>= 1;
|
||||
tv_mode.timing.v_sync_end >>= 1;
|
||||
tv_mode.timing.v_total >>= 1;
|
||||
|
||||
/*program the second CRTC*/
|
||||
CR2W(HPARAM, ((((tv_mode.timing.h_display - 8) & 0x0fff) << 16) |
|
||||
((tv_mode.timing.h_total - 8) & 0x0fff)));
|
||||
CR2W(HSYNC, ((((tv_mode.timing.h_sync_end - 8) & 0x0fff) << 16) |
|
||||
((tv_mode.timing.h_sync_start - 8) & 0x0fff)));
|
||||
CR2W(VPARAM, ((((tv_mode.timing.v_display - 1) & 0x0fff) << 16) |
|
||||
((tv_mode.timing.v_total - 1) & 0x0fff)));
|
||||
CR2W(VSYNC, ((((tv_mode.timing.v_sync_end - 1) & 0x0fff) << 16) |
|
||||
((tv_mode.timing.v_sync_start - 1) & 0x0fff)));
|
||||
//Mark: (wrong AFAIK, warning: SETMODE MAVEN-CRTC delay is now tuned to new setup!!)
|
||||
//CR2W(PRELOAD, (((tv_mode.timing.v_sync_start & 0x0fff) << 16) |
|
||||
// (tv_mode.timing.h_sync_start & 0x0fff)));
|
||||
CR2W(PRELOAD, ((((tv_mode.timing.v_sync_start - 1) & 0x0fff) << 16) |
|
||||
((tv_mode.timing.h_sync_start - 8) & 0x0fff)));
|
||||
|
||||
/* set CRTC2 to interlaced mode:
|
||||
* First enable progressive scan mode while making sure
|
||||
* CRTC2 is setup for TVout mode use... */
|
||||
CR2W(CTL, ((CR2R(CTL) & ~0x02000000) | 0x00001000));
|
||||
/* now synchronize to the start of a frame... */
|
||||
prev_vcount = 0;
|
||||
for (frame = 0; frame < 2; frame++)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
vcount = (CR2R(VCOUNT) & 0x00000fff);
|
||||
if (vcount >= prev_vcount)
|
||||
prev_vcount = vcount;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* and start interlaced mode now! */
|
||||
CR2W(CTL, (CR2R(CTL) | 0x02000000));
|
||||
|
||||
temp = (0xfff << 16);
|
||||
if (!(tv_mode.timing.flags & B_POSITIVE_HSYNC)) temp |= (0x01 << 8);
|
||||
if (!(tv_mode.timing.flags & B_POSITIVE_VSYNC)) temp |= (0x01 << 9);
|
||||
CR2W(MISC, temp);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t g400_crtc2_depth(int mode)
|
||||
{
|
||||
/*validate bit depth and set mode*/
|
||||
/* validate bit depth and set mode */
|
||||
/* also clears TVout mode (b12) */
|
||||
switch(mode)
|
||||
{
|
||||
case BPP16:case BPP32DIR:
|
||||
@@ -57,10 +159,29 @@ status_t g400_crtc2_depth(int mode)
|
||||
|
||||
status_t g400_crtc2_dpms(uint8 display,uint8 h,uint8 v)
|
||||
{
|
||||
//fixme: CTL b0=1 is CRTC2 enabled, 0 is disabled. This code is dangerous...
|
||||
CR2W(CTL,(CR2R(CTL)&0xFFF0077E)|(display&h&v)); /*enable second CRTC if required*/
|
||||
if (display & h & v)
|
||||
{
|
||||
/* enable CRTC2 and don't touch the rest */
|
||||
CR2W(CTL, ((CR2R(CTL) & 0xFFF0177E) | 0x01));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* disable CRTC2 and don't touch the rest */
|
||||
CR2W(CTL, (CR2R(CTL) & 0xFFF0177E));
|
||||
}
|
||||
|
||||
if (si->ps.card_type >= G450)
|
||||
{
|
||||
//fixme:
|
||||
/* setup monitor mode DPMS: G450 and later fully support this on CRTC2 */
|
||||
//for now:
|
||||
//enable 'straight-through' sync outputs on both analog output connectors...
|
||||
DXIW(SYNCCTRL,0x00);
|
||||
}
|
||||
|
||||
/* On <= G400MAX dualhead cards we always need to send a 'copy' to the MAVEN */
|
||||
if (si->ps.secondary_head) gx00_maven_dpms(display, h, v);
|
||||
|
||||
/*ignore h,v because they are not supported*/
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -73,31 +194,54 @@ status_t g400_crtc2_dpms_fetch(uint8 * display,uint8 * h,uint8 * v)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t g400_crtc2_set_display_pitch(uint32 pitch,uint8 bpp)
|
||||
status_t g400_crtc2_set_display_pitch()
|
||||
{
|
||||
uint32 offset;
|
||||
|
||||
LOG(4,("CRTC2: setting card pitch 0x%08x bpp %d\n", pitch, bpp));
|
||||
LOG(4,("CRTC2: setting card pitch (offset between lines)\n"));
|
||||
|
||||
/*figure out offset value hardware needs*/
|
||||
offset = pitch*(bpp>>3);
|
||||
/* figure out offset value hardware needs */
|
||||
offset = si->fbc.bytes_per_row;
|
||||
if (si->interlaced_tv_mode)
|
||||
{
|
||||
LOG(4,("CRTC2: setting interlaced mode\n"));
|
||||
/* double the CRTC2 linelength so fields are displayed instead of frames */
|
||||
offset *= 2;
|
||||
}
|
||||
else
|
||||
LOG(4,("CRTC2: setting progressive scan mode\n"));
|
||||
|
||||
LOG(2,("CRTC2: offset: %x\n",offset));
|
||||
LOG(2,("CRTC2: offset set to %d bytes\n", offset));
|
||||
|
||||
/*program the card!*/
|
||||
/* program the head */
|
||||
CR2W(OFFSET,offset);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t g400_crtc2_set_display_start(uint32 startadd,uint8 bpp)
|
||||
{
|
||||
LOG(4,("CRTC2: setting card RAM to be displayed bpp %d\n", bpp));
|
||||
LOG(4,("CRTC2: setting card RAM to be displayed for %d bits per pixel\n", bpp));
|
||||
|
||||
LOG(2,("CRTC2: startadd: %x\n",startadd));
|
||||
LOG(2,("CRTC2: frameRAM: %x\n",si->framebuffer));
|
||||
LOG(2,("CRTC2: framebuffer: %x\n",si->fbc.frame_buffer));
|
||||
LOG(2,("CRTC2: startadd: $%x\n",startadd));
|
||||
LOG(2,("CRTC2: frameRAM: $%x\n",si->framebuffer));
|
||||
LOG(2,("CRTC2: framebuffer: $%x\n",si->fbc.frame_buffer));
|
||||
|
||||
if (si->interlaced_tv_mode)
|
||||
{
|
||||
LOG(4,("CRTC2: setting up fields for interlaced mode\n"));
|
||||
/* program the head for interlaced use */
|
||||
//fixme: seperate both heads: we need a secondary si->fbc!
|
||||
/* setup field 0 startadress in buffer to read picture's odd lines */
|
||||
CR2W(STARTADD0, (startadd + si->fbc.bytes_per_row));
|
||||
/* setup field 1 startadress in buffer to read picture's even lines */
|
||||
CR2W(STARTADD1, startadd);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(4,("CRTC2: setting up frames for progressive scan mode\n"));
|
||||
/* program the head for non-interlaced use */
|
||||
CR2W(STARTADD0, startadd);
|
||||
}
|
||||
|
||||
/*program the card!*/
|
||||
CR2W(STARTADD0,startadd);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -2,19 +2,23 @@
|
||||
/* Authors:
|
||||
Mark Watson 2/2000,
|
||||
Apsed 2002,
|
||||
Rudolf Cornelissen 9-12/2002
|
||||
Rudolf Cornelissen 9/2002-4/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00010000
|
||||
|
||||
#include "mga_std.h"
|
||||
|
||||
static status_t g100_g400max_dac_pix_pll_find(
|
||||
static status_t milx_dac_pix_pll_find(
|
||||
display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result);
|
||||
static status_t g100_g400max_dac_pix_pll_find(
|
||||
display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test);
|
||||
static status_t g450_g550_dac_pix_pll_find(
|
||||
display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test);
|
||||
static status_t g100_g400max_dac_sys_pll_find(
|
||||
float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result);
|
||||
static status_t g450_g550_dac_sys_pll_find(
|
||||
float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result);
|
||||
|
||||
/*set the mode, brightness is a value from 0->2 (where 1 is equivalent to direct)*/
|
||||
status_t gx00_dac_mode(int mode,float brightness)
|
||||
@@ -81,10 +85,59 @@ status_t gx00_dac_mode(int mode,float brightness)
|
||||
if (gx00_dac_palette(r,g,b)!=B_OK) return B_ERROR;
|
||||
|
||||
/*set the mode - also sets VCLK dividor*/
|
||||
DXIW(MULCTRL,mode);
|
||||
DACW(PIXRDMSK,0xff); // apsed, palette addressing not masked
|
||||
if (si->ps.card_type >= G100)
|
||||
{
|
||||
DXIW(MULCTRL, mode);
|
||||
LOG(2,("DAC: mulctrl 0x%02x\n", DXIR(MULCTRL)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* MIL1/2 differs here (TVP3026DAC) */
|
||||
uint8 miscctrl = 0, latchctrl = 0;
|
||||
uint8 tcolctrl = 0, mulctrl = 0;
|
||||
|
||||
LOG(2,("DAC: mulctrl=%x, pixrdmsk=%x\n",DXIR(MULCTRL), DACR(PIXRDMSK)));
|
||||
/* set the mode */
|
||||
switch (mode)
|
||||
{
|
||||
/* presetting mulctrl for DAC pixelbus_width of 32 */
|
||||
case BPP8:
|
||||
miscctrl=0x00; latchctrl=0x06; tcolctrl=0x80; mulctrl=0x4b;
|
||||
break;
|
||||
case BPP15:
|
||||
miscctrl=0x20; latchctrl=0x06; tcolctrl=0x04; mulctrl=0x53;
|
||||
break;
|
||||
case BPP16:
|
||||
miscctrl=0x20; latchctrl=0x06; tcolctrl=0x05; mulctrl=0x53;
|
||||
break;
|
||||
case BPP24:
|
||||
miscctrl=0x20; latchctrl=0x06; tcolctrl=0x1f; mulctrl=0x5b;
|
||||
break;
|
||||
case BPP32:
|
||||
miscctrl=0x20; latchctrl=0x07; tcolctrl=0x06; mulctrl=0x5b;
|
||||
break;
|
||||
case BPP32DIR:
|
||||
miscctrl=0x20; latchctrl=0x07; tcolctrl=0x06; mulctrl=0x5b;
|
||||
break;
|
||||
}
|
||||
|
||||
/* modify mulctrl if DAC pixelbus_width is 64 */
|
||||
//fixme? do 32bit DACbus MIL 1/2 cards exist? if so, setup via si->ps...
|
||||
if (true) mulctrl += 1;
|
||||
|
||||
DXIW(MISCCTRL, (DXIR(MISCCTRL) & 0x1d) | miscctrl);
|
||||
DXIW(TVP_LATCHCTRL, latchctrl);
|
||||
DXIW(TVP_TCOLCTRL, tcolctrl);
|
||||
DXIW(MULCTRL, mulctrl);
|
||||
|
||||
LOG(2,("DAC: TVP miscctrl 0x%02x, TVP latchctrl 0x%02x\n",
|
||||
DXIR(MISCCTRL), DXIR(TVP_LATCHCTRL)));
|
||||
LOG(2,("DAC: TVP tcolctrl 0x%02x, TVP mulctrl 0x%02x\n",
|
||||
DXIR(TVP_TCOLCTRL), DXIR(MULCTRL)));
|
||||
}
|
||||
|
||||
/* disable palette RAM adressing mask */
|
||||
DACW(PIXRDMSK,0xff);
|
||||
LOG(2,("DAC: pixrdmsk 0x%02x\n", DACR(PIXRDMSK)));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -96,10 +149,8 @@ status_t gx00_dac_palette(uint8 r[256],uint8 g[256],uint8 b[256])
|
||||
|
||||
LOG(4,("DAC: setting palette\n"));
|
||||
|
||||
/* clear palwtadd to start programming (LUT index?) */
|
||||
/* clear palwtadd before starting programming (LUT index) */
|
||||
DACW(PALWTADD,0);
|
||||
/* just for safety (specs are somewhat unclear) (LUT color?) */
|
||||
DACW(PALRDADD,0);
|
||||
|
||||
/*loop through all 256 to program DAC*/
|
||||
for (i=0;i<256;i++)
|
||||
@@ -128,10 +179,6 @@ if (0)
|
||||
LOG(1,("DAC palette %d: w %x %x %x, r %x %x %x\n", i, r[i], g[i], b[i], R, G, B)); // apsed
|
||||
}
|
||||
}
|
||||
/* reset to LUT start just for safety (LUT index?) */
|
||||
DACW(PALWTADD,0);
|
||||
/* (specs are somewhat unclear) (LUT color?) */
|
||||
DACW(PALRDADD,0);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -154,6 +201,7 @@ status_t gx00_dac_set_pix_pll(display_mode target)
|
||||
req_pclk = (target.timing.pixel_clock)/1000.0;
|
||||
LOG(4,("DAC: Setting PIX PLL for pixelclock %f\n", req_pclk));
|
||||
|
||||
/* signal that we actually want to set the mode */
|
||||
result = gx00_dac_pix_pll_find(target,&pix_setting,&m,&n,&p, 1);
|
||||
if (result != B_OK)
|
||||
{
|
||||
@@ -282,14 +330,134 @@ status_t gx00_dac_pix_pll_find
|
||||
switch (si->ps.card_type) {
|
||||
case G550:
|
||||
case G450: return g450_g550_dac_pix_pll_find(target, calc_pclk, m_result, n_result, p_result, test);
|
||||
default: return g100_g400max_dac_pix_pll_find(target, calc_pclk, m_result, n_result, p_result);
|
||||
case MIL2:
|
||||
case MIL1: return milx_dac_pix_pll_find(target, calc_pclk, m_result, n_result, p_result);
|
||||
default: return g100_g400max_dac_pix_pll_find(target, calc_pclk, m_result, n_result, p_result, test);
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/* find nearest valid pixel PLL setting: rewritten by rudolf */
|
||||
static status_t g100_g400max_dac_pix_pll_find(
|
||||
static status_t milx_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;
|
||||
float error, error_best = 999999999;
|
||||
int best[3];
|
||||
float f_vco, max_pclk;
|
||||
float req_pclk = target.timing.pixel_clock/1000.0;
|
||||
|
||||
LOG(4,("DAC: MIL1/MIL2 TVP restrictions apply\n"));
|
||||
|
||||
/* 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;
|
||||
case B_RGB32_LITTLE:
|
||||
max_pclk = si->ps.max_dac1_clock_32;
|
||||
break;
|
||||
default:
|
||||
/* use fail-safe value */
|
||||
max_pclk = si->ps.max_dac1_clock_32;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure the requested pixelclock is within the PLL's operational limits */
|
||||
/* lower limit is min_pixel_vco divided by highest postscaler-factor */
|
||||
if (req_pclk < (si->ps.min_pixel_vco / 8.0))
|
||||
{
|
||||
LOG(4,("DAC: TVP clamping pixclock: requested %fMHz, set to %fMHz\n",
|
||||
req_pclk, (float)(si->ps.min_pixel_vco / 8.0)));
|
||||
req_pclk = (si->ps.min_pixel_vco / 8.0);
|
||||
}
|
||||
/* upper limit is given by pins in combination with current active mode */
|
||||
if (req_pclk > max_pclk)
|
||||
{
|
||||
LOG(4,("DAC: TVP clamping pixclock: requested %fMHz, set to %fMHz\n",
|
||||
req_pclk, (float)max_pclk));
|
||||
req_pclk = max_pclk;
|
||||
}
|
||||
|
||||
/* iterate through all valid PLL postscaler settings */
|
||||
for (p=0x01; p < 0x10; p = p<<1)
|
||||
{
|
||||
/* calculate the needed VCO frequency for this postscaler setting */
|
||||
f_vco = req_pclk * p;
|
||||
|
||||
/* check if this is within range of the VCO specs */
|
||||
if ((f_vco >= si->ps.min_pixel_vco) && (f_vco <= si->ps.max_pixel_vco))
|
||||
{
|
||||
/* iterate trough all valid reference-frequency postscaler settings */
|
||||
for (n = 3; n <= 25; n++)
|
||||
{
|
||||
/* calculate VCO postscaler setting for current setup.. */
|
||||
m = (int)(((f_vco * n) / (8 * si->ps.f_ref)) + 0.5);
|
||||
/* ..and check for validity */
|
||||
if ((m < 3) || (m > 64)) continue;
|
||||
|
||||
/* find error in frequency this setting gives */
|
||||
error = fabs(req_pclk - ((((8 * si->ps.f_ref) / n) * m) / p));
|
||||
|
||||
/* note the setting if best yet */
|
||||
if (error < error_best)
|
||||
{
|
||||
error_best = error;
|
||||
best[0]=m;
|
||||
best[1]=n;
|
||||
best[2]=p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = best[0];
|
||||
n = best[1];
|
||||
p = best[2];
|
||||
|
||||
f_vco = (((8 * si->ps.f_ref) / n) * m);
|
||||
LOG(2,("DAC: TVP pix VCO frequency found %fMhz\n", f_vco));
|
||||
|
||||
/* setup the scalers programming values for found optimum setting */
|
||||
*calc_pclk = (f_vco / p);
|
||||
*m_result = (65 - m);
|
||||
*n_result = (65 - n);
|
||||
|
||||
switch(p)
|
||||
{
|
||||
case 1:
|
||||
p = 0x00;
|
||||
break;
|
||||
case 2:
|
||||
p = 0x01;
|
||||
break;
|
||||
case 4:
|
||||
p = 0x02;
|
||||
break;
|
||||
case 8:
|
||||
p = 0x03;
|
||||
break;
|
||||
}
|
||||
*p_result = p;
|
||||
|
||||
/* display the found pixelclock values */
|
||||
LOG(2,("DAC: TVP pix PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
|
||||
req_pclk, *calc_pclk, *m_result, *n_result, *p_result));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* find nearest valid pixel PLL setting: rewritten by rudolf */
|
||||
static status_t g100_g400max_dac_pix_pll_find(
|
||||
display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test)
|
||||
{
|
||||
int m = 0, n = 0, p = 0, m_max;
|
||||
float error, error_best = 999999999;
|
||||
@@ -315,6 +483,17 @@ static status_t g100_g400max_dac_pix_pll_find(
|
||||
break;
|
||||
}
|
||||
|
||||
/* make sure the pixelPLL and the videoPLL have a little different settings to
|
||||
* minimize distortions in the outputs due to crosstalk:
|
||||
* do *not* change the videoPLL setting because it must be exact if TVout is enabled! */
|
||||
/* Note:
|
||||
* only modify the clock if we are actually going to set the mode */
|
||||
if ((target.flags & DUALHEAD_BITS) && test)
|
||||
{
|
||||
LOG(4,("DAC: dualhead mode active: modified requested pixelclock +1.5%%\n"));
|
||||
req_pclk *= 1.015;
|
||||
}
|
||||
|
||||
/* determine the max. pixelclock for the current videomode */
|
||||
switch (target.space)
|
||||
{
|
||||
@@ -343,9 +522,18 @@ static status_t g100_g400max_dac_pix_pll_find(
|
||||
/* Make sure the requested pixelclock is within the PLL's operational limits */
|
||||
/* lower limit is min_pixel_vco divided by highest postscaler-factor */
|
||||
if (req_pclk < (si->ps.min_pixel_vco / 8.0))
|
||||
{
|
||||
LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n",
|
||||
req_pclk, (float)(si->ps.min_pixel_vco / 8.0)));
|
||||
req_pclk = (si->ps.min_pixel_vco / 8.0);
|
||||
}
|
||||
/* upper limit is given by pins in combination with current active mode */
|
||||
if (req_pclk > max_pclk) req_pclk = max_pclk;
|
||||
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;
|
||||
}
|
||||
|
||||
/* iterate through all valid PLL postscaler settings */
|
||||
for (p=0x01; p < 0x10; p = p<<1)
|
||||
@@ -466,9 +654,18 @@ static status_t g450_g550_dac_pix_pll_find
|
||||
/* Make sure the requested pixelclock is within the PLL's operational limits */
|
||||
/* lower limit is min_pixel_vco divided by highest postscaler-factor */
|
||||
if (req_pclk < (si->ps.min_pixel_vco / 16.0))
|
||||
{
|
||||
LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n",
|
||||
req_pclk, (float)(si->ps.min_pixel_vco / 16.0)));
|
||||
req_pclk = (si->ps.min_pixel_vco / 16.0);
|
||||
}
|
||||
/* upper limit is given by pins in combination with current active mode */
|
||||
if (req_pclk > max_pclk) req_pclk = max_pclk;
|
||||
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;
|
||||
}
|
||||
|
||||
/* iterate through all valid PLL postscaler settings */
|
||||
for (p=0x01; p < 0x20; p = p<<1)
|
||||
@@ -505,7 +702,7 @@ static status_t g450_g550_dac_pix_pll_find
|
||||
|
||||
/* setup the scalers programming values for found optimum setting */
|
||||
m=best[0] - 1;
|
||||
n=best[1] - 1;
|
||||
n=best[1] - 2;
|
||||
switch(best[2])
|
||||
{
|
||||
case 1:
|
||||
@@ -526,7 +723,7 @@ static status_t g450_g550_dac_pix_pll_find
|
||||
}
|
||||
|
||||
/* log the closest VCO speed found */
|
||||
f_vco = ((si->ps.f_ref * 2) / (m + 1)) * (n + 1);
|
||||
f_vco = ((si->ps.f_ref * 2) / (m + 1)) * (n + 2);
|
||||
LOG(2,("DAC: pix VCO frequency found %fMhz\n", f_vco));
|
||||
|
||||
/* now find the filtersetting that matches best with this frequency by testing.
|
||||
@@ -579,9 +776,18 @@ static status_t g100_g400max_dac_sys_pll_find(
|
||||
/* Make sure the requested systemclock is within the PLL's operational limits */
|
||||
/* lower limit is min_system_vco divided by highest postscaler-factor */
|
||||
if (req_sclk < (si->ps.min_system_vco / 8.0))
|
||||
{
|
||||
LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
|
||||
req_sclk, (float)(si->ps.min_system_vco / 8.0)));
|
||||
req_sclk = (si->ps.min_system_vco / 8.0);
|
||||
}
|
||||
/* upper limit is max_system_vco */
|
||||
if (req_sclk > si->ps.max_system_vco) req_sclk = si->ps.max_system_vco;
|
||||
if (req_sclk > si->ps.max_system_vco)
|
||||
{
|
||||
LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
|
||||
req_sclk, (float)si->ps.max_system_vco));
|
||||
req_sclk = si->ps.max_system_vco;
|
||||
}
|
||||
|
||||
/* iterate through all valid PLL postscaler settings */
|
||||
for (p=0x01; p < 0x10; p = p<<1)
|
||||
@@ -666,7 +872,6 @@ status_t gx50_dac_check_sys_pll(uint8 m, uint8 n, uint8 p)
|
||||
uint time = 0, count = 0;
|
||||
|
||||
/* program the new clock */
|
||||
// DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0C)|0x01); /*select the PIXPLL*/
|
||||
DXIW(SYSPLLM, m);
|
||||
DXIW(SYSPLLN, n);
|
||||
DXIW(SYSPLLP, p);
|
||||
@@ -705,7 +910,6 @@ status_t gx50_dac_check_sys_pll_range(uint8 m, uint8 n, uint8 *p, uint8 *q)
|
||||
*p &= 0x47;
|
||||
|
||||
/* iterate through all possible filtersettings */
|
||||
// DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0F)|0x04); /*disable the PIXPLL*/
|
||||
for (s = 0; s < 8 ;s++)
|
||||
{
|
||||
if (gx50_dac_check_sys_pll(m, n, *p)== B_OK)
|
||||
@@ -722,7 +926,6 @@ status_t gx50_dac_check_sys_pll_range(uint8 m, uint8 n, uint8 *p, uint8 *q)
|
||||
/* preset first choice setting found */
|
||||
*q = 1;
|
||||
/* we are done */
|
||||
// DXIW(PIXCLKCTRL,DXIR(PIXCLKCTRL)&0x0B); /*enable the PIXPLL*/
|
||||
return B_OK;
|
||||
}
|
||||
else
|
||||
@@ -741,7 +944,6 @@ status_t gx50_dac_check_sys_pll_range(uint8 m, uint8 n, uint8 *p, uint8 *q)
|
||||
|
||||
/* return the (last found) backup result, or the original p value */
|
||||
*p = p_backup;
|
||||
// DXIW(PIXCLKCTRL,DXIR(PIXCLKCTRL)&0x0B); /*enable the PIXPLL*/
|
||||
/* we found only a non-optimal value */
|
||||
if (*q == 2) return B_OK;
|
||||
|
||||
@@ -765,9 +967,18 @@ static status_t g450_g550_dac_sys_pll_find(
|
||||
/* Make sure the requested pixelclock is within the PLL's operational limits */
|
||||
/* lower limit is min_system_vco divided by highest postscaler-factor */
|
||||
if (req_sclk < (si->ps.min_system_vco / 16.0))
|
||||
{
|
||||
LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
|
||||
req_sclk, (float)(si->ps.min_system_vco / 16.0)));
|
||||
req_sclk = (si->ps.min_system_vco / 16.0);
|
||||
}
|
||||
/* upper limit is max_system_vco */
|
||||
if (req_sclk > si->ps.max_system_vco) req_sclk = si->ps.max_system_vco;
|
||||
if (req_sclk > si->ps.max_system_vco)
|
||||
{
|
||||
LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
|
||||
req_sclk, (float)si->ps.max_system_vco));
|
||||
req_sclk = si->ps.max_system_vco;
|
||||
}
|
||||
|
||||
/* iterate through all valid PLL postscaler settings */
|
||||
for (p=0x01; p < 0x20; p = p<<1)
|
||||
@@ -804,7 +1015,7 @@ static status_t g450_g550_dac_sys_pll_find(
|
||||
|
||||
/* setup the scalers programming values for found optimum setting */
|
||||
m=best[0] - 1;
|
||||
n=best[1] - 1;
|
||||
n=best[1] - 2;
|
||||
switch(best[2])
|
||||
{
|
||||
case 1:
|
||||
@@ -825,7 +1036,7 @@ static status_t g450_g550_dac_sys_pll_find(
|
||||
}
|
||||
|
||||
/* log the closest VCO speed found */
|
||||
f_vco = ((si->ps.f_ref * 2) / (m + 1)) * (n + 1);
|
||||
f_vco = ((si->ps.f_ref * 2) / (m + 1)) * (n + 2);
|
||||
LOG(2,("DAC: sys VCO frequency found %fMhz\n", f_vco));
|
||||
|
||||
/* now find the filtersetting that matches best with this frequency by testing.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Authors:
|
||||
Mark Watson 12/1999,
|
||||
Apsed,
|
||||
Rudolf Cornelissen 10-12/2002
|
||||
Rudolf Cornelissen 10/2002-4/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00008000
|
||||
@@ -11,7 +11,7 @@
|
||||
//#include "mga_init.c" //Nicole's test stuff.
|
||||
|
||||
status_t test_ram();
|
||||
static status_t mil2_general_powerup (void);
|
||||
static status_t mil_general_powerup (void);
|
||||
static status_t g100_general_powerup (void);
|
||||
static status_t g200_general_powerup (void);
|
||||
static status_t g400_general_powerup (void);
|
||||
@@ -56,17 +56,23 @@ status_t gx00_general_powerup()
|
||||
status_t status;
|
||||
uint32 card_class;
|
||||
|
||||
LOG(1,("POWERUP: Matrox (open)BeOS Accelerant 0.14 running.\n"));
|
||||
|
||||
/* detect card type and power it up */
|
||||
switch(CFGR(DEVID))
|
||||
{
|
||||
case 0x0519102b: //MGA-2064 Millenium PCI
|
||||
case 0x051a102b: //MGA-1064 Mystic PCI
|
||||
LOG(8,("POWERUP: Unimplemented Matrox device %08x\n",CFGR(DEVID)));
|
||||
return B_ERROR;
|
||||
case 0x0519102b: //MGA-2064 Millenium PCI
|
||||
si->ps.card_type = MIL1;
|
||||
LOG(4,("POWERUP: Detected MGA-2064 Millennium 1\n"));
|
||||
status = mil_general_powerup();
|
||||
break;
|
||||
case 0x051b102b:case 0x051f102b: //MGA-2164 Millenium 2 PCI/AGP
|
||||
si->ps.card_type = MIL2;
|
||||
LOG(4,("POWERUP: Detected MGA-2164 Millennium 2\n"));
|
||||
status = mil2_general_powerup();
|
||||
status = mil_general_powerup();
|
||||
break;
|
||||
case 0x1000102b:case 0x1001102b: //G100
|
||||
si->ps.card_type = G100;
|
||||
@@ -201,7 +207,7 @@ status_t mga_set_cas_latency()
|
||||
break;
|
||||
case G450:
|
||||
case G550:
|
||||
/* G450 and G550 tune CAS latency via a predefined table at powerup time */
|
||||
/* fixme: implement this if needed */
|
||||
LOG(4,("INIT: G450/G550 RAM CAS tuning not implemented, aborting.\n"));
|
||||
return B_OK;
|
||||
break;
|
||||
@@ -220,11 +226,11 @@ status_t mga_set_cas_latency()
|
||||
}
|
||||
|
||||
static
|
||||
status_t mil2_general_powerup()
|
||||
status_t mil_general_powerup()
|
||||
{
|
||||
status_t result;
|
||||
|
||||
LOG(4, ("INIT: Millenium II powerup\n"));
|
||||
LOG(4, ("INIT: Millenium I/II powerup\n"));
|
||||
if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
|
||||
|
||||
/* initialize the shared_info PINS struct */
|
||||
@@ -235,15 +241,9 @@ status_t mil2_general_powerup()
|
||||
dump_pins();
|
||||
|
||||
//remove this:
|
||||
// various sensible defaults for MIL2
|
||||
si->ps.sdram = true;
|
||||
si->ps.memory_size = 2; //can override
|
||||
si->ps.memory_size = 4; //can override my mil2
|
||||
|
||||
// apsed TODO MIL2 TVP 3026 may be 135, 175, 220 or 250MHz
|
||||
// chip on my Millenium2 is TVP3026-250CPCE, 250MHz
|
||||
// rudolf: works in Mhz now
|
||||
si->ps.max_dac1_clock=250; // TVP3026
|
||||
fake_pins();
|
||||
LOG(2, ("INIT: Using faked PINS for now:\n"));
|
||||
dump_pins();
|
||||
//end remove this.
|
||||
|
||||
/* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */
|
||||
@@ -254,20 +254,20 @@ status_t mil2_general_powerup()
|
||||
LOG(2, ("INIT: Skipping card coldstart!\n"));
|
||||
mil2_dac_init();
|
||||
|
||||
//rudolf: sync on green test:
|
||||
/* disable 15bit mode CLUT-overlay function */
|
||||
//enable 'sync on green' option
|
||||
// DXIW(GENCTRL, DXIR(GENCTRL | 0x20));
|
||||
/* enable composite sync instead of Hsync only */
|
||||
// VGAW_I(CRTCEXT,3,(VGAR_I(CRTCEXT,3) | 0x40));
|
||||
//end sync on green test.
|
||||
//ok:
|
||||
/* disable overscan, select 0 IRE, select straight-through sync signals from CRTC */
|
||||
DXIW (GENCTRL, (DXIR (GENCTRL) & 0x0c));
|
||||
/* fixme: checkout if we need this sync inverting stuff: already done via CRTC!?!
|
||||
| (vsync_pos? 0x00:0x02)
|
||||
| (hsync_pos? 0x00:0x01)); */
|
||||
|
||||
/* 8-bit DAC, enable DAC */
|
||||
DXIW(MISCCTRL, 0x0c);
|
||||
//
|
||||
|
||||
VGAW_I(SEQ,1,0x00);
|
||||
/*enable screen*/
|
||||
return B_OK;
|
||||
|
||||
// apsed TODO MIL2 taken from G100, avoid DXIR/W DACR/W
|
||||
//rudolf: G100 version that was here nolonger exists, look at new implementation...
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -309,7 +309,6 @@ status_t g100_general_powerup()
|
||||
/* disable pixelclock oscillations before switching on CLUT */
|
||||
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
|
||||
/* disable 15bit mode CLUT-overlay function */
|
||||
//fixme: setup b5 later for 'sync on green' option
|
||||
DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
|
||||
/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
|
||||
DXIW(MISCCTRL,0x1b);
|
||||
@@ -349,12 +348,12 @@ status_t g100_general_powerup()
|
||||
/* wait 200uS minimum */
|
||||
snooze(250);
|
||||
|
||||
/* reset memory */
|
||||
/* reset memory (MACCESS is a write only register!) */
|
||||
ACCW(MACCESS, 0x00000000);
|
||||
/* select JEDEC reset method */
|
||||
ACCW(MACCESS,ACCR(MACCESS)|0x4000);
|
||||
ACCW(MACCESS, 0x00004000);
|
||||
/* perform actual RAM reset */
|
||||
ACCW(MACCESS,ACCR(MACCESS)|0x8000);
|
||||
ACCW(MACCESS, 0x0000c000);
|
||||
snooze(250);
|
||||
/* start memory refresh */
|
||||
CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
|
||||
@@ -412,7 +411,6 @@ status_t g200_general_powerup()
|
||||
/* disable pixelclock oscillations before switching on CLUT */
|
||||
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
|
||||
/* disable 15bit mode CLUT-overlay function */
|
||||
//fixme: setup b5 later for 'sync on green' option
|
||||
DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
|
||||
/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
|
||||
DXIW(MISCCTRL,0x1b);
|
||||
@@ -452,10 +450,10 @@ status_t g200_general_powerup()
|
||||
/* wait 200uS minimum */
|
||||
snooze(250);
|
||||
|
||||
/* reset memory */
|
||||
/* reset memory (MACCESS is a write only register!) */
|
||||
ACCW(MACCESS, 0x00000000);
|
||||
/* perform actual RAM reset */
|
||||
ACCW(MACCESS,ACCR(MACCESS)|0x8000);
|
||||
ACCW(MACCESS, 0x00008000);
|
||||
snooze(250);
|
||||
/* start memory refresh */
|
||||
CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
|
||||
@@ -512,7 +510,6 @@ status_t g400_general_powerup()
|
||||
/* disable pixelclock oscillations before switching on CLUT */
|
||||
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
|
||||
/* disable 15bit mode CLUT-overlay function */
|
||||
//fixme: setup b5 later for 'sync on green' option
|
||||
DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
|
||||
/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
|
||||
DXIW(MISCCTRL,0x9b);
|
||||
@@ -553,10 +550,10 @@ status_t g400_general_powerup()
|
||||
/* wait 200uS minimum */
|
||||
snooze(250);
|
||||
|
||||
/* reset memory */
|
||||
/* reset memory (MACCESS is a write only register!) */
|
||||
ACCW(MACCESS, 0x00000000);
|
||||
/* perform actual RAM reset */
|
||||
ACCW(MACCESS,ACCR(MACCESS)|0x8000);
|
||||
ACCW(MACCESS, 0x00008000);
|
||||
snooze(250);
|
||||
/* start memory refresh */
|
||||
CFGW(OPTION,(CFGR(OPTION)&0xffe07fff) | (si->ps.option_reg & 0x001f8000));
|
||||
@@ -584,10 +581,12 @@ status_t g400_general_powerup()
|
||||
static
|
||||
status_t g450_general_powerup()
|
||||
{
|
||||
//fixme: check if g450 and g550 powerup should be the same! (DAC outputconnector?)
|
||||
status_t result;
|
||||
uint32 pwr_cas[] = {0, 1, 5, 6, 7, 5, 2, 3};
|
||||
|
||||
/* used for convenience: MACCESS is a write only register! */
|
||||
uint32 maccess = 0x00000000;
|
||||
|
||||
LOG(4, ("INIT: G450/G550 powerup\n"));
|
||||
if (si->settings.logmask & 0x80000000) mga_dump_configuration_space();
|
||||
|
||||
@@ -607,8 +606,7 @@ status_t g450_general_powerup()
|
||||
DXIW(OUTPUTCONN,0x00);
|
||||
/* turn off both displays and the hardcursor (also disables transfers) */
|
||||
gx00_crtc_dpms(0,0,0);
|
||||
//fixme:
|
||||
//g400_crtc2_dpms(0,0,0);
|
||||
g400_crtc2_dpms(0,0,0);
|
||||
gx00_crtc_cursor_hide();
|
||||
|
||||
/* power up everything except DVI electronics (for now) */
|
||||
@@ -625,7 +623,6 @@ status_t g450_general_powerup()
|
||||
/* disable pixelclock oscillations before switching on CLUT */
|
||||
DXIW(PIXCLKCTRL, (DXIR(PIXCLKCTRL) | 0x04));
|
||||
/* disable 15bit mode CLUT-overlay function */
|
||||
//fixme: setup b5 later for 'sync on green' option
|
||||
DXIW(GENCTRL, DXIR(GENCTRL & 0xfd));
|
||||
/* CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC */
|
||||
DXIW(MISCCTRL,0x9b);
|
||||
@@ -663,7 +660,8 @@ status_t g450_general_powerup()
|
||||
/* set RAM read tap delays and mode register opcode / streamer flow control */
|
||||
ACCW(MEMRDBK, si->ps.memrdbk_reg);
|
||||
/* b7 v5_mem_type = done by Mark Watson. fixme: still confirm! (unknown bits) */
|
||||
ACCW(MACCESS, ((((uint32)si->ps.v5_mem_type) & 0x80) >> 1));
|
||||
maccess = ((((uint32)si->ps.v5_mem_type) & 0x80) >> 1);
|
||||
ACCW(MACCESS, maccess);
|
||||
/* clear b0-1 and 3, and set b31 in option4: re-enable memory clock */
|
||||
CFGW(OPTION4, ((si->ps.option4_reg & 0x60000004) | 0x80000000));
|
||||
snooze(250);
|
||||
@@ -675,7 +673,8 @@ status_t g450_general_powerup()
|
||||
if (!(si->ps.v5_mem_type & 0x0100))
|
||||
{
|
||||
/* clear unknown bits */
|
||||
ACCW(MACCESS, 0x00000000);
|
||||
maccess = 0x00000000;
|
||||
ACCW(MACCESS, maccess);
|
||||
/* clear b12: unknown bit */
|
||||
ACCW(MEMRDBK, (si->ps.memrdbk_reg & 0xffffefff));
|
||||
}
|
||||
@@ -689,8 +688,8 @@ status_t g450_general_powerup()
|
||||
}
|
||||
|
||||
/* create positive flank to generate memory reset */
|
||||
ACCW(MACCESS,ACCR(MACCESS) & 0xffff7fff);
|
||||
ACCW(MACCESS,ACCR(MACCESS) | 0x00008000);
|
||||
ACCW(MACCESS, (maccess & 0xffff7fff));
|
||||
ACCW(MACCESS, (maccess | 0x00008000));
|
||||
snooze(250);
|
||||
|
||||
/* start memory refresh */
|
||||
@@ -724,6 +723,9 @@ status_t g450_general_powerup()
|
||||
/*turn on display one*/
|
||||
gx00_crtc_dpms(1,1,1);
|
||||
|
||||
/* enable 'straight-through' sync outputs on both analog output connectors */
|
||||
DXIW(SYNCCTRL,0x00);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -763,27 +765,62 @@ status_t gx00_general_dac_select(int dac)
|
||||
/*MISCCTRL, clock src,...*/
|
||||
switch(dac)
|
||||
{
|
||||
/* G400 */
|
||||
case DS_CRTC1DAC_CRTC2MAVEN:
|
||||
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); /*internal clk*/
|
||||
CR2W(CTL,(CR2R(CTL)&0xffe00779)|0xD0000002); /*external clk*/
|
||||
VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0x77));
|
||||
/* connect CRTC1 to pixPLL */
|
||||
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1);
|
||||
/* connect CRTC2 to vidPLL, connect CRTC1 to internal DAC and
|
||||
* enable CRTC2 external video timing reset signal.
|
||||
* (Setting for MAVEN 'master mode' TVout signal generation.) */
|
||||
CR2W(CTL,(CR2R(CTL)&0xffe00779)|0xD0000002);
|
||||
/* disable CRTC1 external video timing reset signal */
|
||||
VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)&0x77));
|
||||
/* select CRTC2 RGB24 MAFC mode: connects CRTC2 to MAVEN DAC */
|
||||
DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x82);
|
||||
break;
|
||||
case DS_CRTC1MAVEN_CRTC2DAC:
|
||||
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x2); /*external clk*/
|
||||
CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x1<<20)); /*internal clk*/
|
||||
/* connect CRTC1 to vidPLL */
|
||||
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x2);
|
||||
/* connect CRTC2 to pixPLL and internal DAC and
|
||||
* disable CRTC2 external video timing reset signal */
|
||||
CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x1<<20));
|
||||
/* enable CRTC1 external video timing reset signal.
|
||||
* note: this is nolonger used as G450/G550 cannot do TVout on CRTC1 */
|
||||
VGAW_I(CRTCEXT,1,(VGAR_I(CRTCEXT,1)|0x88));
|
||||
/* select CRTC1 RGB24 MAFC mode: connects CRTC1 to MAVEN DAC */
|
||||
DXIW(MISCCTRL,(DXIR(MISCCTRL)&0x19)|0x02);
|
||||
break;
|
||||
/* G450/G550 */
|
||||
case DS_CRTC1CON1_CRTC2CON2:
|
||||
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); /*internal clk*/
|
||||
CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x0<<20)); /*internal clk - no DAC PTR*/
|
||||
/* connect CRTC1 to pixPLL */
|
||||
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1);
|
||||
/* connect CRTC2 to vidPLL, connect CRTC1 to DAC1, disable CRTC2
|
||||
* external video timing reset signal, set CRTC2 progressive scan mode
|
||||
* and disable TVout mode (b12).
|
||||
* (Setting for MAVEN 'slave mode' TVout signal generation.) */
|
||||
//fixme: enable timing resets if TVout is used in master mode!
|
||||
//otherwise keep it disabled.
|
||||
CR2W(CTL,(CR2R(CTL)&0x2de00779)|0x6|(0x0<<20));
|
||||
/* connect DAC1 to CON1, CRTC2/'DAC2' to CON2 (monitor mode) */
|
||||
DXIW(OUTPUTCONN,0x09);
|
||||
/* Select 1.5 Volt MAVEN DAC ref. for monitor mode */
|
||||
DXIW(GENIOCTRL, DXIR(GENIOCTRL) & ~0x40);
|
||||
DXIW(GENIODATA, 0x00);
|
||||
break;
|
||||
//fixme: toggle PLL's below if possible:
|
||||
// otherwise toggle PLL's for G400 2nd case?
|
||||
case DS_CRTC1CON2_CRTC2CON1:
|
||||
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1); /*internal clk*/
|
||||
CR2W(CTL,(CR2R(CTL)&0x2fe00779)|0x4|(0x1<<20)); /*internal clk - gets DAC*/
|
||||
/* connect CRTC1 to pixPLL */
|
||||
DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0xc)|0x1);
|
||||
/* connect CRTC2 to vidPLL and DAC1, disable CRTC2 external
|
||||
* video timing reset signal, and set CRTC2 progressive scan mode and
|
||||
* disable TVout mode (b12). */
|
||||
CR2W(CTL,(CR2R(CTL)&0x2de00779)|0x6|(0x1<<20));
|
||||
/* connect DAC1 to CON2 (monitor mode), CRTC2/'DAC2' to CON1 */
|
||||
DXIW(OUTPUTCONN,0x05);
|
||||
/* Select 1.5 Volt MAVEN DAC ref. for monitor mode */
|
||||
DXIW(GENIOCTRL, DXIR(GENIOCTRL) & ~0x40);
|
||||
DXIW(GENIODATA, 0x00);
|
||||
break;
|
||||
default:
|
||||
return B_ERROR;
|
||||
@@ -817,13 +854,34 @@ status_t gx00_general_bios_to_powergraphics()
|
||||
VGAW(MISCW,0x08);
|
||||
/*set only MGA pixel clock in MISC - I don't want to map VGA stuff under this OS*/
|
||||
|
||||
if (si->ps.card_type >= G100) {
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
case G400:
|
||||
case G400MAX:
|
||||
/* makes CRTC2 stable! Matrox specify 8, but use 4 - grrrr! */
|
||||
DXIW(MAFCDEL,0x02);
|
||||
break;
|
||||
case G450:
|
||||
case G550:
|
||||
/* power up everything except DVI electronics (for now) */
|
||||
DXIW(PWRCTRL,0x1b);
|
||||
/* enable 'straight-through' sync outputs on both analog output connectors */
|
||||
DXIW(SYNCCTRL,0x00);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (si->ps.card_type >= G100)
|
||||
{
|
||||
DXIW(MISCCTRL,0x9b);
|
||||
/*CRTC2->MAFC, 8-bit DAC, CLUT enabled, enable DAC*/
|
||||
|
||||
DXIW(MULCTRL,0x4);
|
||||
/*RGBA direct mode*/
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(8, ("INIT: < G100 DAC powerup badly implemented, MISC 0x%02x\n", VGAR(MISCR)));
|
||||
} // apsed TODO MIL2
|
||||
|
||||
@@ -832,3 +890,193 @@ status_t gx00_general_bios_to_powergraphics()
|
||||
|
||||
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. */
|
||||
//fixme: seperate heads for real dualhead modes:
|
||||
//CRTC1 and 2 constraints differ!
|
||||
status_t gx00_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
/* determine pixel multiple based on 2D/3D engine constraints */
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
case MIL1:
|
||||
case MIL2:
|
||||
/* see MIL1/2 specs:
|
||||
* these cards always use a 64bit RAMDAC (TVP3026) and interleaved memory */
|
||||
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;
|
||||
case B_RGB32: acc_mask = 0x1f; depth = 32; break;
|
||||
default:
|
||||
LOG(8,("INIT: unknown color space: 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;
|
||||
case B_RGB32: depth = 32; break;
|
||||
default:
|
||||
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
|
||||
return B_ERROR;
|
||||
}
|
||||
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.) */
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
case MIL1:
|
||||
case MIL2:
|
||||
/* see MIL1/2 specs:
|
||||
* these cards always use a 64bit RAMDAC and interleaved memory */
|
||||
switch (target->space)
|
||||
{
|
||||
case B_CMAP8: crtc_mask = 0x7f; break;
|
||||
case B_RGB15: crtc_mask = 0x3f; break;
|
||||
case B_RGB16: crtc_mask = 0x3f; break;
|
||||
/* for B_RGB24 crtc_mask 0x7f is worst case scenario (MIL2 constraint) */
|
||||
case B_RGB24: crtc_mask = 0x7f; break;
|
||||
case B_RGB32: crtc_mask = 0x1f; break;
|
||||
default:
|
||||
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
|
||||
return B_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* see G100 and up specs */
|
||||
switch (target->space)
|
||||
{
|
||||
case B_CMAP8: crtc_mask = 0x0f; break;
|
||||
case B_RGB15: crtc_mask = 0x07; break;
|
||||
case B_RGB16: crtc_mask = 0x07; break;
|
||||
case B_RGB24: crtc_mask = 0x0f; break;
|
||||
case B_RGB32: crtc_mask = 0x03; break;
|
||||
default:
|
||||
LOG(8,("INIT: unknown color space: 0x%08x\n", target->space));
|
||||
return B_ERROR;
|
||||
}
|
||||
/* see G400 specs: CRTC2 has different constraints */
|
||||
/* Note:
|
||||
* set for RGB and B_YCbCr422 modes. Other modes need larger multiples! */
|
||||
if (target->flags & DUALHEAD_BITS)
|
||||
{
|
||||
switch (target->space)
|
||||
{
|
||||
case B_RGB16: crtc_mask = 0x1f; break;
|
||||
case B_RGB32: crtc_mask = 0x0f; break;
|
||||
default:
|
||||
LOG(8,("INIT: illegal DH color space: 0x%08x\n", target->space));
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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 MIL1:
|
||||
case MIL2:
|
||||
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;
|
||||
|
||||
/* 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. */
|
||||
{
|
||||
/* 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;
|
||||
case B_RGB32_LITTLE:
|
||||
if (target->virtual_width > (4092 & ~crtc_mask))
|
||||
target->virtual_width = (4092 & ~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;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/* some bits are hacks, where PINS is not known */
|
||||
/* Authors:
|
||||
Mark Watson 2/2000,
|
||||
Rudolf Cornelissen 10-11/2002
|
||||
Rudolf Cornelissen 10/2002-4/2003
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00002000
|
||||
@@ -111,52 +111,80 @@ status_t parse_pins ()
|
||||
|
||||
status_t pins1_read(uint8 *pins, uint8 length)
|
||||
{
|
||||
//remove later on here:
|
||||
// float f_ref; /* PLL reference-oscillator frequency */
|
||||
// uint32 max_system_vco; /* graphics engine PLL VCO limits */
|
||||
// uint32 min_system_vco;
|
||||
// uint32 max_pixel_vco; /* dac1 PLL VCO limits */
|
||||
// uint32 min_pixel_vco;
|
||||
// uint32 max_video_vco; /* dac2, maven PLL VCO limits */
|
||||
// uint32 min_video_vco;
|
||||
// uint32 std_engine_clock; /* graphics engine clock speed needed */
|
||||
// uint32 std_engine_clock_dh;
|
||||
// uint32 max_dac1_clock; /* dac1 limits */
|
||||
// uint32 max_dac1_clock_8; /* dac1 limits correlated to RAMspeed limits */
|
||||
// uint32 max_dac1_clock_16;
|
||||
// uint32 max_dac1_clock_24;
|
||||
// uint32 max_dac1_clock_32;
|
||||
// uint32 max_dac1_clock_32dh;
|
||||
// uint32 max_dac2_clock; /* dac2 limits */
|
||||
// uint32 max_dac2_clock_8; /* dac2, maven limits correlated to RAMspeed limits */
|
||||
// uint32 max_dac2_clock_16;
|
||||
// uint32 max_dac2_clock_24;
|
||||
// uint32 max_dac2_clock_32;
|
||||
// uint32 max_dac2_clock_32dh;
|
||||
// bool secondary_head; /* presence of functions */
|
||||
// bool secondary_tvout;
|
||||
// bool primary_dvi;
|
||||
// bool secondary_dvi;
|
||||
// uint32 memory_size; /* memory in Mb */
|
||||
// uint32 mctlwtst_reg; /* memory control waitstate register */
|
||||
// uint32 memrdbk_reg; /* memory readback register */
|
||||
// uint32 option_reg; /* option register */
|
||||
// uint32 option2_reg; /* option2 register */
|
||||
// uint32 option3_reg; /* option3 register */
|
||||
// uint32 option4_reg; /* option4 register */
|
||||
// uint8 v3_option2_reg;
|
||||
// uint8 v3_clk_div; /* pins v3 memory and system clock division factors */
|
||||
// uint8 v3_mem_type; /* pins v3 memory type info */
|
||||
// uint16 v5_mem_type; /* pins v5 memory type info */
|
||||
// bool sdram;
|
||||
//end remove later on here.
|
||||
if (length != 64)
|
||||
{
|
||||
LOG(8,("INFO: wrong PINS length, expected 64, got %d\n", length));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
//fixme: implement this..
|
||||
return B_ERROR;
|
||||
//reset all for test:
|
||||
//float:
|
||||
si->ps.f_ref = 0;
|
||||
//uint32:
|
||||
si->ps.max_system_vco = 0;
|
||||
si->ps.min_system_vco = 0;
|
||||
si->ps.min_pixel_vco = 0;
|
||||
si->ps.min_video_vco = 0;
|
||||
si->ps.std_engine_clock_dh = 0;
|
||||
si->ps.max_dac1_clock_32 = 0;
|
||||
si->ps.max_dac1_clock_32dh = 0;
|
||||
si->ps.memory_size = 0;
|
||||
si->ps.mctlwtst_reg = 0;
|
||||
si->ps.memrdbk_reg = 0;
|
||||
si->ps.option2_reg = 0;
|
||||
si->ps.option3_reg = 0;
|
||||
si->ps.option4_reg = 0;
|
||||
//uint8:
|
||||
si->ps.v3_option2_reg = 0;
|
||||
si->ps.v3_clk_div = 0;
|
||||
si->ps.v3_mem_type = 0;
|
||||
//uint16:
|
||||
si->ps.v5_mem_type = 0;
|
||||
//bools:
|
||||
si->ps.secondary_head = false;
|
||||
si->ps.secondary_tvout = false;
|
||||
si->ps.primary_dvi = false;
|
||||
si->ps.secondary_dvi = false;
|
||||
si->ps.sdram = true;
|
||||
|
||||
//experimental: checkout!
|
||||
si->ps.max_dac1_clock_32 = pins[22];//ramdac
|
||||
si->ps.max_pixel_vco = (pins[25] << 8) | pins[24];//PCLK
|
||||
si->ps.std_engine_clock = (pins[29] << 8) | pins[28];
|
||||
if (((pins[31] << 8) | pins[30]) < si->ps.std_engine_clock)
|
||||
si->ps.std_engine_clock = (pins[31] << 8) | pins[30];
|
||||
if (((pins[33] << 8) | pins[32]) < si->ps.std_engine_clock)
|
||||
si->ps.std_engine_clock = (pins[33] << 8) | pins[32];
|
||||
|
||||
//temp. test to see some vals..
|
||||
si->ps.max_video_vco = (pins[27] << 8) | pins[26];//LCLK
|
||||
//feature flags:
|
||||
si->ps.option_reg = (pins[53] << 24) | (pins[52] << 16) | (pins[51] << 8) | pins [50];
|
||||
|
||||
si->ps.max_dac2_clock = (pins[35] << 8) | pins[34];//clkmod
|
||||
si->ps.max_dac2_clock_8 = (pins[37] << 8) | pins[36];//testclk
|
||||
si->ps.max_dac2_clock_16 = (pins[39] << 8) | pins[38];//vgafreq1
|
||||
si->ps.max_dac2_clock_24 = (pins[41] << 8) | pins[40];//vgafreq2
|
||||
si->ps.max_dac2_clock_32 = (pins[55] << 8) | pins[54];//vga clock
|
||||
si->ps.max_dac2_clock_32dh = pins[58];//vid ctrl
|
||||
|
||||
si->ps.max_dac1_clock = (pins[29] << 8) | pins[28];//clkbase
|
||||
si->ps.max_dac1_clock_8 = (pins[31] << 8) | pins[30];//4mb
|
||||
si->ps.max_dac1_clock_16 = (pins[33] << 8) | pins[32];//8mb
|
||||
si->ps.max_dac1_clock_24 = pins[23];//ramdac type
|
||||
|
||||
//test! Don't actually use the reported settings for now...
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t pins2_read(uint8 *pins, uint8 length)
|
||||
{
|
||||
if (length != 64)
|
||||
{
|
||||
LOG(8,("INFO: wrong PINS length, expected 64, got %d\n", length));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
LOG(2,("INFO: PINS version 2 details not yet known\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
@@ -424,18 +452,15 @@ status_t pins5_read(uint8 *pins, uint8 length)
|
||||
}
|
||||
|
||||
/* fill out the shared info si->ps struct */
|
||||
if (pins[4]) m_factor = 8;
|
||||
if (pins[4] == 0x01) m_factor = 8;
|
||||
if (pins[4] >= 0x02) m_factor = 10;
|
||||
|
||||
si->ps.max_system_vco = m_factor * pins[36];
|
||||
si->ps.max_video_vco = m_factor * pins[37];
|
||||
/* pixelVCO multiplier is 10 if pins V5.2 */
|
||||
if (pins[4] == 0x02) si->ps.max_pixel_vco = 10 * pins[38];
|
||||
else si->ps.max_pixel_vco = m_factor * pins[38];
|
||||
si->ps.max_pixel_vco = m_factor * pins[38];
|
||||
si->ps.min_system_vco = m_factor * pins[121];
|
||||
si->ps.min_video_vco = m_factor * pins[122];
|
||||
/* pixelVCO multiplier is 10 if pins V5.2 */
|
||||
if (pins[4] == 0x02) si->ps.min_pixel_vco = 10 * pins[123];
|
||||
else si->ps.min_pixel_vco = m_factor * pins[123];
|
||||
si->ps.min_pixel_vco = m_factor * pins[123];
|
||||
|
||||
if (pins[39] == 0xff) si->ps.max_dac1_clock_8 = si->ps.max_pixel_vco;
|
||||
else si->ps.max_dac1_clock_8 = 4 * pins[39];
|
||||
@@ -517,6 +542,9 @@ void fake_pins(void)
|
||||
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
case MIL1:
|
||||
pinsmil1_fake();
|
||||
break;
|
||||
case MIL2:
|
||||
pinsmil2_fake();
|
||||
break;
|
||||
@@ -541,15 +569,16 @@ void fake_pins(void)
|
||||
}
|
||||
|
||||
/* find out if the card has a maven */
|
||||
if (i2c_maven_probe() == B_OK)
|
||||
si->ps.secondary_tvout = false;
|
||||
si->ps.secondary_head = false;
|
||||
/* only do I2C probe if the card has a chance */
|
||||
if (si->ps.card_type >= G100)
|
||||
{
|
||||
si->ps.secondary_tvout = true;
|
||||
si->ps.secondary_head = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
si->ps.secondary_tvout = false;
|
||||
si->ps.secondary_head = false;
|
||||
if (i2c_maven_probe() == B_OK)
|
||||
{
|
||||
si->ps.secondary_tvout = true;
|
||||
si->ps.secondary_head = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* not used because no coldstart will be attempted */
|
||||
@@ -567,8 +596,82 @@ void fake_pins(void)
|
||||
si->ps.v5_mem_type = 0;
|
||||
}
|
||||
|
||||
void pinsmil1_fake(void)
|
||||
{
|
||||
/* 'worst case' scenario defaults, overrule-able via mga.settings if needed */
|
||||
|
||||
si->ps.f_ref = 14.31818;
|
||||
/* see MIL1 specs */
|
||||
si->ps.max_system_vco = 220;
|
||||
si->ps.min_system_vco = 110;
|
||||
si->ps.max_pixel_vco = 220;
|
||||
si->ps.min_pixel_vco = 110;
|
||||
/* no specs, assuming these */
|
||||
si->ps.max_video_vco = 0;
|
||||
si->ps.min_video_vco = 0;
|
||||
/* see MIL1 specs */
|
||||
si->ps.max_dac1_clock = 220;
|
||||
si->ps.max_dac1_clock_8 = 220;
|
||||
si->ps.max_dac1_clock_16 = 200;
|
||||
/* 'failsave' values */
|
||||
si->ps.max_dac1_clock_24 = 180;
|
||||
si->ps.max_dac1_clock_32 = 136;
|
||||
si->ps.max_dac1_clock_32dh = 0;
|
||||
/* see specs */
|
||||
si->ps.max_dac2_clock = 0;
|
||||
si->ps.max_dac2_clock_8 = 0;
|
||||
si->ps.max_dac2_clock_16 = 0;
|
||||
si->ps.max_dac2_clock_24 = 0;
|
||||
si->ps.max_dac2_clock_32 = 0;
|
||||
/* 'failsave' value */
|
||||
si->ps.max_dac2_clock_32dh = 0;
|
||||
si->ps.primary_dvi = false;
|
||||
si->ps.secondary_dvi = false;
|
||||
/* presume 2Mb RAM mounted */
|
||||
//fixme: see if we can get this from OPTION or so...
|
||||
si->ps.memory_size = 2;
|
||||
//fixme: should be overrule-able via mga.settings for MIL1.
|
||||
//fail-safe mode for now:
|
||||
si->ps.sdram = true;
|
||||
}
|
||||
|
||||
void pinsmil2_fake(void)
|
||||
{
|
||||
/* 'worst case' scenario defaults, overrule-able via mga.settings if needed */
|
||||
|
||||
si->ps.f_ref = 14.31818;
|
||||
/* see MIL2 specs */
|
||||
si->ps.max_system_vco = 220;
|
||||
si->ps.min_system_vco = 110;
|
||||
si->ps.max_pixel_vco = 220;
|
||||
si->ps.min_pixel_vco = 110;
|
||||
/* no specs, assuming these */
|
||||
si->ps.max_video_vco = 0;
|
||||
si->ps.min_video_vco = 0;
|
||||
/* see MIL2 specs */
|
||||
si->ps.max_dac1_clock = 220;
|
||||
si->ps.max_dac1_clock_8 = 220;
|
||||
si->ps.max_dac1_clock_16 = 200;
|
||||
/* 'failsave' values */
|
||||
si->ps.max_dac1_clock_24 = 180;
|
||||
si->ps.max_dac1_clock_32 = 136;
|
||||
si->ps.max_dac1_clock_32dh = 0;
|
||||
/* see specs */
|
||||
si->ps.max_dac2_clock = 0;
|
||||
si->ps.max_dac2_clock_8 = 0;
|
||||
si->ps.max_dac2_clock_16 = 0;
|
||||
si->ps.max_dac2_clock_24 = 0;
|
||||
si->ps.max_dac2_clock_32 = 0;
|
||||
/* 'failsave' value */
|
||||
si->ps.max_dac2_clock_32dh = 0;
|
||||
si->ps.primary_dvi = false;
|
||||
si->ps.secondary_dvi = false;
|
||||
/* presume 4Mb RAM mounted */
|
||||
//fixme: see if we can get this from OPTION or so...
|
||||
si->ps.memory_size = 4;
|
||||
//fixme: should be overrule-able via mga.settings for MIL2.
|
||||
//fail-safe mode for now:
|
||||
si->ps.sdram = true;
|
||||
}
|
||||
|
||||
void pinsg100_fake(void)
|
||||
@@ -741,12 +844,12 @@ void pinsg450_fake(void)
|
||||
si->ps.f_ref = 27.000;
|
||||
/* see G450 pins readouts for max ranges, then use a bit smaller ones */
|
||||
/* carefull not to take to high lower limits, and high should be >= 2x low. */
|
||||
si->ps.max_system_vco = 600;
|
||||
si->ps.min_system_vco = 256;
|
||||
si->ps.max_system_vco = 640;
|
||||
si->ps.min_system_vco = 320;
|
||||
si->ps.max_pixel_vco = 640;
|
||||
si->ps.min_pixel_vco = 320;
|
||||
si->ps.max_video_vco = 600;
|
||||
si->ps.min_video_vco = 256;
|
||||
si->ps.max_video_vco = 640;
|
||||
si->ps.min_video_vco = 320;
|
||||
si->ps.max_dac1_clock = 360;
|
||||
si->ps.max_dac1_clock_8 = 360;
|
||||
si->ps.max_dac1_clock_16 = 360;
|
||||
@@ -786,8 +889,8 @@ void pinsg550_fake(void)
|
||||
si->ps.min_system_vco = 384;
|
||||
si->ps.max_pixel_vco = 960;
|
||||
si->ps.min_pixel_vco = 320;
|
||||
si->ps.max_video_vco = 600;
|
||||
si->ps.min_video_vco = 256;
|
||||
si->ps.max_video_vco = 960;
|
||||
si->ps.min_video_vco = 320;
|
||||
si->ps.max_dac1_clock = 360;
|
||||
si->ps.max_dac1_clock_8 = 360;
|
||||
si->ps.max_dac1_clock_16 = 360;
|
||||
|
||||
@@ -1,76 +1,114 @@
|
||||
/* program the MAVEN in monitor mode */
|
||||
/* Thanx to Petr Vandrovec for info on the MAVEN */
|
||||
/* Mark Watson 6/2000 */
|
||||
|
||||
/* Authors:
|
||||
Mark Watson 6/2000,
|
||||
Rudolf Cornelissen 1/2003-4/2003
|
||||
|
||||
Thanx to Petr Vandrovec for writing matroxfb.
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00001000
|
||||
|
||||
#include "mga_std.h"
|
||||
|
||||
status_t g450_g550_maven_set_vid_pll(display_mode target);
|
||||
status_t g100_g400max_maven_set_vid_pll(display_mode target);
|
||||
|
||||
status_t gx00_maven_dpms(uint8 display,uint8 h,uint8 v)
|
||||
{
|
||||
if (display&h&v)
|
||||
/* this function is nolonger needed on G450/G550 cards */
|
||||
if (si->ps.card_type > G400MAX) return B_OK;
|
||||
|
||||
if (display & h & v)
|
||||
{
|
||||
MAVW(MONEN,0xb2);
|
||||
MAVW(MONSET,0x20); /*must be set to this in monitor mode*/
|
||||
MAVW(OUTMODE,3); /*monitor mode*/
|
||||
MAVW(STABLE,0x22); /*makes picture stable?*/
|
||||
MAVW(TEST,0x00); /*turn off test signal*/
|
||||
/* turn on screen */
|
||||
if (!(si->dm.flags & TV_BITS))
|
||||
{
|
||||
/* monitor mode */
|
||||
MAVW(MONEN, 0xb2);
|
||||
MAVW(MONSET, 0x20); /* must be set to this in monitor mode */
|
||||
MAVW(OUTMODE, 0x03); /* output: monitor mode */
|
||||
MAVW(STABLE, 0x22); /* makes picture stable? */
|
||||
MAVW(TEST, 0x00); /* turn off test signal */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TVout mode */
|
||||
MAVW(MONEN, 0xb3);
|
||||
MAVW(MONSET, 0x20);
|
||||
MAVW(OUTMODE, 0x08); /* output: SVideo/Composite */
|
||||
MAVW(STABLE, 0x02); /* makes picture stable? */
|
||||
//fixme? linux uses 0x14...
|
||||
MAVW(TEST, (MAVR(TEST) & 0x10));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*turn off screen using a few methods!*/
|
||||
MAVW(STABLE,0x6a);
|
||||
// MAVW(TEST,0x3);
|
||||
MAVW(OUTMODE,0x00);
|
||||
/* turn off screen using a few methods! */
|
||||
MAVW(STABLE, 0x6a);
|
||||
// MAVW(TEST, 0x03);
|
||||
MAVW(OUTMODE, 0x00);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*set a mode line - inputs are in pixels/scanlines*/
|
||||
status_t gx00_maven_set_timing(
|
||||
uint32 hdisp_e,uint32 hsync_s,uint32 hsync_e,uint32 htotal,
|
||||
uint32 vdisp_e,uint32 vsync_s,uint32 vsync_e,uint32 vtotal,
|
||||
uint8 hsync_pos,uint8 vsync_pos
|
||||
)
|
||||
status_t gx00_maven_set_timing(display_mode target)
|
||||
{
|
||||
/* this function is nolonger needed on G450/G550 cards */
|
||||
if (si->ps.card_type > G400MAX) return B_OK;
|
||||
|
||||
LOG(4,("MAVEN: setting timing\n"));
|
||||
|
||||
/*check horizontal timing parameters are to nearest 8 pixels*/
|
||||
if ((hdisp_e&7)|(hsync_s&7)|(hsync_e&7)|(htotal&7))
|
||||
if ((target.timing.h_display & 0x07) |
|
||||
(target.timing.h_sync_start & 0x07) |
|
||||
(target.timing.h_sync_end & 0x07) |
|
||||
(target.timing.h_total & 0x07))
|
||||
{
|
||||
LOG(8,("MAVEN:Horizontal timings are not multiples of 8 pixels\n"));
|
||||
LOG(8,("MAVEN: Horizontal timing is not multiples of 8 pixels\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/*program the MAVEN*/
|
||||
MAVWW(LASTLINEL,htotal);
|
||||
MAVWW(HSYNCLENL,(hsync_e-hsync_s));
|
||||
MAVWW(HSYNCSTRL,(htotal-hsync_s));
|
||||
MAVWW(HDISPLAYL,(htotal-hsync_s+hdisp_e));
|
||||
MAVWW(HTOTALL,(htotal+1));
|
||||
MAVWW(LASTLINEL, target.timing.h_total);
|
||||
MAVWW(HSYNCLENL, (target.timing.h_sync_end - target.timing.h_sync_start));
|
||||
MAVWW(HSYNCSTRL, (target.timing.h_total - target.timing.h_sync_start));
|
||||
MAVWW(HDISPLAYL, ((target.timing.h_total - target.timing.h_sync_start) +
|
||||
target.timing.h_display));
|
||||
MAVWW(HTOTALL, (target.timing.h_total + 1));
|
||||
|
||||
MAVWW(VSYNCLENL,(vsync_e-vsync_s-1));
|
||||
MAVWW(VSYNCSTRL,(vtotal-vsync_s));
|
||||
MAVWW(VDISPLAYL,(vtotal-1));
|
||||
MAVWW(VTOTALL,(vtotal-1));
|
||||
MAVWW(VSYNCLENL, (target.timing.v_sync_end - target.timing.v_sync_start - 1));
|
||||
MAVWW(VSYNCSTRL, (target.timing.v_total - target.timing.v_sync_start));
|
||||
MAVWW(VDISPLAYL, (target.timing.v_total - 1));
|
||||
MAVWW(VTOTALL, (target.timing.v_total - 1));
|
||||
|
||||
MAVWW(HVIDRSTL,(htotal-si->crtc_delay));
|
||||
MAVWW(VVIDRSTL,(vtotal-2));
|
||||
MAVWW(HVIDRSTL, (target.timing.h_total - si->crtc_delay));
|
||||
MAVWW(VVIDRSTL, (target.timing.v_total - 2));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
//not used:
|
||||
/*
|
||||
void gx00_maven_delay(int number)
|
||||
{
|
||||
// this function is nolonger needed on G450/G550 cards
|
||||
if (si->ps.card_type > G400MAX) return;
|
||||
|
||||
MAVWW(HVIDRSTL,(si->dm.timing.h_total-number));
|
||||
}
|
||||
*/
|
||||
|
||||
/*set the mode, brightness is a value from 0->2 (where 1 is equivalent to direct)*/
|
||||
status_t gx00_maven_mode(int mode,float brightness)
|
||||
{
|
||||
uint8 luma;
|
||||
|
||||
/* this function is nolonger needed on G450/G550 cards */
|
||||
if (si->ps.card_type > G400MAX) return B_OK;
|
||||
|
||||
/*set luma to a suitable value for brightness*/
|
||||
/*assuming 1A is a sensible value*/
|
||||
luma = (uint8)(0x1a * brightness);
|
||||
@@ -80,93 +118,442 @@ status_t gx00_maven_mode(int mode,float brightness)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*program the pixpll on the maven - frequency in kHz*/
|
||||
status_t gx00_maven_set_pix_pll(float f_vco)
|
||||
status_t gx00_maven_set_vid_pll(display_mode target)
|
||||
{
|
||||
switch (si->ps.card_type)
|
||||
{
|
||||
case G450:
|
||||
case G550:
|
||||
return g450_g550_maven_set_vid_pll(target);
|
||||
break;
|
||||
default:
|
||||
return g100_g400max_maven_set_vid_pll(target);
|
||||
break;
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t g450_g550_maven_set_vid_pll(display_mode target)
|
||||
{
|
||||
uint8 m=0,n=0,p=0;
|
||||
uint time = 0;
|
||||
|
||||
float pix_setting;
|
||||
float pix_setting, req_pclk;
|
||||
status_t result;
|
||||
|
||||
LOG(4,("MAVEN:Setting PIX PLL %fMHz\n", f_vco));
|
||||
req_pclk = (target.timing.pixel_clock)/1000.0;
|
||||
LOG(4,("MAVEN: Setting VID PLL for pixelclock %f\n", req_pclk));
|
||||
|
||||
result = gx00_maven_pix_pll_find(f_vco,&pix_setting,&m,&n,&p);
|
||||
result = g450_g550_maven_vid_pll_find(target,&pix_setting,&m,&n,&p, 1);
|
||||
if (result != B_OK)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/*reprogram (select,wait for stability)*/
|
||||
MAVW(PIXPLLM,(m)); /*set m value*/
|
||||
MAVW(PIXPLLN,(n)); /*set n value*/
|
||||
MAVW(PIXPLLP,(p|0x80)); /*set p value*/
|
||||
LOG(2,("MAVEN: Clocks found: %x %x %x\n",m,n,p));
|
||||
delay(1000); /*wait 1000us for PIXPLL to lock (no way of knowing)*/
|
||||
LOG(2,("MAVEN: PIX PLL frequency locked\n"));
|
||||
|
||||
/*reprogram (disable,select,wait for stability,enable)*/
|
||||
CR2W(CTL, (CR2R(CTL) | 0x08)); /* disable the VIDPLL */
|
||||
CR2W(CTL, (CR2R(CTL) | 0x06)); /* select the VIDPLL */
|
||||
DXIW(VIDPLLM,(m)); /* set m value */
|
||||
DXIW(VIDPLLN,(n)); /* set n value */
|
||||
DXIW(VIDPLLP,(p)); /* set p value */
|
||||
|
||||
/* Wait for the VIDPLL frequency to lock until timeout occurs */
|
||||
while((!(DXIR(VIDPLLSTAT) & 0x40)) & (time <= 2000))
|
||||
{
|
||||
time++;
|
||||
snooze(1);
|
||||
}
|
||||
|
||||
if (time > 2000)
|
||||
LOG(2,("MAVEN: VID PLL frequency not locked!\n"));
|
||||
else
|
||||
LOG(2,("MAVEN: VID PLL frequency locked\n"));
|
||||
CR2W(CTL, (CR2R(CTL) & ~0x08)); /* enable the VIDPLL */
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*find nearest valid pix pll*/
|
||||
status_t gx00_maven_pix_pll_find(float f_vco,float * result,uint8 * m_result,uint8 * n_result,uint8 * p_result)
|
||||
/* program the video PLL in the MAVEN */
|
||||
status_t g100_g400max_maven_set_vid_pll(display_mode target)
|
||||
{
|
||||
float f_ref=27.000;
|
||||
int n_min=4;
|
||||
int n_max=127;
|
||||
int m_min=2;
|
||||
int m_max=31;
|
||||
int m=0,n=0,p=0;
|
||||
float error;
|
||||
float error_best;
|
||||
int best[3];
|
||||
float f_rat;
|
||||
uint8 m=0,n=0,p=0;
|
||||
|
||||
LOG(4,("MAVEN:Checking PIX PLL %fMHz\n", f_vco));
|
||||
float pix_setting, req_pclk;
|
||||
status_t result;
|
||||
|
||||
/*f_rat.m/p=n where m=M+1,n=N+1,p=P+1,f_rat=f_vco/f_ref*/
|
||||
f_rat = f_vco/f_ref;
|
||||
error_best = 999999999;
|
||||
for (p=0x2 -1*(f_vco>80.0);p<0x10;p=p<<1)
|
||||
req_pclk = (target.timing.pixel_clock)/1000.0;
|
||||
LOG(4,("MAVEN: Setting VID PLL for pixelclock %f\n", req_pclk));
|
||||
|
||||
result = g100_g400max_maven_vid_pll_find(target,&pix_setting,&m,&n,&p);
|
||||
if (result != B_OK)
|
||||
{
|
||||
for (m=m_min;m<m_max;m++)
|
||||
{
|
||||
/*calculate n for this m & p (and check for validity)*/
|
||||
n=(int)((f_rat*m*p)+0.5);
|
||||
if (n>n_max || n<n_min)
|
||||
continue;
|
||||
|
||||
/*find error in frequency this gives*/
|
||||
error=fabs(((f_ref*n)/(m*p))-f_vco);
|
||||
if (error<error_best)
|
||||
{
|
||||
error_best = error;
|
||||
best[0]=m;
|
||||
best[1]=n;
|
||||
best[2]=p;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
m=best[0];
|
||||
n=best[1];
|
||||
p=best[2];
|
||||
|
||||
/*calculate value of s for fvco, not sure if these are correct*/
|
||||
for(;;)/*set loop filter bandwidth -> spot the Perl coder :-)*/
|
||||
/*reprogram (select,wait for stability)*/
|
||||
MAVW(PIXPLLM,(m)); /* set m value */
|
||||
MAVW(PIXPLLN,(n)); /* set n value */
|
||||
MAVW(PIXPLLP,(p | 0x80)); /* set p value enabling PLL */
|
||||
|
||||
/* Wait for the VIDPLL frequency to lock: detection is not possible it seems */
|
||||
snooze(2000);
|
||||
|
||||
LOG(2,("MAVEN: VID PLL frequency should be locked now...\n"));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/* find nearest valid video PLL setting */
|
||||
status_t g100_g400max_maven_vid_pll_find(
|
||||
display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result)
|
||||
{
|
||||
int m = 0, n = 0, p = 0, m_max;
|
||||
float error, error_best = 999999999;
|
||||
int best[3];
|
||||
float f_vco, max_pclk;
|
||||
float req_pclk = target.timing.pixel_clock/1000.0;
|
||||
|
||||
/* determine the max. reference-frequency postscaler setting for the current card */
|
||||
//fixme: check G100 and G200 m_max if possible...
|
||||
switch(si->ps.card_type)
|
||||
{
|
||||
if(f_vco>180) {p|=0x18;break;};
|
||||
if(f_vco>140) {p|=0x10;break;};
|
||||
if(f_vco>100) {p|=0x08;break;};
|
||||
case G100:
|
||||
LOG(4,("MAVEN: G100 restrictions apply\n"));
|
||||
m_max = 32;
|
||||
break;
|
||||
case G200:
|
||||
LOG(4,("MAVEN: G200 restrictions apply\n"));
|
||||
m_max = 32;
|
||||
break;
|
||||
default:
|
||||
LOG(4,("MAVEN: G400/G400MAX restrictions apply\n"));
|
||||
m_max = 32;
|
||||
break;
|
||||
}
|
||||
|
||||
/*set the result*/
|
||||
*result = (float) (f_ref*n)/(m*(p&0x7));
|
||||
*m_result = m-1;
|
||||
*n_result = n-1;
|
||||
*p_result = p-1;
|
||||
/* determine the max. pixelclock for the current videomode */
|
||||
switch (target.space)
|
||||
{
|
||||
case B_RGB16_LITTLE:
|
||||
max_pclk = si->ps.max_dac2_clock_16;
|
||||
break;
|
||||
case B_RGB32_LITTLE:
|
||||
max_pclk = si->ps.max_dac2_clock_32;
|
||||
break;
|
||||
default:
|
||||
/* use fail-safe value */
|
||||
max_pclk = si->ps.max_dac2_clock_32;
|
||||
break;
|
||||
}
|
||||
/* if some dualhead mode is active, an extra restriction might apply */
|
||||
if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE))
|
||||
max_pclk = si->ps.max_dac2_clock_32dh;
|
||||
|
||||
/*display the found value*/
|
||||
LOG(4,("MAVEN: pixpllcheck - requested %fMHz got %fMHz\n",(double)f_vco,*result));
|
||||
/* Make sure the requested pixelclock is within the PLL's operational limits */
|
||||
/* lower limit is min_video_vco divided by highest postscaler-factor */
|
||||
if (req_pclk < (si->ps.min_video_vco / 8.0))
|
||||
{
|
||||
LOG(4,("MAVEN: clamping vidclock: requested %fMHz, set to %fMHz\n",
|
||||
req_pclk, (float)(si->ps.min_video_vco / 8.0)));
|
||||
req_pclk = (si->ps.min_video_vco / 8.0);
|
||||
}
|
||||
/* upper limit is given by pins in combination with current active mode */
|
||||
if (req_pclk > max_pclk)
|
||||
{
|
||||
LOG(4,("MAVEN: clamping vidclock: requested %fMHz, set to %fMHz\n",
|
||||
req_pclk, (float)max_pclk));
|
||||
req_pclk = max_pclk;
|
||||
}
|
||||
|
||||
/* iterate through all valid PLL postscaler settings */
|
||||
for (p=0x01; p < 0x10; p = p<<1)
|
||||
{
|
||||
/* calculate the needed VCO frequency for this postscaler setting */
|
||||
f_vco = req_pclk * p;
|
||||
|
||||
/* check if this is within range of the VCO specs */
|
||||
if ((f_vco >= si->ps.min_video_vco) && (f_vco <= si->ps.max_video_vco))
|
||||
{
|
||||
/* iterate trough all valid reference-frequency postscaler settings */
|
||||
for (m = 2; m <= m_max; m++)
|
||||
{
|
||||
/* calculate VCO postscaler setting for current setup.. */
|
||||
n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5);
|
||||
/* ..and check for validity */
|
||||
if ((n < 8) || (n > 128)) continue;
|
||||
|
||||
/* find error in frequency this setting gives */
|
||||
error = fabs(req_pclk - (((si->ps.f_ref / m) * n) / p));
|
||||
|
||||
/* note the setting if best yet */
|
||||
if (error < error_best)
|
||||
{
|
||||
error_best = error;
|
||||
best[0]=m;
|
||||
best[1]=n;
|
||||
best[2]=p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* setup the scalers programming values for found optimum setting */
|
||||
m=best[0] - 1;
|
||||
n=best[1] - 1;
|
||||
p=best[2] - 1;
|
||||
|
||||
/* calc the needed PLL loopbackfilter setting belonging to current VCO speed */
|
||||
f_vco = (si->ps.f_ref / (m + 1)) * (n + 1);
|
||||
LOG(2,("MAVEN: vid VCO frequency found %fMhz\n", f_vco));
|
||||
|
||||
switch(si->ps.card_type)
|
||||
{
|
||||
case G100:
|
||||
case G200:
|
||||
for(;;)
|
||||
{
|
||||
if (f_vco >= 180) {p |= (0x03 << 3); break;};
|
||||
if (f_vco >= 140) {p |= (0x02 << 3); break;};
|
||||
if (f_vco >= 100) {p |= (0x01 << 3); break;};
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for(;;)
|
||||
{
|
||||
if (f_vco >= 240) {p |= (0x03 << 3); break;};
|
||||
if (f_vco >= 170) {p |= (0x02 << 3); break;};
|
||||
if (f_vco >= 110) {p |= (0x01 << 3); break;};
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* return the results */
|
||||
*calc_pclk = f_vco / ((p & 0x07) + 1);
|
||||
*m_result = m;
|
||||
*n_result = n;
|
||||
*p_result = p;
|
||||
|
||||
/* display the found pixelclock values */
|
||||
LOG(2,("MAVEN: vid PLL check: req. %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
|
||||
req_pclk, *calc_pclk, *m_result, *n_result, *p_result));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t gx50_maven_check_vid_pll(uint8 m, uint8 n, uint8 p)
|
||||
{
|
||||
uint time = 0, count = 0;
|
||||
|
||||
/* reprogram (disable,select,wait for stability,enable) */
|
||||
CR2W(CTL, (CR2R(CTL) | 0x06)); /* select the VIDPLL */
|
||||
DXIW(VIDPLLM,(m)); /* set m value */
|
||||
DXIW(VIDPLLN,(n)); /* set n value */
|
||||
DXIW(VIDPLLP,(p)); /* set p value */
|
||||
|
||||
/* give the PLL 1mS at least to get a lock */
|
||||
time = 0;
|
||||
while((!(DXIR(VIDPLLSTAT) & 0x40)) & (time <= 1000))
|
||||
{
|
||||
time++;
|
||||
snooze(1);
|
||||
}
|
||||
|
||||
/* no lock aquired, not useable */
|
||||
if (time > 1000) return B_ERROR;
|
||||
|
||||
/* check if lock holds for at least 90% of the time */
|
||||
for (time = 0, count = 0; time <= 1000; time++)
|
||||
{
|
||||
if(DXIR(VIDPLLSTAT) & 0x40) count++;
|
||||
snooze(1);
|
||||
}
|
||||
/* we have a winner */
|
||||
if (count >= 900) return B_OK;
|
||||
|
||||
/* nogo, the PLL does not stabilize */
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t gx50_maven_check_vid_pll_range(uint8 m, uint8 n, uint8 *p, uint8 *q)
|
||||
{
|
||||
uint8 s=0, p_backup = *p;
|
||||
|
||||
/* preset no candidate, non working setting */
|
||||
*q = 0;
|
||||
/* preset lowest range filter */
|
||||
*p &= 0x47;
|
||||
|
||||
/* iterate through all possible filtersettings */
|
||||
CR2W(CTL, (CR2R(CTL) | 0x08)); /* disable the VIDPLL */
|
||||
|
||||
for (s = 0; s < 8 ;s++)
|
||||
{
|
||||
if (gx50_maven_check_vid_pll(m, n, *p)== B_OK)
|
||||
{
|
||||
/* now check 3 closest lower and higher settings */
|
||||
if ((gx50_maven_check_vid_pll(m, n - 3, *p)== B_OK) &&
|
||||
(gx50_maven_check_vid_pll(m, n - 2, *p)== B_OK) &&
|
||||
(gx50_maven_check_vid_pll(m, n - 1, *p)== B_OK) &&
|
||||
(gx50_maven_check_vid_pll(m, n + 1, *p)== B_OK) &&
|
||||
(gx50_maven_check_vid_pll(m, n + 2, *p)== B_OK) &&
|
||||
(gx50_maven_check_vid_pll(m, n + 3, *p)== B_OK))
|
||||
{
|
||||
LOG(2,("MAVEN: found optimal working VCO filter: #%d\n",s));
|
||||
/* preset first choice setting found */
|
||||
*q = 1;
|
||||
/* we are done */
|
||||
CR2W(CTL, (CR2R(CTL) & ~0x08)); /* enable the VIDPLL */
|
||||
return B_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(2,("MAVEN: found critical but working VCO filter: #%d\n",s));
|
||||
/* preset backup setting found */
|
||||
*q = 2;
|
||||
/* remember this setting */
|
||||
p_backup = *p;
|
||||
/* let's continue to see if a better filter exists */
|
||||
}
|
||||
}
|
||||
/* new filtersetting to try */
|
||||
*p += (1 << 3);
|
||||
}
|
||||
|
||||
/* return the (last found) backup result, or the original p value */
|
||||
*p = p_backup;
|
||||
CR2W(CTL, (CR2R(CTL) & ~0x08)); /* enable the VIDPLL */
|
||||
/* we found only a non-optimal value */
|
||||
if (*q == 2) return B_OK;
|
||||
|
||||
/* nothing worked at all */
|
||||
LOG(2,("MAVEN: no working VCO filter found!\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
/* find nearest valid video PLL setting */
|
||||
status_t g450_g550_maven_vid_pll_find
|
||||
(display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test)
|
||||
{
|
||||
int m = 0, n = 0;
|
||||
uint8 p = 0, q = 0;
|
||||
float error, error_best = 999999999;
|
||||
int best[3];
|
||||
float f_vco, max_pclk;
|
||||
float req_pclk = target.timing.pixel_clock/1000.0;
|
||||
|
||||
LOG(4,("MAVEN: G450/G550 restrictions apply\n"));
|
||||
|
||||
/* determine the max. pixelclock for the current videomode */
|
||||
switch (target.space)
|
||||
{
|
||||
case B_RGB16_LITTLE:
|
||||
max_pclk = si->ps.max_dac2_clock_16;
|
||||
break;
|
||||
case B_RGB32_LITTLE:
|
||||
max_pclk = si->ps.max_dac2_clock_32;
|
||||
break;
|
||||
default:
|
||||
/* use fail-safe value */
|
||||
max_pclk = si->ps.max_dac2_clock_32;
|
||||
break;
|
||||
}
|
||||
/* if some dualhead mode is active, an extra restriction might apply */
|
||||
if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE))
|
||||
max_pclk = si->ps.max_dac2_clock_32dh;
|
||||
|
||||
/* Make sure the requested pixelclock is within the PLL's operational limits */
|
||||
/* lower limit is min_pixel_vco divided by highest postscaler-factor */
|
||||
if (req_pclk < (si->ps.min_video_vco / 16.0))
|
||||
{
|
||||
LOG(4,("MAVEN: clamping vidclock: requested %fMHz, set to %fMHz\n",
|
||||
req_pclk, (float)(si->ps.min_video_vco / 16.0)));
|
||||
req_pclk = (si->ps.min_video_vco / 16.0);
|
||||
}
|
||||
/* upper limit is given by pins in combination with current active mode */
|
||||
if (req_pclk > max_pclk)
|
||||
{
|
||||
LOG(4,("MAVEN: clamping vidclock: requested %fMHz, set to %fMHz\n",
|
||||
req_pclk, (float)max_pclk));
|
||||
req_pclk = max_pclk;
|
||||
}
|
||||
|
||||
/* iterate through all valid PLL postscaler settings */
|
||||
for (p=0x01; p < 0x20; p = p<<1)
|
||||
{
|
||||
/* calculate the needed VCO frequency for this postscaler setting */
|
||||
f_vco = req_pclk * p;
|
||||
|
||||
/* check if this is within range of the VCO specs */
|
||||
if ((f_vco >= si->ps.min_video_vco) && (f_vco <= si->ps.max_video_vco))
|
||||
{
|
||||
/* iterate trough all valid reference-frequency postscaler settings */
|
||||
for (m = 2; m <= 32; m++)
|
||||
{
|
||||
/* calculate VCO postscaler setting for current setup.. */
|
||||
n = (int)(((f_vco * m) / (si->ps.f_ref * 2)) + 0.5);
|
||||
/* ..and check for validity, BUT:
|
||||
* Keep in mind that we need to be able to test n-3 ... n+3! */
|
||||
if ((n < (8 + 3)) || (n > (128 - 3))) continue;
|
||||
|
||||
/* find error in frequency this setting gives */
|
||||
error = fabs(req_pclk - ((((si->ps.f_ref * 2)/ m) * n) / p));
|
||||
|
||||
/* note the setting if best yet */
|
||||
if (error < error_best)
|
||||
{
|
||||
error_best = error;
|
||||
best[0]=m;
|
||||
best[1]=n;
|
||||
best[2]=p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* setup the scalers programming values for found optimum setting */
|
||||
m=best[0] - 1;
|
||||
n=best[1] - 2;
|
||||
switch(best[2])
|
||||
{
|
||||
case 1:
|
||||
p = 0x40;
|
||||
break;
|
||||
case 2:
|
||||
p = 0x00;
|
||||
break;
|
||||
case 4:
|
||||
p = 0x01;
|
||||
break;
|
||||
case 8:
|
||||
p = 0x02;
|
||||
break;
|
||||
case 16:
|
||||
p = 0x03;
|
||||
break;
|
||||
}
|
||||
|
||||
/* log the closest VCO speed found */
|
||||
f_vco = ((si->ps.f_ref * 2) / (m + 1)) * (n + 2);
|
||||
LOG(2,("MAVEN: vid VCO frequency found %fMhz\n", f_vco));
|
||||
|
||||
/* now find the filtersetting that matches best with this frequency by testing.
|
||||
* for now we assume this routine succeeds to get us a stable setting */
|
||||
if (test)
|
||||
gx50_maven_check_vid_pll_range(m, n, &p, &q);
|
||||
else
|
||||
LOG(2,("MAVEN: Not testing G450/G550 VCO feedback filters\n"));
|
||||
|
||||
/* return the results */
|
||||
*calc_pclk = f_vco / best[2];
|
||||
*m_result = m;
|
||||
*n_result = n;
|
||||
*p_result = p;
|
||||
|
||||
/* display the found pixelclock values */
|
||||
LOG(2,("MAVEN: vid PLL check: req. %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
|
||||
req_pclk, *calc_pclk, *m_result, *n_result, *p_result));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@ status_t mga_set_cas_latency();
|
||||
status_t gx50_general_output_select();
|
||||
status_t gx00_general_dac_select(int);
|
||||
status_t gx00_general_wait_retrace();
|
||||
status_t gx00_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row);
|
||||
//status_t gx00_general_bios_to_powergraphics();
|
||||
|
||||
/* apsed: logging macros */
|
||||
@@ -35,6 +36,7 @@ status_t pins3_read(uint8 *pins, uint8 length);
|
||||
status_t pins4_read(uint8 *pins, uint8 length);
|
||||
status_t pins5_read(uint8 *pins, uint8 length);
|
||||
void fake_pins(void);
|
||||
void pinsmil1_fake(void);
|
||||
void pinsmil2_fake(void);
|
||||
void pinsg100_fake(void);
|
||||
void pinsg200_fake(void);
|
||||
@@ -57,22 +59,24 @@ status_t g200_dac_set_sys_pll();
|
||||
status_t g100_dac_set_sys_pll();
|
||||
|
||||
status_t mil2_dac_init(void);
|
||||
status_t mil2_dac_mode(int,float, int hsync_pos,int vsync_pos, int sync_green);
|
||||
status_t mil2_dac_palette(uint8*,uint8*,uint8*);
|
||||
status_t mil2_dac_pix_pll_find(float f_vco,float * result,uint8 *,uint8 *,uint8 *);
|
||||
status_t mil2_dac_set_pix_pll(float f_vco,int bpp);
|
||||
|
||||
/*MAVEN functions*/
|
||||
status_t gx00_maven_dpms(uint8,uint8,uint8);
|
||||
status_t gx00_maven_set_timing(
|
||||
uint32 hdisp_e,uint32 hsync_s,uint32 hsync_e,uint32 htotal,
|
||||
uint32 vdisp_e,uint32 vsync_s,uint32 vsync_e,uint32 vtotal,
|
||||
uint8 hsync_pos,uint8 vsync_pos
|
||||
);
|
||||
status_t gx00_maven_set_timing(display_mode target);
|
||||
status_t gx00_maven_mode(int,float);
|
||||
|
||||
status_t gx00_maven_pix_pll_find(float f_vco,float * result,uint8 *,uint8 *,uint8 *);
|
||||
status_t gx00_maven_set_pix_pll(float f_vco);
|
||||
status_t g100_g400max_maven_vid_pll_find(display_mode target,float * calc_pclk,
|
||||
uint8 * m_result,uint8 * n_result,uint8 * p_result);
|
||||
status_t g450_g550_maven_vid_pll_find(display_mode target,float * calc_pclk,
|
||||
uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test);
|
||||
status_t gx00_maven_set_vid_pll(display_mode target);
|
||||
|
||||
/*MAVENTV functions*/
|
||||
status_t g100_g400max_maventv_vid_pll_find(
|
||||
display_mode target, unsigned int * ht_new, unsigned int * ht_last_line,
|
||||
uint8 * m_result, uint8 * n_result, uint8 * p_result);
|
||||
int maventv_init(display_mode target);
|
||||
|
||||
/*CRTC1 functions*/
|
||||
status_t gx00_crtc_validate_timing(
|
||||
@@ -86,7 +90,7 @@ status_t gx00_crtc_set_timing(
|
||||
);
|
||||
status_t gx00_crtc_depth(int mode);
|
||||
status_t gx00_crtc_set_display_start(uint32 startadd,uint8 bpp);
|
||||
status_t gx00_crtc_set_display_pitch(uint32 pitch,uint8 bpp);
|
||||
status_t gx00_crtc_set_display_pitch();
|
||||
|
||||
status_t gx00_crtc_dpms(uint8,uint8,uint8);
|
||||
status_t gx00_crtc_dpms_fetch(uint8*,uint8*,uint8*);
|
||||
@@ -100,24 +104,23 @@ status_t gx00_crtc_cursor_hide();
|
||||
|
||||
/*CRTC2 functions*/
|
||||
/*XXX - validate_timing*/
|
||||
status_t g400_crtc2_set_timing(
|
||||
uint32 hdisp_e,uint32 hsync_s,uint32 hsync_e,uint32 htotal,
|
||||
uint32 vdisp_e,uint32 vsync_s,uint32 vsync_e,uint32 vtotal,
|
||||
uint8 hsync_pos,uint8 vsync_pos
|
||||
);
|
||||
status_t g400_crtc2_set_timing(display_mode target);
|
||||
status_t g400_crtc2_depth(int mode);
|
||||
status_t g400_crtc2_set_display_pitch(uint32 pitch,uint8 bpp);
|
||||
status_t g400_crtc2_set_display_pitch();
|
||||
status_t g400_crtc2_set_display_start(uint32 startadd,uint8 bpp);
|
||||
|
||||
status_t g400_crtc2_dpms(uint8 display,uint8 h,uint8 v);
|
||||
status_t g400_crtc2_dpms_fetch(uint8 * display,uint8 * h,uint8 * v);
|
||||
|
||||
/*acceleration functions*/
|
||||
status_t check_acc_capability(uint32 feature);
|
||||
status_t gx00_acc_init();
|
||||
status_t gx00_acc_rectangle(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint32 col);
|
||||
status_t gx00_acc_rectangle_invert(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint32 col);
|
||||
status_t gx00_acc_blit(uint16,uint16,uint16, uint16,uint16,uint16 );
|
||||
status_t gx00_acc_transparent_blit(uint16,uint16,uint16, uint16,uint16,uint16, uint32);
|
||||
status_t gx00_acc_video_blit(uint16 xs,uint16 ys,uint16 ws, uint16 hs,
|
||||
uint16 xd,uint16 yd,uint16 wd,uint16 hd);
|
||||
status_t gx00_acc_wait_idle();
|
||||
|
||||
/*backend scaler functions*/
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
Program the Texas TVP3026
|
||||
using Texas Instrument TVP3026 manual SLA098B July 1996
|
||||
|
||||
Author:
|
||||
Apsed May 2002 a lot of time after ...
|
||||
|
||||
NB BPP24 and BPP32DIR not tested
|
||||
Authors:
|
||||
Apsed May 2002 plus a lot of time after;
|
||||
Rudolf Cornelissen 3/2003.
|
||||
*/
|
||||
|
||||
#define MODULE_BIT 0x00010000
|
||||
@@ -13,76 +12,12 @@
|
||||
#include <OS.h> // system_time, snooze
|
||||
#include "mga_std.h"
|
||||
|
||||
#define PIXEL_BUS_WIDTH64 0 // if 0: 32 bits width, else 64
|
||||
#define PIXEL_BUS_WIDTH64 1 // if 0: 32 bits width, else 64
|
||||
|
||||
#define FPLL_REF 14.31818 // MHz
|
||||
#define FVCO_MAX 220.00000 // MHz, may be 220 or 250, see 3.5
|
||||
#define FVCO_MIN 110.00000 // MHz
|
||||
#define FPLL_MCLK 100.00000 // MHz
|
||||
|
||||
//r: ??
|
||||
#define MGAVGA_INSTS0 0x1FC2
|
||||
|
||||
// access the TVP3026, this is near G200 DAC but ...
|
||||
|
||||
/* direct registers */
|
||||
#define TVP_PALWTADD 0x3c00
|
||||
#define TVP_PALDATA 0x3c01
|
||||
#define TVP_PIXRDMSK 0x3c02
|
||||
#define TVP_PALRDADD 0x3c03
|
||||
#define TVP_CUROVRWTADD 0x3c04
|
||||
#define TVP_CUROVRDATA 0x3c05
|
||||
#define TVP_CUROVRRDADD 0x3c07
|
||||
#define TVP_DIRCURCTRL 0x3c09
|
||||
#define TVP_X_DATAREG 0x3c0a
|
||||
#define TVP_CURRAMDATA 0x3c0b
|
||||
#define TVP_CURPOSXL 0x3c0c
|
||||
#define TVP_CURPOSXH 0x3c0d
|
||||
#define TVP_CURPOSYL 0x3c0e
|
||||
#define TVP_CURPOSYH 0x3c0f
|
||||
|
||||
/* indirect registers */
|
||||
#define TVPI_SILICONREV 0x01
|
||||
#define TVPI_INDCURCTRL 0x06
|
||||
#define TVPI_LATCHCTRL 0x0f
|
||||
#define TVPI_TCOLCTRL 0x18
|
||||
#define TVPI_MULCTRL 0x19
|
||||
#define TVPI_CLOCKSEL 0x1a
|
||||
#define TVPI_PALPAGE 0x1c
|
||||
#define TVPI_GENCTRL 0x1d
|
||||
#define TVPI_MISCCTRL 0x1e
|
||||
#define TVPI_GENIOCTRL 0x2a
|
||||
#define TVPI_GENIODATA 0x2b
|
||||
#define TVPI_PLLADDR 0x2c
|
||||
#define TVPI_PIXPLLDATA 0x2d
|
||||
#define TVPI_MEMPLLDATA 0x2e
|
||||
#define TVPI_LOOPLLDATA 0x2f
|
||||
#define TVPI_COLKEYOL 0x30
|
||||
#define TVPI_COLKEYOH 0x31
|
||||
#define TVPI_COLKEYRL 0x32
|
||||
#define TVPI_COLKEYRH 0x33
|
||||
#define TVPI_COLKEYGL 0x34
|
||||
#define TVPI_COLKEYGH 0x35
|
||||
#define TVPI_COLKEYBL 0x36
|
||||
#define TVPI_COLKEYBH 0x37
|
||||
#define TVPI_COLKEYCTRL 0x38
|
||||
#define TVPI_MEMCLKCTRL 0x39
|
||||
#define TVPI_SENSETEST 0x3a
|
||||
#define TVPI_TESTMODEDATA 0x3b
|
||||
#define TVPI_CRCREML 0x3c
|
||||
#define TVPI_CRCREMH 0x3d
|
||||
#define TVPI_CRCBITSEL 0x3e
|
||||
#define TVPI_ID 0x3f
|
||||
#define TVPI_RESET 0xff
|
||||
|
||||
/*read and write from the TVP3026 registers*/
|
||||
#define TVPR(A) (MGA_REG8(TVP_##A))
|
||||
#define TVPW(A,B) (MGA_REG8(TVP_##A)=B)
|
||||
|
||||
/*read and write from the TVP3026 indirect register*/
|
||||
#define TVPIR(A) (TVPW(PALWTADD,TVPI_##A),TVPR(X_DATAREG))
|
||||
#define TVPIW(A,B) (TVPW(PALWTADD,TVPI_##A),TVPW(X_DATAREG,B))
|
||||
|
||||
#define WAIT_FOR_PLL_LOCK( pll, on_error) do { \
|
||||
bigtime_t start, now; \
|
||||
float delay; \
|
||||
@@ -90,7 +25,7 @@
|
||||
\
|
||||
start = system_time(); \
|
||||
for (tmo = 0; tmo < 100 * 1000 * 1000; tmo++) { \
|
||||
int status = TVPIR (pll ## PLLDATA); \
|
||||
int status = DXIR (pll ## PLLDATA); \
|
||||
if (status & 0x40) break; \
|
||||
/* snooze(10); */ \
|
||||
} \
|
||||
@@ -103,369 +38,6 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define REREAD_PLL( pll) do { \
|
||||
uint8 n, m, p; \
|
||||
float f, vco; \
|
||||
\
|
||||
TVPIW(PLLADDR, 0x00); \
|
||||
n = TVPIR(pll ## PLLDATA); \
|
||||
TVPIW(PLLADDR, 0x15); \
|
||||
m = TVPIR(pll ## PLLDATA); \
|
||||
TVPIW(PLLADDR, 0x2a); \
|
||||
p = TVPIR(pll ## PLLDATA); \
|
||||
vco = 8 * FPLL_REF * (65 - (m & 0x3f)) / (65 - (n & 0x3f)); \
|
||||
f = vco / (1 << (p & 0x03)); \
|
||||
LOG(2,("mil2 reread %s PLL, nmp 0x%02x 0x%02x 0x%02x, %fMHz, vco %fMHz\n", \
|
||||
#pll, n, m, p, f, vco)); \
|
||||
} while (0)
|
||||
|
||||
#define DUMP_CFG(reg) MSG(( \
|
||||
"PCI CONFIG register 0x%04x %20s 0x%08x\n", MGACFG_##reg, #reg, CFGR(reg)))
|
||||
#define DUMP_VGA(reg) MSG(( \
|
||||
"MGA VGA register 0x%04x %20s 0x%02x\n", MGAVGA_##reg, #reg, VGAR(reg)))
|
||||
#define DUMP_VGA_ATTR(reg) MSG(( \
|
||||
"MGA VGA ATTR register 0x%04x %20s 0x%02x\n", 0x##reg, "ATTR" #reg, VGAR_I(ATTR, 0x##reg)))
|
||||
#define DUMP_VGA_SEQ(reg) MSG(( \
|
||||
"MGA VGA SEQ register 0x%04x %20s 0x%02x\n", 0x##reg, "SEQ" #reg, VGAR_I(SEQ, 0x##reg)))
|
||||
#define DUMP_VGA_GCTL(reg) MSG(( \
|
||||
"MGA VGA GCTL register 0x%04x %20s 0x%02x\n", 0x##reg, "GCTL" #reg, VGAR_I(GCTL, 0x##reg)))
|
||||
#define DUMP_VGA_CRTC(reg) MSG(( \
|
||||
"MGA VGA CRTC register 0x%04x %20s 0x%02x\n", 0x##reg, "CRTC" #reg, VGAR_I(CRTC, 0x##reg)))
|
||||
#define DUMP_VGA_CRTCEXT(reg) MSG(( \
|
||||
"MGA VGA CRTCEXT register 0x%04x %20s 0x%02x\n", 0x##reg, "CRTCEXT" #reg, VGAR_I(CRTCEXT, 0x##reg)))
|
||||
#define DUMP_TVP(reg) MSG(( \
|
||||
"TVP3028 register 0x%04x %20s 0x%02x\n", TVP_##reg, #reg, TVPR(reg)))
|
||||
#define DUMP_TVPI(reg) MSG(( \
|
||||
"TVP3028 INDIRECT register 0x%04x %20s 0x%02x\n", TVPI_##reg, #reg, TVPIR(reg)))
|
||||
#define DUMP_MGA(reg) MSG(( \
|
||||
"MGA register 0x%04x %20s 0x%08x\n", MGAACC_##reg, #reg, ACCR(reg)))
|
||||
|
||||
static void dump_tvp3026 (void)
|
||||
{
|
||||
/* TVP3026 DAC direct registers */
|
||||
// DUMP_TVP (PALWTADD);
|
||||
// DUMP_TVP (PALDATA );
|
||||
DUMP_TVP (PIXRDMSK);
|
||||
// DUMP_TVP (PALRDADD);
|
||||
DUMP_TVP (CUROVRWTADD);
|
||||
DUMP_TVP (CUROVRDATA);
|
||||
DUMP_TVP (CUROVRRDADD);
|
||||
DUMP_TVP (DIRCURCTRL);
|
||||
// DUMP_TVP (X_DATAREG);
|
||||
DUMP_TVP (CURRAMDATA);
|
||||
DUMP_TVP (CURPOSXL);
|
||||
DUMP_TVP (CURPOSXH);
|
||||
DUMP_TVP (CURPOSYL);
|
||||
DUMP_TVP (CURPOSYH);
|
||||
|
||||
/* TVP3026 DAC indirect registers */
|
||||
DUMP_TVPI (SILICONREV);
|
||||
DUMP_TVPI (INDCURCTRL);
|
||||
DUMP_TVPI (LATCHCTRL);
|
||||
DUMP_TVPI (TCOLCTRL);
|
||||
DUMP_TVPI (MULCTRL);
|
||||
DUMP_TVPI (CLOCKSEL);
|
||||
DUMP_TVPI (PALPAGE);
|
||||
DUMP_TVPI (GENCTRL);
|
||||
DUMP_TVPI (MISCCTRL);
|
||||
DUMP_TVPI (GENIOCTRL);
|
||||
DUMP_TVPI (GENIODATA);
|
||||
// DUMP_TVPI (PLLADDR);
|
||||
// DUMP_TVPI (PIXPLLDATA);
|
||||
// DUMP_TVPI (MEMPLLDATA);
|
||||
// DUMP_TVPI (LOOPLLDATA);
|
||||
REREAD_PLL (PIX);
|
||||
REREAD_PLL (MEM);
|
||||
REREAD_PLL (LOO);
|
||||
DUMP_TVPI (COLKEYOL);
|
||||
DUMP_TVPI (COLKEYOH);
|
||||
DUMP_TVPI (COLKEYRL);
|
||||
DUMP_TVPI (COLKEYRH);
|
||||
DUMP_TVPI (COLKEYGL);
|
||||
DUMP_TVPI (COLKEYGH);
|
||||
DUMP_TVPI (COLKEYBL);
|
||||
DUMP_TVPI (COLKEYBH);
|
||||
DUMP_TVPI (COLKEYCTRL);
|
||||
DUMP_TVPI (MEMCLKCTRL);
|
||||
DUMP_TVPI (SENSETEST);
|
||||
DUMP_TVPI (TESTMODEDATA);
|
||||
DUMP_TVPI (CRCREML);
|
||||
DUMP_TVPI (CRCREMH);
|
||||
// DUMP_TVPI (CRCBITSEL); // WO
|
||||
DUMP_TVPI (ID);
|
||||
// DUMP_TVPI (RESET); // WO
|
||||
}
|
||||
|
||||
static void dump_mil2 (void)
|
||||
{
|
||||
/* PCI_config_space */
|
||||
DUMP_CFG (DEVID);
|
||||
DUMP_CFG (DEVCTRL);
|
||||
DUMP_CFG (CLASS);
|
||||
DUMP_CFG (HEADER);
|
||||
DUMP_CFG (MGABASE2);
|
||||
DUMP_CFG (MGABASE1);
|
||||
DUMP_CFG (MGABASE3);
|
||||
DUMP_CFG (SUBSYSIDR);
|
||||
DUMP_CFG (ROMBASE);
|
||||
DUMP_CFG (CAP_PTR);
|
||||
DUMP_CFG (INTCTRL);
|
||||
DUMP_CFG (OPTION);
|
||||
DUMP_CFG (MGA_INDEX);
|
||||
DUMP_CFG (MGA_DATA);
|
||||
DUMP_CFG (SUBSYSIDW);
|
||||
DUMP_CFG (AGP_IDENT);
|
||||
DUMP_CFG (AGP_STS);
|
||||
DUMP_CFG (AGP_CMD);
|
||||
|
||||
/*VGA registers - these are byte wide*/
|
||||
// DUMP_VGA (ATTR_I);
|
||||
// DUMP_VGA (ATTR_D);
|
||||
DUMP_VGA_ATTR (0);
|
||||
DUMP_VGA_ATTR (1);
|
||||
DUMP_VGA_ATTR (3);
|
||||
DUMP_VGA_ATTR (3);
|
||||
DUMP_VGA_ATTR (4);
|
||||
DUMP_VGA_ATTR (5);
|
||||
DUMP_VGA_ATTR (6);
|
||||
DUMP_VGA_ATTR (7);
|
||||
DUMP_VGA_ATTR (8);
|
||||
DUMP_VGA_ATTR (9);
|
||||
DUMP_VGA_ATTR (A);
|
||||
DUMP_VGA_ATTR (B);
|
||||
DUMP_VGA_ATTR (C);
|
||||
DUMP_VGA_ATTR (D);
|
||||
DUMP_VGA_ATTR (E);
|
||||
DUMP_VGA_ATTR (F);
|
||||
DUMP_VGA_ATTR (10);
|
||||
DUMP_VGA_ATTR (11);
|
||||
DUMP_VGA_ATTR (12);
|
||||
DUMP_VGA_ATTR (13);
|
||||
DUMP_VGA_ATTR (14);
|
||||
// DUMP_VGA (CRTC_I);
|
||||
// DUMP_VGA (CRTC_D);
|
||||
DUMP_VGA_CRTC (0);
|
||||
DUMP_VGA_CRTC (1);
|
||||
DUMP_VGA_CRTC (2);
|
||||
DUMP_VGA_CRTC (3);
|
||||
DUMP_VGA_CRTC (4);
|
||||
DUMP_VGA_CRTC (5);
|
||||
DUMP_VGA_CRTC (6);
|
||||
DUMP_VGA_CRTC (7);
|
||||
DUMP_VGA_CRTC (8);
|
||||
DUMP_VGA_CRTC (9);
|
||||
DUMP_VGA_CRTC (A);
|
||||
DUMP_VGA_CRTC (B);
|
||||
DUMP_VGA_CRTC (C);
|
||||
DUMP_VGA_CRTC (D);
|
||||
DUMP_VGA_CRTC (E);
|
||||
DUMP_VGA_CRTC (F);
|
||||
DUMP_VGA_CRTC (10);
|
||||
DUMP_VGA_CRTC (11);
|
||||
DUMP_VGA_CRTC (12);
|
||||
DUMP_VGA_CRTC (13);
|
||||
DUMP_VGA_CRTC (14);
|
||||
DUMP_VGA_CRTC (15);
|
||||
DUMP_VGA_CRTC (16);
|
||||
DUMP_VGA_CRTC (17);
|
||||
DUMP_VGA_CRTC (18);
|
||||
DUMP_VGA_CRTC (22);
|
||||
DUMP_VGA_CRTC (24);
|
||||
DUMP_VGA_CRTC (26);
|
||||
// DUMP_VGA (CRTCEXT_I);
|
||||
// DUMP_VGA (CRTCEXT_D);
|
||||
DUMP_VGA_CRTCEXT (0);
|
||||
DUMP_VGA_CRTCEXT (1);
|
||||
DUMP_VGA_CRTCEXT (2);
|
||||
DUMP_VGA_CRTCEXT (3);
|
||||
DUMP_VGA_CRTCEXT (4);
|
||||
DUMP_VGA_CRTCEXT (5);
|
||||
DUMP_VGA (DACSTAT);
|
||||
// DUMP_VGA (FEATW);
|
||||
DUMP_VGA (FEATR);
|
||||
// DUMP_VGA (GCTL_I);
|
||||
// DUMP_VGA (GCTL_D);
|
||||
DUMP_VGA_GCTL (0);
|
||||
DUMP_VGA_GCTL (1);
|
||||
DUMP_VGA_GCTL (2);
|
||||
DUMP_VGA_GCTL (3);
|
||||
DUMP_VGA_GCTL (4);
|
||||
DUMP_VGA_GCTL (5);
|
||||
DUMP_VGA_GCTL (6);
|
||||
DUMP_VGA_GCTL (7);
|
||||
DUMP_VGA_GCTL (8);
|
||||
DUMP_VGA (INSTS0);
|
||||
DUMP_VGA (INSTS1);
|
||||
DUMP_VGA (MISCR);
|
||||
DUMP_VGA (MISCW);
|
||||
// DUMP_VGA (SEQ_I);
|
||||
// DUMP_VGA (SEQ_D);
|
||||
DUMP_VGA_SEQ (0);
|
||||
DUMP_VGA_SEQ (1);
|
||||
DUMP_VGA_SEQ (2);
|
||||
DUMP_VGA_SEQ (3);
|
||||
DUMP_VGA_SEQ (4);
|
||||
|
||||
/* MGA registers, only the readable*/
|
||||
DUMP_MGA (IEN);
|
||||
DUMP_MGA (RST);
|
||||
DUMP_MGA (OPMODE);
|
||||
DUMP_MGA (STATUS);
|
||||
|
||||
/* TVP3026 registers */
|
||||
dump_tvp3026();
|
||||
}
|
||||
|
||||
/*set the mode, brightness is a value from 0->2 (where 1 is equivalent to direct)*/
|
||||
status_t mil2_dac_mode (int mode, float brightness, int hsync_pos, int vsync_pos, int sync_green)
|
||||
{
|
||||
uint8 *r, *g, *b, t[64];
|
||||
int i;
|
||||
uint8 miscctrl = 0, latchctrl = 0;
|
||||
uint8 tcolctrl = 0, mulctrl = 0;
|
||||
|
||||
LOG(4,("TVP:Setting screen mode %d brightness %f\n", mode, brightness));
|
||||
if (si->settings.logmask & 0x80000000) dump_tvp3026();
|
||||
|
||||
/*set colour arrays to point to space reserved in shared info*/
|
||||
r = si->color_data;
|
||||
g = r + 256;
|
||||
b = g + 256;
|
||||
|
||||
/*init a basic palette for brightness specified*/
|
||||
brightness = 2.0; // TODO
|
||||
for (i=0;i<256;i++) {
|
||||
int ri = i*brightness;
|
||||
if (ri > 255) ri = 255;
|
||||
r[i]=ri;
|
||||
}
|
||||
|
||||
/*modify the palette for the specified mode (&validate mode)*/
|
||||
switch(mode) {
|
||||
case BPP8:
|
||||
case BPP24:case BPP32:
|
||||
for (i=0;i<256;i++) b[i]=g[i]=r[i];
|
||||
break;
|
||||
case BPP16:
|
||||
for (i=0;i<64;i++) t[i]=r[i<<2];
|
||||
for (i=0;i<64;i++) g[i]=t[i];
|
||||
for (i=0;i<32;i++) b[i]=r[i]=t[i<<1];
|
||||
break;
|
||||
case BPP15:
|
||||
for (i=0;i<32;i++) t[i]=r[i<<3];
|
||||
for (i=0;i<32;i++) g[i]=r[i]=b[i]=t[i];
|
||||
break;
|
||||
case BPP32DIR:
|
||||
break;
|
||||
default:
|
||||
LOG(8,("TVP:Invalid bit depth requested\n"));
|
||||
return B_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mil2_dac_palette (r, g, b) != B_OK) return B_ERROR;
|
||||
|
||||
// set the mode
|
||||
switch (mode) { // mulctrl for PIXEL_BUS_WIDTH 32
|
||||
case BPP8: miscctrl=0x0c; latchctrl=0x06; tcolctrl=0x80; mulctrl=0x4b; break;
|
||||
case BPP15: miscctrl=0x20; latchctrl=0x06; tcolctrl=0x04; mulctrl=0x53; break;
|
||||
case BPP16: miscctrl=0x20; latchctrl=0x06; tcolctrl=0x05; mulctrl=0x53; break;
|
||||
case BPP24: miscctrl=0x20; latchctrl=0x06; tcolctrl=0x1f; mulctrl=0x5b; break;
|
||||
case BPP32: miscctrl=0x20; latchctrl=0x07; tcolctrl=0x06; mulctrl=0x5b; break;
|
||||
case BPP32DIR: miscctrl=0x20; latchctrl=0x07; tcolctrl=0x06; mulctrl=0x5b; break;
|
||||
}
|
||||
if (PIXEL_BUS_WIDTH64) mulctrl += 1;
|
||||
TVPIW(MISCCTRL,(TVPIR(MISCCTRL) & 0xd3) | miscctrl);
|
||||
TVPIW(LATCHCTRL, latchctrl);
|
||||
TVPIW(TCOLCTRL, tcolctrl);
|
||||
TVPIW(MULCTRL, mulctrl);
|
||||
|
||||
// synchros
|
||||
TVPIW (GENCTRL, (TVPIR (GENCTRL) & 0xdc)
|
||||
| (sync_green? 0x00:0x20) // apsed TODO ?
|
||||
| (vsync_pos? 0x00:0x02)
|
||||
| (hsync_pos? 0x00:0x01));
|
||||
|
||||
//VGAW (MISCW, VGAR(MISCR) & 0x3f); // TODO
|
||||
//TVPIW (GENCTRL, TVPIR (GENCTRL) & 0xdf); // TODO
|
||||
|
||||
LOG(2,("TVP: clocksel 0x%02x, miscctrl 0x%02x\n",
|
||||
TVPIR(CLOCKSEL), TVPIR(MISCCTRL)));
|
||||
LOG(2,("TVP: tcolctrl 0x%02x, mulctrl 0x%02x, pixrdmsk 0x%02x, genctrl 0x%02x\n",
|
||||
TVPIR(TCOLCTRL), TVPIR(MULCTRL), TVPR(PIXRDMSK), TVPIR (GENCTRL)));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// program the palette using the given r,g,b values
|
||||
status_t mil2_dac_palette (uint8 r[256], uint8 g[256], uint8 b[256])
|
||||
{
|
||||
int i;
|
||||
|
||||
LOG(4,("TVP: setting palette\n"));
|
||||
|
||||
/*clear palwtadd to start programming*/
|
||||
TVPW(PALWTADD,0);
|
||||
|
||||
/*loop through all 256 to program LUT*/
|
||||
for (i=0;i<256;i++) {
|
||||
TVPW(PALDATA,r[i]);
|
||||
TVPW(PALDATA,g[i]);
|
||||
TVPW(PALDATA,b[i]);
|
||||
}
|
||||
if (TVPR(PALWTADD)!=0) {
|
||||
LOG(8,("TVP: PALWTADD is not 0 after programming\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
if (0) { // apsed: reread LUT
|
||||
uint8 R, G, B;
|
||||
TVPW(PALRDADD,0);
|
||||
for (i=0;i<256;i++) {
|
||||
R = TVPR(PALDATA);
|
||||
G = TVPR(PALDATA);
|
||||
B = TVPR(PALDATA);
|
||||
if ((r[i] != R) || (g[i] != G) || (b[i] != B)) {
|
||||
LOG(8,("TVP: palette 0x%02x: w %02x %02x %02x, r %02x %02x %02x\n",
|
||||
i, r[i], g[i], b[i], R, G, B));
|
||||
}
|
||||
}
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// find nearest valid pll parameters, TVP3026 2.4.1
|
||||
status_t mil2_dac_pix_pll_find (float f_need, float *f_result, uint8 *m_result, uint8 *n_result, uint8 *p_result)
|
||||
{
|
||||
int m, n, p;
|
||||
float error, best, best_vco;
|
||||
float f_vco, f_pll;
|
||||
|
||||
LOG(0,("mil2_dac_pix_pll_find for %fMHz\n", f_need));
|
||||
best = 999999999;
|
||||
// stupid implementation of 2.4.1 and 2.4.2
|
||||
for (m = 1; m <= 62; m++) {
|
||||
for (n = 40; n <= 62; n++) {
|
||||
f_vco = (8.0 * FPLL_REF * (65 - m)) / (65 - n);
|
||||
if ((f_vco < FVCO_MIN) || (f_vco >= FVCO_MAX)) continue;
|
||||
for (p = 0; p <= 3; p++) {
|
||||
f_pll = f_vco / (float)(1 << p);
|
||||
error = fabs (f_need - f_pll) / f_need;
|
||||
if (error > best) continue;
|
||||
best = error;
|
||||
best_vco = f_vco;
|
||||
*f_result = f_pll;
|
||||
*m_result = m;
|
||||
*n_result = n;
|
||||
*p_result = p;
|
||||
LOG (0,("mil2_dac_pix_pll_find nmp %fMHz %fMHz 0x%02x 0x%02x 0x%02x\n",
|
||||
f_pll, f_vco, *n_result, *m_result, *p_result));
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG(0,("mil2_dac_pix_pll_find requested %fMHz got %fMHz, vco %fMHz, nmp 0x%02x 0x%02x 0x%02x\n",
|
||||
f_need, *f_result, best_vco, *n_result, *m_result, *p_result));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*program the pixpll - frequency in MHz*/
|
||||
status_t mil2_dac_set_pix_pll (float f_need, int bpp)
|
||||
{
|
||||
@@ -474,39 +46,41 @@ status_t mil2_dac_set_pix_pll (float f_need, int bpp)
|
||||
float fd;
|
||||
status_t result;
|
||||
|
||||
display_mode target;
|
||||
target.timing.pixel_clock = (f_need * 1000);
|
||||
|
||||
LOG(4,("mil2_dac_set_pix_pll need %fMHz, %dbpp\n", f_need, bpp));
|
||||
result = mil2_dac_pix_pll_find(f_need,&fd,&m,&n,&p);
|
||||
result = gx00_dac_pix_pll_find(target, &fd, &m, &n, &p, 0);
|
||||
if (result != B_OK) return result;
|
||||
LOG(2,("mil2_dac_set_pix_pll need %fMHz got %fMHz, nmp 0x%02x 0x%02x 0x%02x\n",
|
||||
f_need, fd, n, m, p));
|
||||
|
||||
// follows (!strictly) Appendix C, extended mode setup
|
||||
// 1st stop the PLLs,
|
||||
switch (bpp) {
|
||||
case 8: TVPIW(CLOCKSEL, 0x25); break;
|
||||
case 16: TVPIW(CLOCKSEL, 0x15); break;
|
||||
case 24: TVPIW(CLOCKSEL, 0x25); break;
|
||||
case 32: TVPIW(CLOCKSEL, 0x05); break;
|
||||
case 8: DXIW(TVP_CLOCKSEL, 0x25); break;
|
||||
case 16: DXIW(TVP_CLOCKSEL, 0x15); break;
|
||||
case 24: DXIW(TVP_CLOCKSEL, 0x25); break;
|
||||
case 32: DXIW(TVP_CLOCKSEL, 0x05); break;
|
||||
default: return B_ERROR;
|
||||
}
|
||||
TVPIW(PLLADDR, 0x2a); // 0x2c: 2.4 select P to ...
|
||||
TVPIW(LOOPLLDATA, 0x00); // 0x2f: 2.4.1 ... stop the loop PLL
|
||||
TVPIW(PIXPLLDATA, 0x00); // 0x2d: 2.4.1 ... stop the pixel PLL
|
||||
DXIW(TVP_PLLADDR, 0x2a); // 0x2c: 2.4 select P to ...
|
||||
DXIW(TVP_LOOPLLDATA, 0x00); // 0x2f: 2.4.1 ... stop the loop PLL
|
||||
DXIW(TVP_PIXPLLDATA, 0x00); // 0x2d: 2.4.1 ... stop the pixel PLL
|
||||
VGAW (MISCW, VGAR(MISCR) | 0x0c); // PLLSEL(1,0) set to 1x
|
||||
|
||||
// 2nd setup the pixel PLL
|
||||
LOG(2,("mil2_dac_set_pix_pll pix PLL, nmp 0x%02x 0x%02x 0x%02x\n",
|
||||
n, m, p));
|
||||
TVPIW(PLLADDR, 0x00); // 0x2c: 2.4 select N to ...
|
||||
TVPIW(PIXPLLDATA, n | 0xc0); // 0x2d: ... load n, m, p and ...
|
||||
TVPIW(PIXPLLDATA, m);
|
||||
TVPIW(PIXPLLDATA, p | 0xb0);
|
||||
WAIT_FOR_PLL_LOCK (PIX, return B_ERROR); // ... wait for PLL lock
|
||||
if (1) REREAD_PLL (PIX);
|
||||
DXIW(TVP_PLLADDR, 0x00); // 0x2c: 2.4 select N to ...
|
||||
DXIW(TVP_PIXPLLDATA, n | 0xc0); // 0x2d: ... load n, m, p and ...
|
||||
DXIW(TVP_PIXPLLDATA, m);
|
||||
DXIW(TVP_PIXPLLDATA, p | 0xb0);
|
||||
WAIT_FOR_PLL_LOCK (TVP_PIX, return B_ERROR); // ... wait for PLL lock
|
||||
|
||||
// now compute parameters for the loop PLL (24bpp not available) see 2.4.3.1
|
||||
k = 1; // ?? external division factor between RCLK and LCLK
|
||||
n = (65 - (4 * (PIXEL_BUS_WIDTH64? 64: 32)) / bpp);
|
||||
// does 32bit DAC path exists for MIL1/2? if so, do this via si->ps...
|
||||
// n = (65 - (4 * (PIXEL_BUS_WIDTH64? 64: 32)) / bpp);
|
||||
n = (65 - (4 * 64) / bpp);
|
||||
m = 61;
|
||||
z = (FVCO_MIN * (65 - n)) / (4 * fd * k);
|
||||
q = 0;
|
||||
@@ -520,19 +94,18 @@ status_t mil2_dac_set_pix_pll (float f_need, int bpp)
|
||||
}
|
||||
LOG(2,("mil2_dac_set_pix_pll loop PLL, nmpq 0x%02x 0x%02x 0x%02x 0x%02x\n",
|
||||
n, m, p, q));
|
||||
TVPIW(MEMCLKCTRL, (TVPIR(MEMCLKCTRL) & 0xf8) | q | 0x20); // 0x39: 2.4.2 table 2.13
|
||||
DXIW(TVP_MEMCLKCTRL, (DXIR(TVP_MEMCLKCTRL) & 0xf8) | q | 0x20); // 0x39: 2.4.2 table 2.13
|
||||
LOG(2,("mil2_dac_set_pix_pll loop PLL, nmpq 0x%02x 0x%02x 0x%02x 0x%02x\n",
|
||||
n, m, p, q));
|
||||
|
||||
// now setup the loop PLL
|
||||
LOG(2,("mil2_dac_set_pix_pll loop PLL, nmpq 0x%02x 0x%02x 0x%02x 0x%02x\n",
|
||||
n, m, p, q));
|
||||
TVPIW(PLLADDR, 0x00); // 0x2c: 2.4 select N to ...
|
||||
TVPIW(LOOPLLDATA, n | 0xc0); // 0x2f: ... load n, m, p and ...
|
||||
TVPIW(LOOPLLDATA, m);
|
||||
TVPIW(LOOPLLDATA, p | 0xf0);
|
||||
WAIT_FOR_PLL_LOCK (LOO, return B_ERROR); // ... wait for PLL lock
|
||||
if (1) REREAD_PLL (LOO);
|
||||
DXIW(TVP_PLLADDR, 0x00); // 0x2c: 2.4 select N to ...
|
||||
DXIW(TVP_LOOPLLDATA, n | 0xc0); // 0x2f: ... load n, m, p and ...
|
||||
DXIW(TVP_LOOPLLDATA, m);
|
||||
DXIW(TVP_LOOPLLDATA, p | 0xf0);
|
||||
WAIT_FOR_PLL_LOCK (TVP_LOO, return B_ERROR); // ... wait for PLL lock
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -544,68 +117,63 @@ static status_t mil2_dac_set_mem_pll (float f_need, float *mclk)
|
||||
uint8 n, m, p;
|
||||
uint8 n_pix, m_pix, p_pix;
|
||||
uint8 memclkctrl;
|
||||
|
||||
display_mode target;
|
||||
target.timing.pixel_clock = (f_need * 1000);
|
||||
|
||||
status = mil2_dac_pix_pll_find (f_need, mclk, &m, &n, &p);
|
||||
LOG(4,("mil2_dac_set_sys_pll need %fMHz\n", f_need));
|
||||
//fixme: MIL has same restrictions for pixel and system PLL, so Apsed did this:
|
||||
status = gx00_dac_pix_pll_find(target, mclk, &m, &n, &p, 0);
|
||||
if (status != B_OK) return status;
|
||||
LOG(2,("mil2_dac_set_mem_pll need %fMHz got %fMHz, nmp 0x%02x 0x%02x 0x%02x\n",
|
||||
f_need, *mclk, n, m, p));
|
||||
|
||||
// follows (!strictly) TVP3026 2.4.2.1, extended mode setup
|
||||
|
||||
// 0) save PIXPLL nmp to restore it at end
|
||||
TVPIW(PLLADDR, 0x00);
|
||||
n_pix = TVPIR(PIXPLLDATA);
|
||||
TVPIW(PLLADDR, 0x15);
|
||||
m_pix = TVPIR(PIXPLLDATA);
|
||||
TVPIW(PLLADDR, 0x2a);
|
||||
p_pix = TVPIR(PIXPLLDATA);
|
||||
if (1) REREAD_PLL (PIX);
|
||||
DXIW(TVP_PLLADDR, 0x00);
|
||||
n_pix = DXIR(TVP_PIXPLLDATA);
|
||||
DXIW(TVP_PLLADDR, 0x15);
|
||||
m_pix = DXIR(TVP_PIXPLLDATA);
|
||||
DXIW(TVP_PLLADDR, 0x2a);
|
||||
p_pix = DXIR(TVP_PIXPLLDATA);
|
||||
|
||||
// 1) disable pixel PLL, set pixel PLL at MCLK freq and poll for lock
|
||||
TVPIW(PLLADDR, 0x2a); // 0x2c: 2.4 select P to ...
|
||||
TVPIW(PIXPLLDATA, 0x00); // 0x2d: 2.4.1 ... stop the PLL
|
||||
TVPIW(PLLADDR, 0x00); // 0x2c: 2.4 select N to ...
|
||||
TVPIW(PIXPLLDATA, n | 0xc0); // 0x2d: ... load n, m, p and ...
|
||||
TVPIW(PIXPLLDATA, m);
|
||||
TVPIW(PIXPLLDATA, p | 0xb0);
|
||||
WAIT_FOR_PLL_LOCK (PIX, return B_ERROR); // ... wait for PLL lock
|
||||
if (1) REREAD_PLL (PIX);
|
||||
DXIW(TVP_PLLADDR, 0x2a); // 0x2c: 2.4 select P to ...
|
||||
DXIW(TVP_PIXPLLDATA, 0x00); // 0x2d: 2.4.1 ... stop the PLL
|
||||
DXIW(TVP_PLLADDR, 0x00); // 0x2c: 2.4 select N to ...
|
||||
DXIW(TVP_PIXPLLDATA, n | 0xc0); // 0x2d: ... load n, m, p and ...
|
||||
DXIW(TVP_PIXPLLDATA, m);
|
||||
DXIW(TVP_PIXPLLDATA, p | 0xb0);
|
||||
WAIT_FOR_PLL_LOCK (TVP_PIX, return B_ERROR); // ... wait for PLL lock
|
||||
|
||||
// 2) select pixel clock as dot clock source
|
||||
VGAW (MISCW, VGAR(MISCR) | 0x0c); // PLLSEL(1,0) set to 1x
|
||||
|
||||
// 3) output dot clock on MCLK pin
|
||||
memclkctrl = TVPIR(MEMCLKCTRL) & 0xe7;
|
||||
TVPIW(MEMCLKCTRL, memclkctrl | (0x00 << 3));
|
||||
TVPIW(MEMCLKCTRL, memclkctrl | (0x01 << 3));
|
||||
memclkctrl = DXIR(TVP_MEMCLKCTRL) & 0xe7;
|
||||
DXIW(TVP_MEMCLKCTRL, memclkctrl | (0x00 << 3));
|
||||
DXIW(TVP_MEMCLKCTRL, memclkctrl | (0x01 << 3));
|
||||
|
||||
// 4) disable mem PLL, set mem PLL at MCLK freq and poll for lock
|
||||
if (1) REREAD_PLL (MEM);
|
||||
TVPIW(PLLADDR, 0x2a);
|
||||
TVPIW(MEMPLLDATA, 0x00);
|
||||
TVPIW(PLLADDR, 0x00);
|
||||
TVPIW(MEMPLLDATA, n | 0xc0);
|
||||
TVPIW(MEMPLLDATA, m);
|
||||
TVPIW(MEMPLLDATA, p | 0xb0);
|
||||
WAIT_FOR_PLL_LOCK (MEM, return B_ERROR);
|
||||
if (1) REREAD_PLL (MEM);
|
||||
DXIW(TVP_PLLADDR, 0x2a);
|
||||
DXIW(TVP_MEMPLLDATA, 0x00);
|
||||
DXIW(TVP_PLLADDR, 0x00);
|
||||
DXIW(TVP_MEMPLLDATA, n | 0xc0);
|
||||
DXIW(TVP_MEMPLLDATA, m);
|
||||
DXIW(TVP_MEMPLLDATA, p | 0xb0);
|
||||
WAIT_FOR_PLL_LOCK (TVP_MEM, return B_ERROR);
|
||||
|
||||
// 5) output mem clock on MCLK pin
|
||||
TVPIW(MEMCLKCTRL, memclkctrl | (0x02 << 3));
|
||||
TVPIW(MEMCLKCTRL, memclkctrl | (0x03 << 3));
|
||||
DXIW(TVP_MEMCLKCTRL, memclkctrl | (0x02 << 3));
|
||||
DXIW(TVP_MEMCLKCTRL, memclkctrl | (0x03 << 3));
|
||||
|
||||
// 6) restaure pixel clock as it was
|
||||
TVPIW(PLLADDR, 0x2a);
|
||||
TVPIW(PIXPLLDATA, 0x00);
|
||||
TVPIW(PLLADDR, 0x00);
|
||||
// TVPIW(PIXPLLDATA, n_pix);
|
||||
// TVPIW(PIXPLLDATA, m_pix);
|
||||
// TVPIW(PIXPLLDATA, p_pix);
|
||||
TVPIW(PIXPLLDATA, n_pix | 0xc0);
|
||||
TVPIW(PIXPLLDATA, m_pix);
|
||||
TVPIW(PIXPLLDATA, p_pix | 0xb0);
|
||||
WAIT_FOR_PLL_LOCK (PIX, return B_ERROR);
|
||||
if (1) REREAD_PLL (PIX);
|
||||
DXIW(TVP_PLLADDR, 0x2a);
|
||||
DXIW(TVP_PIXPLLDATA, 0x00);
|
||||
DXIW(TVP_PLLADDR, 0x00);
|
||||
DXIW(TVP_PIXPLLDATA, n_pix | 0xc0);
|
||||
DXIW(TVP_PIXPLLDATA, m_pix);
|
||||
DXIW(TVP_PIXPLLDATA, p_pix | 0xb0);
|
||||
WAIT_FOR_PLL_LOCK (TVP_PIX, return B_ERROR);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -619,8 +187,6 @@ status_t mil2_dac_init (void)
|
||||
uint32 option;
|
||||
uint32 rfhcnt, nogscale, memconfig;
|
||||
|
||||
dump_mil2();
|
||||
|
||||
LOG(4, ("mil2_dac_init MISC 0x%02x\n", VGAR(MISCR)));
|
||||
CFGW(DEVCTRL,(2|CFGR(DEVCTRL))); // enable device response (already enabled here!)
|
||||
VGAW_I(CRTC,0x11,0); // allow me to change CRTC
|
||||
@@ -658,11 +224,12 @@ rfhcnt_found:
|
||||
LOG(2,("mil2_dac_init: found refresh count %d nogscale %d for %fMHz\n",
|
||||
rfhcnt, nogscale, mclk));
|
||||
|
||||
memconfig = 0x00; // 32 bits RAMDAC
|
||||
memconfig = 0x01; // 64 bits RAMDAC
|
||||
memconfig = 0x01; // worst case scenario: 64 bits RAMDAC (= tvp3026m) with >2Mb RAM.
|
||||
option = CFGR(OPTION) & 0xffd0cfff;
|
||||
CFGW(OPTION, option | (nogscale << 21) | (rfhcnt << 16) | (memconfig << 12));
|
||||
LOG(2,("mil2_dac_init: OPTION 0x%08x\n", CFGR(OPTION)));
|
||||
|
||||
|
||||
//r: select indirect cursor control register and set defaults
|
||||
DXIW(CURCTRL, 0x00);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user