diff options
-rw-r--r-- | vidix/drivers/Makefile | 11 | ||||
-rw-r--r-- | vidix/drivers/savage_regs.h | 303 | ||||
-rw-r--r-- | vidix/drivers/savage_vid.c | 1475 |
3 files changed, 1788 insertions, 1 deletions
diff --git a/vidix/drivers/Makefile b/vidix/drivers/Makefile index d028ca2ba5..ae33a14b8a 100644 --- a/vidix/drivers/Makefile +++ b/vidix/drivers/Makefile @@ -64,7 +64,13 @@ UNICHROME_OBJS=unichrome_vid.o UNICHROME_LIBS=-L../../libdha -ldha -lm UNICHROME_CFLAGS=$(OPTFLAGS) -fPIC -I. -I.. -all: $(CYBERBLADE_VID) $(RADEON_VID) $(RAGE128_VID) $(MACH64_VID) $(NVIDIA_VID) $(GENFB_VID) $(MGA_VID) $(MGA_CRTC2_VID) $(PM3_VID) $(SIS_VID) $(UNICHROME_VID) +SAVAGE_VID=savage_vid.so +SAVAGE_SRCS=savage_vid.c +SAVAGE_OBJS=savage_vid.o +SAVAGE_LIBS=-L../../libdha -ldha -lm +SAVAGE_CFLAGS=$(OPTFLAGS) -fPIC -I. -I.. + +all: $(CYBERBLADE_VID) $(RADEON_VID) $(RAGE128_VID) $(MACH64_VID) $(NVIDIA_VID) $(GENFB_VID) $(MGA_VID) $(MGA_CRTC2_VID) $(PM3_VID) $(SIS_VID) $(UNICHROME_VID) $(SAVAGE_VID) .SUFFIXES: .c .o @@ -137,6 +143,9 @@ $(UNICHROME_OBJS): $(UNICHROME_SRCS) $(UNICHROME_VID): $(UNICHROME_OBJS) $(CC) -shared $(UNICHROME_OBJS) $(UNICHROME_LIBS) -Wl,-soname,$(UNICHROME_VID) -o $(UNICHROME_VID) +$(SAVAGE_VID): $(SAVAGE_OBJS) + $(CC) -shared $(SAVAGE_OBJS) $(SAVAGE_LIBS) -Wl,-soname,$(SAVAGE_VID) -o $(SAVAGE_VID) + clean: rm -f *.o *.so *~ diff --git a/vidix/drivers/savage_regs.h b/vidix/drivers/savage_regs.h new file mode 100644 index 0000000000..0272e87b4b --- /dev/null +++ b/vidix/drivers/savage_regs.h @@ -0,0 +1,303 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/savage/savage_regs.h,v 1.10 2001/11/04 22:17:48 alanh Exp $ */ + +#ifndef _SAVAGE_REGS_H +#define _SAVAGE_REGS_H + +/* These are here until xf86PciInfo.h is updated. */ + +#ifndef PCI_CHIP_S3TWISTER_P +#define PCI_CHIP_S3TWISTER_P 0x8d01 +#endif +#ifndef PCI_CHIP_S3TWISTER_K +#define PCI_CHIP_S3TWISTER_K 0x8d02 +#endif +#ifndef PCI_CHIP_SUPSAV_MX128 +#define PCI_CHIP_SUPSAV_MX128 0x8c22 +#define PCI_CHIP_SUPSAV_MX64 0x8c24 +#define PCI_CHIP_SUPSAV_MX64C 0x8c26 +#define PCI_CHIP_SUPSAV_IX128SDR 0x8c2a +#define PCI_CHIP_SUPSAV_IX128DDR 0x8c2b +#define PCI_CHIP_SUPSAV_IX64SDR 0x8c2c +#define PCI_CHIP_SUPSAV_IX64DDR 0x8c2d +#define PCI_CHIP_SUPSAV_IXCSDR 0x8c2e +#define PCI_CHIP_SUPSAV_IXCDDR 0x8c2f +#endif +#ifndef PCI_CHIP_PROSAVAGE_DDR +#define PCI_CHIP_PROSAVAGE_DDR 0x8d03 +#define PCI_CHIP_PROSAVAGE_DDRK 0x8d04 +#endif + +#define S3_SAVAGE3D_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX)) + +#define S3_SAVAGE4_SERIES(chip) ((chip==S3_SAVAGE4) || (chip==S3_PROSAVAGE)) + +#define S3_SAVAGE_MOBILE_SERIES(chip) ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE)) + +#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000)) + + +/* Chip tags. These are used to group the adapters into + * related families. + */ + + +enum S3CHIPTAGS { + S3_UNKNOWN = 0, + S3_SAVAGE3D, + S3_SAVAGE_MX, + S3_SAVAGE4, + S3_PROSAVAGE, + S3_SUPERSAVAGE, + S3_SAVAGE2000, + S3_LAST +}; + +typedef struct { + unsigned int mode, refresh; + unsigned char SR08, SR0E, SR0F; + unsigned char SR10, SR11, SR12, SR13, SR15, SR18, SR1B, SR29, SR30; + unsigned char SR54[8]; + unsigned char Clock; + unsigned char CR31, CR32, CR33, CR34, CR36, CR3A, CR3B, CR3C; + unsigned char CR40, CR41, CR42, CR43, CR45; + unsigned char CR50, CR51, CR53, CR55, CR58, CR5B, CR5D, CR5E; + unsigned char CR60, CR63, CR65, CR66, CR67, CR68, CR69, CR6D, CR6F; + unsigned char CR86, CR88; + unsigned char CR90, CR91, CRB0; + unsigned int STREAMS[22]; /* yuck, streams regs */ + unsigned int MMPR0, MMPR1, MMPR2, MMPR3; +} SavageRegRec, *SavageRegPtr; + + + +#define BIOS_BSIZE 1024 +#define BIOS_BASE 0xc0000 + +#define SAVAGE_NEWMMIO_REGBASE_S3 0x1000000 /* 16MB */ +#define SAVAGE_NEWMMIO_REGBASE_S4 0x0000000 +#define SAVAGE_NEWMMIO_REGSIZE 0x0080000 /* 512kb */ +#define SAVAGE_NEWMMIO_VGABASE 0x8000 + +#define BASE_FREQ 14.31818 + +#define FIFO_CONTROL_REG 0x8200 +#define MIU_CONTROL_REG 0x8204 +#define STREAMS_TIMEOUT_REG 0x8208 +#define MISC_TIMEOUT_REG 0x820c + +/* Stream Processor 1 */ + +/* Primary Stream 1 Frame Buffer Address 0 */ +#define PRI_STREAM_FBUF_ADDR0 0x81c0 +/* Primary Stream 1 Frame Buffer Address 0 */ +#define PRI_STREAM_FBUF_ADDR1 0x81c4 +/* Primary Stream 1 Stride */ +#define PRI_STREAM_STRIDE 0x81c8 +/* Primary Stream 1 Frame Buffer Size */ +#define PRI_STREAM_BUFFERSIZE 0x8214 + +/* Secondary stream 1 Color/Chroma Key Control */ +#define SEC_STREAM_CKEY_LOW 0x8184 +/* Secondary stream 1 Chroma Key Upper Bound */ +#define SEC_STREAM_CKEY_UPPER 0x8194 +/* Blend Control of Secondary Stream 1 & 2 */ +#define BLEND_CONTROL 0x8190 +/* Secondary Stream 1 Color conversion/Adjustment 1 */ +#define SEC_STREAM_COLOR_CONVERT1 0x8198 +/* Secondary Stream 1 Color conversion/Adjustment 2 */ +#define SEC_STREAM_COLOR_CONVERT2 0x819c +/* Secondary Stream 1 Color conversion/Adjustment 3 */ +#define SEC_STREAM_COLOR_CONVERT3 0x81e4 +/* Secondary Stream 1 Horizontal Scaling */ +#define SEC_STREAM_HSCALING 0x81a0 +/* Secondary Stream 1 Frame Buffer Size */ +#define SEC_STREAM_BUFFERSIZE 0x81a8 +/* Secondary Stream 1 Horizontal Scaling Normalization (2K only) */ +#define SEC_STREAM_HSCALE_NORMALIZE 0x81ac +/* Secondary Stream 1 Horizontal Scaling */ +#define SEC_STREAM_VSCALING 0x81e8 +/* Secondary Stream 1 Frame Buffer Address 0 */ +#define SEC_STREAM_FBUF_ADDR0 0x81d0 +/* Secondary Stream 1 Frame Buffer Address 1 */ +#define SEC_STREAM_FBUF_ADDR1 0x81d4 +/* Secondary Stream 1 Frame Buffer Address 2 */ +#define SEC_STREAM_FBUF_ADDR2 0x81ec +/* Secondary Stream 1 Stride */ +#define SEC_STREAM_STRIDE 0x81d8 +/* Secondary Stream 1 Window Start Coordinates */ +#define SEC_STREAM_WINDOW_START 0x81f8 +/* Secondary Stream 1 Window Size */ +#define SEC_STREAM_WINDOW_SZ 0x81fc +/* Secondary Streams Tile Offset */ +#define SEC_STREAM_TILE_OFF 0x821c +/* Secondary Stream 1 Opaque Overlay Control */ +#define SEC_STREAM_OPAQUE_OVERLAY 0x81dc + + +/* Stream Processor 2 */ + +/* Primary Stream 2 Frame Buffer Address 0 */ +#define PRI_STREAM2_FBUF_ADDR0 0x81b0 +/* Primary Stream 2 Frame Buffer Address 1 */ +#define PRI_STREAM2_FBUF_ADDR1 0x81b4 +/* Primary Stream 2 Stride */ +#define PRI_STREAM2_STRIDE 0x81b8 +/* Primary Stream 2 Frame Buffer Size */ +#define PRI_STREAM2_BUFFERSIZE 0x8218 + +/* Secondary Stream 2 Color/Chroma Key Control */ +#define SEC_STREAM2_CKEY_LOW 0x8188 +/* Secondary Stream 2 Chroma Key Upper Bound */ +#define SEC_STREAM2_CKEY_UPPER 0x818c +/* Secondary Stream 2 Horizontal Scaling */ +#define SEC_STREAM2_HSCALING 0x81a4 +/* Secondary Stream 2 Horizontal Scaling */ +#define SEC_STREAM2_VSCALING 0x8204 +/* Secondary Stream 2 Frame Buffer Size */ +#define SEC_STREAM2_BUFFERSIZE 0x81ac +/* Secondary Stream 2 Frame Buffer Address 0 */ +#define SEC_STREAM2_FBUF_ADDR0 0x81bc +/* Secondary Stream 2 Frame Buffer Address 1 */ +#define SEC_STREAM2_FBUF_ADDR1 0x81e0 +/* Secondary Stream 2 Frame Buffer Address 2 */ +#define SEC_STREAM2_FBUF_ADDR2 0x8208 +/* Multiple Buffer/LPB and Secondary Stream 2 Stride */ +#define SEC_STREAM2_STRIDE_LPB 0x81cc +/* Secondary Stream 2 Color conversion/Adjustment 1 */ +#define SEC_STREAM2_COLOR_CONVERT1 0x81f0 +/* Secondary Stream 2 Color conversion/Adjustment 2 */ +#define SEC_STREAM2_COLOR_CONVERT2 0x81f4 +/* Secondary Stream 2 Color conversion/Adjustment 3 */ +#define SEC_STREAM2_COLOR_CONVERT3 0x8200 +/* Secondary Stream 2 Window Start Coordinates */ +#define SEC_STREAM2_WINDOW_START 0x820c +/* Secondary Stream 2 Window Size */ +#define SEC_STREAM2_WINDOW_SZ 0x8210 +/* Secondary Stream 2 Opaque Overlay Control */ +#define SEC_STREAM2_OPAQUE_OVERLAY 0x8180 + + +/* savage 2000 */ +#define SEC_STREAM_COLOR_CONVERT0_2000 0x8198 +#define SEC_STREAM_COLOR_CONVERT1_2000 0x819c +#define SEC_STREAM_COLOR_CONVERT2_2000 0x81e0 +#define SEC_STREAM_COLOR_CONVERT3_2000 0x81e4 + +#define SUBSYS_STAT_REG 0x8504 + +#define SRC_BASE 0xa4d4 +#define DEST_BASE 0xa4d8 +#define CLIP_L_R 0xa4dc +#define CLIP_T_B 0xa4e0 +#define DEST_SRC_STR 0xa4e4 +#define MONO_PAT_0 0xa4e8 +#define MONO_PAT_1 0xa4ec + +/* Constants for CR69. */ + +#define CRT_ACTIVE 0x01 +#define LCD_ACTIVE 0x02 +#define TV_ACTIVE 0x04 +#define CRT_ATTACHED 0x10 +#define LCD_ATTACHED 0x20 +#define TV_ATTACHED 0x40 + + +/* + * reads from SUBSYS_STAT + */ +#define STATUS_WORD0 (INREG(0x48C00)) +#define ALT_STATUS_WORD0 (INREG(0x48C60)) +#define MAXLOOP 0xffffff +#define IN_SUBSYS_STAT() (INREG(SUBSYS_STAT_REG)) + +#define MAXFIFO 0x7f00 + +/* + * NOTE: don't remove 'VGAIN8(vgaCRIndex);'. + * If not present it will cause lockups on Savage4. + * Ask S3, why. + */ +/*#define VerticalRetraceWait() \ +{ \ + VGAIN8(0x3d0+4); \ + VGAOUT8(0x3d0+4, 0x17); \ + if (VGAIN8(0x3d0+5) & 0x80) { \ + while ((VGAIN8(0x3d0 + 0x0a) & 0x08) == 0x08) ; \ + while ((VGAIN8(0x3d0 + 0x0a) & 0x08) == 0x00) ; \ + } \ +} +*/ + +#define VerticalRetraceWait() \ +do { \ + VGAIN8(0x3d4); \ + VGAOUT8(0x3d4, 0x17); \ + if (VGAIN8(0x3d5) & 0x80) { \ + int i = 0x10000; \ + while ((VGAIN8(0x3da) & 0x08) == 0x08 && i--) ; \ + i = 0x10000; \ + while ((VGAIN8(0x3da) & 0x08) == 0x00 && i--) ; \ + } \ +} while (0) + + +#define I2C_REG 0xa0 +#define InI2CREG(a) \ +{ \ + VGAOUT8(0x3d0 + 4, I2C_REG); \ + a = VGAIN8(0x3d0 + 5); \ +} + +#define OutI2CREG(a) \ +{ \ + VGAOUT8(0x3d0 + 4, I2C_REG); \ + VGAOUT8(0x3d0 + 5, a); \ +} + +#define HZEXP_COMP_1 0x54 +#define HZEXP_BORDER 0x58 +#define HZEXP_FACTOR_IGA1 0x59 + +#define VTEXP_COMP_1 0x56 +#define VTEXP_BORDER 0x5a +#define VTEXP_FACTOR_IGA1 0x5b + +#define EC1_CENTER_ON 0x10 +#define EC1_EXPAND_ON 0x0c + +#define MODE_24 24 + +#if (MODE_24 == 32) +# define BYTES_PP24 4 +#else +# define BYTES_PP24 3 +#endif + +#define OVERLAY_DEPTH 16 + +#define STREAMS_MODE32 0x7 +#define STREAMS_MODE24 0x6 +#define STREAMS_MODE16 0x5 /* @@@ */ + + +#define DEPTH_BPP(depth) (depth == 24 ? (BYTES_PP24 << 3) : (depth + 7) & ~0x7) +#define DEPTH_2ND(depth) (depth > 8 ? depth\ + : OVERLAY_DEPTH) +#define SSTREAMS_MODE(bpp) (bpp > 16 ? (bpp > 24 ? STREAMS_MODE32 :\ + STREAMS_MODE24) : STREAMS_MODE16) + +#define HSCALING_Shift 0 +#define HSCALING_Mask (((1L << 16)-1) << HSCALING_Shift) +#define HSCALING(w0,w1) ((((unsigned int)(((double)w0/(double)w1) * (1 << 15))) \ + << HSCALING_Shift) \ + & HSCALING_Mask) + +#define VSCALING_Shift 0 +#define VSCALING_Mask (((1L << 20)-1) << VSCALING_Shift) +#define VSCALING(h0,h1) ((((unsigned int) (((double)h0/(double)h1) * (1 << 15))) \ + << VSCALING_Shift) \ + & VSCALING_Mask) + + +#endif /* _SAVAGE_REGS_H */ diff --git a/vidix/drivers/savage_vid.c b/vidix/drivers/savage_vid.c new file mode 100644 index 0000000000..a3d7b8584b --- /dev/null +++ b/vidix/drivers/savage_vid.c @@ -0,0 +1,1475 @@ +/* + Driver for S3 Savage Series + + Copyright (C) 2004 by Reza Jelveh + + Based on the X11 driver and nvidia vid + + Thanks to Alex Deucher for Support + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Changes: + 2004-11-09 + Initial version + + To Do: + +*/ + + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <unistd.h> + +#include "../vidix.h" +#include "../fourcc.h" +#include "../../libdha/libdha.h" +#include "../../libdha/pci_ids.h" +#include "../../libdha/pci_names.h" +#include "../../config.h" + +#include "savage_regs.h" + + +#define VF_STREAMS_ON 0x0001 +#define BASE_PAD 0xf +#define FRAMEBUFFER_SIZE 1024*2000*4 +/************************************** + S3 streams processor +**************************************/ + +#define EXT_MISC_CTRL2 0x67 + +/* New streams */ + +/* CR67[2] = 1 : enable stream 1 */ +#define ENABLE_STREAM1 0x04 +/* CR67[1] = 1 : enable stream 2 */ +#define ENABLE_STREAM2 0x02 +/* mask to clear CR67[2,1] */ +#define NO_STREAMS 0xF9 +/* CR67[3] = 1 : Mem-mapped regs */ +#define USE_MM_FOR_PRI_STREAM 0x08 + +#define HDM_SHIFT 16 +#define HDSCALE_4 (2 << HDM_SHIFT) +#define HDSCALE_8 (3 << HDM_SHIFT) +#define HDSCALE_16 (4 << HDM_SHIFT) +#define HDSCALE_32 (5 << HDM_SHIFT) +#define HDSCALE_64 (6 << HDM_SHIFT) + +/* Old Streams */ + +#define ENABLE_STREAMS_OLD 0x0c +#define NO_STREAMS_OLD 0xf3 +/* CR69[0] = 1 : Mem-mapped regs */ +#define USE_MM_FOR_PRI_STREAM_OLD 0x01 + +void SavageStreamsOn(); + +/* + * There are two different streams engines used in the Savage line. + * The old engine is in the 3D, 4, Pro, and Twister. + * The new engine is in the 2000, MX, IX, and Super. + */ + + +/* streams registers for old engine */ +#define PSTREAM_CONTROL_REG 0x8180 +#define COL_CHROMA_KEY_CONTROL_REG 0x8184 +#define SSTREAM_CONTROL_REG 0x8190 +#define CHROMA_KEY_UPPER_BOUND_REG 0x8194 +#define SSTREAM_STRETCH_REG 0x8198 +#define COLOR_ADJUSTMENT_REG 0x819C +#define BLEND_CONTROL_REG 0x81A0 +#define PSTREAM_FBADDR0_REG 0x81C0 +#define PSTREAM_FBADDR1_REG 0x81C4 +#define PSTREAM_STRIDE_REG 0x81C8 +#define DOUBLE_BUFFER_REG 0x81CC +#define SSTREAM_FBADDR0_REG 0x81D0 +#define SSTREAM_FBADDR1_REG 0x81D4 +#define SSTREAM_STRIDE_REG 0x81D8 +#define SSTREAM_VSCALE_REG 0x81E0 +#define SSTREAM_VINITIAL_REG 0x81E4 +#define SSTREAM_LINES_REG 0x81E8 +#define STREAMS_FIFO_REG 0x81EC +#define PSTREAM_WINDOW_START_REG 0x81F0 +#define PSTREAM_WINDOW_SIZE_REG 0x81F4 +#define SSTREAM_WINDOW_START_REG 0x81F8 +#define SSTREAM_WINDOW_SIZE_REG 0x81FC +#define FIFO_CONTROL 0x8200 +#define PSTREAM_FBSIZE_REG 0x8300 +#define SSTREAM_FBSIZE_REG 0x8304 +#define SSTREAM_FBADDR2_REG 0x8308 + +#define OS_XY(x,y) (((x+1)<<16)|(y+1)) +#define OS_WH(x,y) (((x-1)<<16)|(y)) + +#define PCI_COMMAND_MEM 0x2 +#define MAX_FRAMES 3 +/** + * @brief Information on PCI device. + */ +pciinfo_t pci_info; + +/** + * @brief Unichrome driver colorkey settings. + */ +static vidix_grkey_t savage_grkey; + +static int frames[VID_PLAY_MAXFRAMES]; +uint8_t *vio; +uint8_t mclk_save[3]; + +#define outb(reg,val) OUTPORT8(reg,val) +#define inb(reg) INPORT8(reg) +#define outw(reg,val) OUTPORT16(reg,val) +#define inw(reg) INPORT16(reg) +#define outl(reg,val) OUTPORT32(reg,val) +#define inl(reg) INPORT32(reg) + + +/* + * PCI-Memory IO access macros. + */ +#define VID_WR08(p,i,val) (((uint8_t *)(p))[(i)]=(val)) +#define VID_RD08(p,i) (((uint8_t *)(p))[(i)]) + +#define VID_WR32(p,i,val) (((uint32_t *)(p))[(i)/4]=(val)) +#define VID_RD32(p,i) (((uint32_t *)(p))[(i)/4]) + +#ifndef USE_RMW_CYCLES +/* + * Can be used to inhibit READ-MODIFY-WRITE cycles. On by default. + */ + +#define MEM_BARRIER() __asm__ __volatile__ ("" : : : "memory") + +#undef VID_WR08 +#define VID_WR08(p,i,val) ({ MEM_BARRIER(); ((uint8_t *)(p))[(i)]=(val); }) +#undef VID_RD08 +#define VID_RD08(p,i) ({ MEM_BARRIER(); ((uint8_t *)(p))[(i)]; }) + +#undef VID_WR16 +#define VID_WR16(p,i,val) ({ MEM_BARRIER(); ((uint16_t *)(p))[(i)/2]=(val); }) +#undef VID_RD16 +#define VID_RD16(p,i) ({ MEM_BARRIER(); ((uint16_t *)(p))[(i)/2]; }) + +#undef VID_WR32 +#define VID_WR32(p,i,val) ({ MEM_BARRIER(); ((uint32_t *)(p))[(i)/4]=(val); }) +#undef VID_RD32 +#define VID_RD32(p,i) ({ MEM_BARRIER(); ((uint32_t *)(p))[(i)/4]; }) +#endif /* USE_RMW_CYCLES */ + +#define VID_AND32(p,i,val) VID_WR32(p,i,VID_RD32(p,i)&(val)) +#define VID_OR32(p,i,val) VID_WR32(p,i,VID_RD32(p,i)|(val)) +#define VID_XOR32(p,i,val) VID_WR32(p,i,VID_RD32(p,i)^(val)) + + +/* from x driver */ + +#define VGAIN8(addr) VID_RD08(info->control_base+0x8000, addr) +#define VGAIN16(addr) VID_RD16(info->control_base+0x8000, addr) +#define VGAIN(addr) VID_RD32(info->control_base+0x8000, addr) + +#define VGAOUT8(addr,val) VID_WR08(info->control_base+0x8000, addr, val) +#define VGAOUT16(addr,val) VID_WR16(info->control_base+0x8000, addr, val) +#define VGAOUT(addr,val) VID_WR32(info->control_base+0x8000, addr, val) + +#define INREG(addr) VID_RD32(info->control_base, addr) +#define OUTREG(addr,val) VID_WR32(info->control_base, addr, val) +#define INREG8(addr) VID_RD08(info->control_base, addr) +#define OUTREG8(addr,val) VID_WR08(info->control_base, addr, val) +#define INREG16(addr) VID_RD16(info->control_base, addr) +#define OUTREG16(addr,val) VID_WR16(info->control_base, addr, val) + +#define ALIGN_TO(v, n) (((v) + (n-1)) & ~(n-1)) + + +void debugout(unsigned int addr, unsigned int val); + + +struct savage_chip { + volatile uint32_t *PMC; /* general control */ + volatile uint32_t *PME; /* multimedia port */ + volatile uint32_t *PFB; /* framebuffer control */ + volatile uint32_t *PVIDEO; /* overlay control */ + volatile uint8_t *PCIO; /* SVGA (CRTC, ATTR) registers */ + volatile uint8_t *PVIO; /* SVGA (MISC, GRAPH, SEQ) registers */ + volatile uint32_t *PRAMIN; /* instance memory */ + volatile uint32_t *PRAMHT; /* hash table */ + volatile uint32_t *PRAMFC; /* fifo context table */ + volatile uint32_t *PRAMRO; /* fifo runout table */ + volatile uint32_t *PFIFO; /* fifo control region */ + volatile uint32_t *FIFO; /* fifo channels (USER) */ + volatile uint32_t *PGRAPH; /* graphics engine */ + + int arch; /* compatible NV_ARCH_XX define */ + unsigned long fbsize; /* framebuffer size */ + void (* lock) (struct savage_chip *, int); +}; +typedef struct savage_chip savage_chip; + + +struct savage_info { + unsigned int use_colorkey; + unsigned int colorkey; /* saved xv colorkey*/ + unsigned int vidixcolorkey; /*currently used colorkey*/ + unsigned int depth; + unsigned int bpp; + unsigned int videoFlags; + unsigned int format; + unsigned int pitch; + unsigned int blendBase; + unsigned int lastKnownPitch; + unsigned int displayWidth, displayHeight; + unsigned int brightness,hue,saturation,contrast; + unsigned int src_w,src_h; + unsigned int drw_w,drw_h; /*scaled width && height*/ + unsigned int wx,wy; /*window x && y*/ + unsigned int screen_x; /*screen width*/ + unsigned int screen_y; /*screen height*/ + unsigned long buffer_size; /* size of the image buffer */ + struct savage_chip chip; /* NV architecture structure */ + void* video_base; /* virtual address of control region */ + void* control_base; /* virtual address of fb region */ + unsigned long picture_base; /* direct pointer to video picture */ + unsigned long picture_offset; /* offset of video picture in frame buffer */ +// struct savage_dma dma; /* DMA structure */ + unsigned int cur_frame; + unsigned int num_frames; /* number of buffers */ + int bps; /* bytes per line */ + void (*SavageWaitIdle) (); + void (*SavageWaitFifo) (int space); +}; +typedef struct savage_info savage_info; + + +static savage_info* info; + + +/** + * @brief Unichrome driver vidix capabilities. + */ +static vidix_capability_t savage_cap = { + "Savage/ProSavage/Twister vidix", + "Reza Jelveh <reza.jelveh@tuhh.de>", + TYPE_OUTPUT, + {0, 0, 0, 0}, + 4096, + 4096, + 4, + 4, + -1, + FLAG_UPSCALER | FLAG_DOWNSCALER, + VENDOR_S3_INC, + -1, + {0, 0, 0, 0} +}; + +struct savage_cards { + unsigned short chip_id; + unsigned short arch; +}; + + +static +unsigned int GetBlendForFourCC( int id ) +{ + switch( id ) { + case IMGFMT_YUY2: + case IMGFMT_YV12: + case IMGFMT_I420: + return 1; + case IMGFMT_Y211: + return 4; + case IMGFMT_RGB15: + return 3; + case IMGFMT_RGB16: + return 5; + default: + return 0; + } +} + +/** + * @brief list of card IDs compliant with the Unichrome driver . + */ +static struct savage_cards savage_card_ids[] = { + /*[ProSavage PN133] AGP4X VGA Controller (Twister)*/ + { PCI_CHIP_S3TWISTER_P, S3_PROSAVAGE }, + /*[ProSavage KN133] AGP4X VGA Controller (TwisterK)*/ + { PCI_CHIP_S3TWISTER_K, S3_PROSAVAGE }, + /*ProSavage DDR*/ + { PCI_CHIP_PROSAVAGE_DDR , S3_PROSAVAGE }, + /*[ProSavageDDR P4M266 K] */ + { PCI_CHIP_PROSAVAGE_DDRK , S3_PROSAVAGE }, +}; + +void SavageSetColorOld() +{ + + + if( + (info->format == IMGFMT_RGB15) || + (info->format == IMGFMT_RGB16) + ) + { + OUTREG( COLOR_ADJUSTMENT_REG, 0 ); + } + else + { + /* Change 0..255 into 0..15 */ + long sat = info->saturation * 16 / 256; + double hue = info->hue * 0.017453292; + unsigned long hs1 = ((long)(sat * cos(hue))) & 0x1f; + unsigned long hs2 = ((long)(sat * sin(hue))) & 0x1f; + + OUTREG( COLOR_ADJUSTMENT_REG, + 0x80008000 | + (info->brightness + 128) | + ((info->contrast & 0xf8) << (12-7)) | + (hs1 << 16) | + (hs2 << 24) + ); + debugout( COLOR_ADJUSTMENT_REG, + 0x80008000 | + (info->brightness + 128) | + ((info->contrast & 0xf8) << (12-7)) | + (hs1 << 16) | + (hs2 << 24) + ); + + } +} + +void SavageSetColorKeyOld() +{ + int red, green, blue; + + /* Here, we reset the colorkey and all the controls. */ + + red = (info->vidixcolorkey & 0x00FF0000) >> 16; + green = (info->vidixcolorkey & 0x0000FF00) >> 8; + blue = info->vidixcolorkey & 0x000000FF; + + if( !info->vidixcolorkey ) { + printf("SavageSetColorKey disabling colorkey\n"); + OUTREG( COL_CHROMA_KEY_CONTROL_REG, 0 ); + OUTREG( CHROMA_KEY_UPPER_BOUND_REG, 0 ); + OUTREG( BLEND_CONTROL_REG, 0 ); + } + else { + switch (info->depth) { + // FIXME: isnt fixed yet + case 8: + OUTREG( COL_CHROMA_KEY_CONTROL_REG, + 0x37000000 | (info->vidixcolorkey & 0xFF) ); + OUTREG( CHROMA_KEY_UPPER_BOUND_REG, + 0x00000000 | (info->vidixcolorkey & 0xFF) ); + break; + case 15: + /* 15 bpp 555 */ + red&=0x1f; + green&=0x1f; + blue&=0x1f; + OUTREG( COL_CHROMA_KEY_CONTROL_REG, + 0x05000000 | (red<<19) | (green<<11) | (blue<<3) ); + OUTREG( CHROMA_KEY_UPPER_BOUND_REG, + 0x00000000 | (red<<19) | (green<<11) | (blue<<3) ); + break; + case 16: + /* 16 bpp 565 */ + red&=0x1f; + green&=0x3f; + blue&=0x1f; + OUTREG( COL_CHROMA_KEY_CONTROL_REG, + 0x16000000 | (red<<19) | (green<<10) | (blue<<3) ); + OUTREG( CHROMA_KEY_UPPER_BOUND_REG, + 0x00020002 | (red<<19) | (green<<10) | (blue<<3) ); + break; + case 24: + /* 24 bpp 888 */ + OUTREG( COL_CHROMA_KEY_CONTROL_REG, + 0x17000000 | (red<<16) | (green<<8) | (blue) ); + OUTREG( CHROMA_KEY_UPPER_BOUND_REG, + 0x00000000 | (red<<16) | (green<<8) | (blue) ); + break; + } + + /* We use destination colorkey */ + OUTREG( BLEND_CONTROL_REG, 0x05000000 ); + } +} + + +static void +SavageDisplayVideoOld( +){ + int vgaCRIndex, vgaCRReg, vgaIOBase; + unsigned int ssControl; + int cr92; + + + vgaIOBase = 0x3d0; + vgaCRIndex = vgaIOBase + 4; + vgaCRReg = vgaIOBase + 5; + +// if( psav->videoFourCC != id ) +// SavageStreamsOff(pScrn); + + if( !info->videoFlags & VF_STREAMS_ON ) + { + SavageStreamsOn(); + // SavageResetVideo(); + SavageSetColorOld(); + SavageSetColorKeyOld(); + } + + + + + /* Set surface format. */ + + OUTREG(SSTREAM_CONTROL_REG,GetBlendForFourCC(info->format) << 24 | info->src_w); + + debugout(SSTREAM_CONTROL_REG,GetBlendForFourCC(info->format) << 24 | info->src_w); + + /* Calculate horizontal scale factor. */ + + //FIXME: enable scaling + OUTREG(SSTREAM_STRETCH_REG, (info->src_w << 15) / info->drw_w ); +// debugout(SSTREAM_STRETCH_REG, 1 << 15); + + OUTREG(SSTREAM_LINES_REG, info->src_h ); + debugout(SSTREAM_LINES_REG, info->src_h ); + + + OUTREG(SSTREAM_VINITIAL_REG, 0 ); + debugout(SSTREAM_VINITIAL_REG, 0 ); + /* Calculate vertical scale factor. */ + +// OUTREG(SSTREAM_VSCALE_REG, 1 << 15); + OUTREG(SSTREAM_VSCALE_REG, VSCALING(info->src_h,info->drw_h) ); + debugout(SSTREAM_VSCALE_REG, VSCALING(info->src_h,info->drw_h) ); +// OUTREG(SSTREAM_VSCALE_REG, (info->src_h << 15) / info->drw_h ); + + /* Set surface location and stride. */ + + OUTREG(SSTREAM_FBADDR0_REG, info->picture_offset ); + debugout(SSTREAM_FBADDR0_REG, info->picture_offset ); + + OUTREG(SSTREAM_FBADDR1_REG, 0 ); + debugout(SSTREAM_FBADDR1_REG, 0 ); + + OUTREG(SSTREAM_STRIDE_REG, info->pitch ); + debugout(SSTREAM_STRIDE_REG, info->pitch ); + + OUTREG(SSTREAM_WINDOW_START_REG, OS_XY(info->wx, info->wy) ); + debugout(SSTREAM_WINDOW_START_REG, OS_XY(info->wx, info->wy) ); + OUTREG(SSTREAM_WINDOW_SIZE_REG, OS_WH(info->drw_w, info->drw_h) ); + debugout(SSTREAM_WINDOW_SIZE_REG, OS_WH(info->drw_w, info->drw_h) ); + + + + ssControl = 0; + + if( info->src_w > (info->drw_w << 1) ) + { + /* BUGBUG shouldn't this be >=? */ + if( info->src_w <= (info->drw_w << 2) ) + ssControl |= HDSCALE_4; + else if( info->src_w > (info->drw_w << 3) ) + ssControl |= HDSCALE_8; + else if( info->src_w > (info->drw_w << 4) ) + ssControl |= HDSCALE_16; + else if( info->src_w > (info->drw_w << 5) ) + ssControl |= HDSCALE_32; + else if( info->src_w > (info->drw_w << 6) ) + ssControl |= HDSCALE_64; + } + + ssControl |= info->src_w; + ssControl |= (1 << 24); + + //FIXME: enable scaling + OUTREG(SSTREAM_CONTROL_REG, ssControl); + debugout(SSTREAM_CONTROL_REG, ssControl); + + // FIXME: this should actually be enabled + + info->pitch = (info->pitch + 7) / 8; + VGAOUT8(vgaCRIndex, 0x92); + cr92 = VGAIN8(vgaCRReg); + VGAOUT8(vgaCRReg, (cr92 & 0x40) | (info->pitch >> 8) | 0x80); + VGAOUT8(vgaCRIndex, 0x93); + VGAOUT8(vgaCRReg, info->pitch); + OUTREG(STREAMS_FIFO_REG, 2 | 25 << 5 | 32 << 11); + + + + +} + +void SavageInitStreamsOld() +{ + /*unsigned long jDelta;*/ + unsigned long format = 0; + + /* + * For the OLD streams engine, several of these registers + * cannot be touched unless streams are on. Seems backwards to me; + * I'd want to set 'em up, then cut 'em loose. + */ + + + /*jDelta = pScrn->displayWidth * (pScrn->bitsPerPixel + 7) / 8;*/ + switch( info->depth ) { + case 8: format = 0 << 24; break; + case 15: format = 3 << 24; break; + case 16: format = 5 << 24; break; + case 24: format = 7 << 24; break; + } +#warning enable this again + OUTREG(PSTREAM_FBSIZE_REG, + info->screen_y * info->screen_x * (info->bpp >> 3)); + + OUTREG( PSTREAM_WINDOW_START_REG, OS_XY(0,0) ); + OUTREG( PSTREAM_WINDOW_SIZE_REG, OS_WH(info->screen_x, info->screen_y) ); + OUTREG( PSTREAM_FBADDR1_REG, 0 ); + /*OUTREG( PSTREAM_STRIDE_REG, jDelta );*/ + OUTREG( PSTREAM_CONTROL_REG, format ); + OUTREG( PSTREAM_FBADDR0_REG, 0 ); + + /*OUTREG( PSTREAM_FBSIZE_REG, jDelta * pScrn->virtualY >> 3 );*/ + + OUTREG( COL_CHROMA_KEY_CONTROL_REG, 0 ); + OUTREG( SSTREAM_CONTROL_REG, 0 ); + OUTREG( CHROMA_KEY_UPPER_BOUND_REG, 0 ); + OUTREG( SSTREAM_STRETCH_REG, 0 ); + OUTREG( COLOR_ADJUSTMENT_REG, 0 ); + OUTREG( BLEND_CONTROL_REG, 1 << 24 ); + OUTREG( DOUBLE_BUFFER_REG, 0 ); + OUTREG( SSTREAM_FBADDR0_REG, 0 ); + OUTREG( SSTREAM_FBADDR1_REG, 0 ); + OUTREG( SSTREAM_FBADDR2_REG, 0 ); + OUTREG( SSTREAM_FBSIZE_REG, 0 ); + OUTREG( SSTREAM_STRIDE_REG, 0 ); + OUTREG( SSTREAM_VSCALE_REG, 0 ); + OUTREG( SSTREAM_LINES_REG, 0 ); + OUTREG( SSTREAM_VINITIAL_REG, 0 ); +#warning is this needed? + OUTREG( SSTREAM_WINDOW_START_REG, OS_XY(0xfffe, 0xfffe) ); + OUTREG( SSTREAM_WINDOW_SIZE_REG, OS_WH(10,2) ); + +} + +void +SavageStreamsOn() +{ + unsigned char jStreamsControl; + unsigned short vgaCRIndex = 0x3d0 + 4; + unsigned short vgaCRReg = 0x3d0 + 5; + +// xf86ErrorFVerb(STREAMS_TRACE, "SavageStreamsOn\n" ); + + /* Sequence stolen from streams.c in M7 NT driver */ + + + enable_app_io (); + + /* Unlock extended registers. */ + + /* FIXME: it looks like mmaped io is broken with vgaout16 */ + VGAOUT16(vgaCRIndex, 0x4838 ); + VGAOUT16(vgaCRIndex, 0xa039); + VGAOUT16(0x3c4, 0x0608); + + + + VGAOUT8( vgaCRIndex, EXT_MISC_CTRL2 ); + + if( S3_SAVAGE_MOBILE_SERIES(info->chip.arch) ) + { +// SavageInitStreamsNew( pScrn ); + + jStreamsControl = VGAIN8( vgaCRReg ) | ENABLE_STREAM1; + + /* Wait for VBLANK. */ + VerticalRetraceWait(); + /* Fire up streams! */ + VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); + /* These values specify brightness, contrast, saturation and hue. */ + OUTREG( SEC_STREAM_COLOR_CONVERT1, 0x0000C892 ); + OUTREG( SEC_STREAM_COLOR_CONVERT2, 0x00039F9A ); + OUTREG( SEC_STREAM_COLOR_CONVERT3, 0x01F1547E ); + } + else if (info->chip.arch == S3_SAVAGE2000) + { +// SavageInitStreams2000( pScrn ); + + jStreamsControl = VGAIN8( vgaCRReg ) | ENABLE_STREAM1; + + /* Wait for VBLANK. */ + VerticalRetraceWait(); + /* Fire up streams! */ + VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); + /* These values specify brightness, contrast, saturation and hue. */ + OUTREG( SEC_STREAM_COLOR_CONVERT0_2000, 0x0000C892 ); + OUTREG( SEC_STREAM_COLOR_CONVERT1_2000, 0x00033400 ); + OUTREG( SEC_STREAM_COLOR_CONVERT2_2000, 0x000001CF ); + OUTREG( SEC_STREAM_COLOR_CONVERT3_2000, 0x01F1547E ); + } + else + { + jStreamsControl = VGAIN8( vgaCRReg ) | ENABLE_STREAMS_OLD; + + /* Wait for VBLANK. */ + + VerticalRetraceWait(); + + /* Fire up streams! */ + + VGAOUT16( vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2 ); + + SavageInitStreamsOld( ); + } + + /* Wait for VBLANK. */ + + VerticalRetraceWait(); + + /* Turn on secondary stream TV flicker filter, once we support TV. */ + + /* SR70 |= 0x10 */ + + info->videoFlags |= VF_STREAMS_ON; + +} + + + + +static void savage_getscreenproperties(struct savage_info *info){ + unsigned char bpp=0; + uint32_t width=0; + + uint32_t vgaIOBase, vgaCRIndex, vgaCRReg; + + vgaIOBase = 0x3d0; + vgaCRIndex = vgaIOBase + 4; + vgaCRReg = vgaIOBase + 5; + + + /* a little reversed from x driver source code */ + VGAOUT8(vgaCRIndex, 0x67); + bpp = VGAIN8(vgaCRReg); + + + switch (bpp&0xf0) { + case 0x00: + case 0x10: + info->depth=8; + info->bpp=8; + break; + case 0x20: + case 0x30: + info->depth=15; + info->bpp=16; + break; + case 0x40: + case 0x50: + info->depth=16; + info->bpp=16; + break; + case 0x70: + case 0xd0: + info->depth=24; + info->bpp=32; + break; + + + } + + + VGAOUT8(vgaCRIndex, 0x1); + info->screen_x = (1 + VGAIN8(vgaCRReg)) <<3; + /*get screen height*/ + /* get first 8 bits in VT_DISPLAY_END*/ + VGAOUT8(0x03D4, 0x12); + info->screen_y = VGAIN8(0x03D5); + VGAOUT8(0x03D4,0x07); + /* get 9th bit in CRTC_OVERFLOW*/ + info->screen_y |= (VGAIN8(0x03D5) &0x02)<<7; + /* and the 10th in CRTC_OVERFLOW*/ + info->screen_y |=(VGAIN8(0x03D5) &0x40)<<3; + ++info->screen_y; + + printf("screen_x = %d, screen_y = %d, bpp = %d\n",info->screen_x,info->screen_y,info->bpp); +} + + +void SavageStreamsOff() +{ + unsigned char jStreamsControl; + unsigned short vgaCRIndex = 0x3d0 + 4; + unsigned short vgaCRReg = 0x3d0 + 5; + + + /* Unlock extended registers. */ + + VGAOUT16(vgaCRIndex, 0x4838); + VGAOUT16(vgaCRIndex, 0xa039); + VGAOUT16(0x3c4, 0x0608); + + VGAOUT8( vgaCRIndex, EXT_MISC_CTRL2 ); + if( S3_SAVAGE_MOBILE_SERIES(info->chip.arch) || + (info->chip.arch == S3_SUPERSAVAGE) || + (info->chip.arch == S3_SAVAGE2000) ) + jStreamsControl = VGAIN8( vgaCRReg ) & NO_STREAMS; + else |