Mercurial > mplayer.hg
changeset 26096:e6a565ec1a3b
New S3 VIDIX driver.
Provides support for S3 Trio and S3 Virge chipsets.
This deprecates the old Savage driver that worked with latest chips only.
(synchronized with vidix.sf.net r326 and r327)
author | ben |
---|---|
date | Fri, 29 Feb 2008 20:01:28 +0000 |
parents | 7470a625bbdd |
children | 74106358c073 |
files | configure vidix/Makefile vidix/drivers.c vidix/s3_regs.h vidix/s3_vid.c |
diffstat | 5 files changed, 1153 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/configure Fri Feb 29 17:44:54 2008 +0000 +++ b/configure Fri Feb 29 20:01:28 2008 +0000 @@ -337,7 +337,7 @@ --disable-vidix-external disable external VIDIX [for x86 *nix] --with-vidix-drivers[=*] list of VIDIX drivers to be compiled in Available: cyberblade,ivtv,mach64,mga,mga_crtc2, - nvidia,pm2,pm3,radeon,rage128,savage,sis,unichrome + nvidia,pm2,pm3,radeon,rage128,s3,sis,unichrome --disable-vidix-pcidb disable VIDIX PCI device name database --enable-gl enable OpenGL video output [autodetect] --enable-dga2 enable DGA 2 support [autodetect] @@ -4246,8 +4246,8 @@ _vidix_drv_radeon=no _def_vidix_drv_rage128='#undef CONFIG_VIDIX_DRV_RAGE128' _vidix_drv_rage128=no -_def_vidix_drv_savage='#undef CONFIG_VIDIX_DRV_SAVAGE' -_vidix_drv_savage=no +_def_vidix_drv_s3='#undef CONFIG_VIDIX_DRV_S3' +_vidix_drv_s3=no _def_vidix_drv_sis='#undef CONFIG_VIDIX_DRV_SIS' _vidix_drv_sis=no _def_vidix_drv_unichrome='#undef CONFIG_VIDIX_DRV_UNICHROME' @@ -4277,7 +4277,7 @@ _def_vidix='#define CONFIG_VIDIX 1' _vosrc="$_vosrc vo_cvidix.c" _vomodules="cvidix $_vomodules" - test "$_vidix_drivers" || _vidix_drivers="cyberblade ivtv mach64 mga mga_crtc2 nvidia pm2 pm3 radeon rage128 savage sis unichrome" + test "$_vidix_drivers" || _vidix_drivers="cyberblade ivtv mach64 mga mga_crtc2 nvidia pm2 pm3 radeon rage128 s3 sis unichrome" test $_ivtv = "yes" || _vidix_drivers=`echo $_vidix_drivers | sed s/ivtv//` # some vidix drivers are meant to work on x86 only, discard them elsewhere @@ -7821,7 +7821,7 @@ VIDIX_PM3=$_vidix_drv_pm3 VIDIX_RADEON=$_vidix_drv_radeon VIDIX_RAGE128=$_vidix_drv_rage128 -VIDIX_SAVAGE=$_vidix_drv_savage +VIDIX_S3=$_vidix_drv_s3 VIDIX_SIS=$_vidix_drv_sis VIDIX_UNICHROME=$_vidix_drv_unichrome @@ -8504,7 +8504,7 @@ $_def_vidix_drv_pm3 $_def_vidix_drv_radeon $_def_vidix_drv_rage128 -$_def_vidix_drv_savage +$_def_vidix_drv_s3 $_def_vidix_drv_sis $_def_vidix_drv_unichrome $_def_vidix_pfx
--- a/vidix/Makefile Fri Feb 29 17:44:54 2008 +0000 +++ b/vidix/Makefile Fri Feb 29 20:01:28 2008 +0000 @@ -20,7 +20,7 @@ SRCS_MPLAYER-$(VIDIX_PM3) += pm3_vid.c SRCS_MPLAYER-$(VIDIX_RADEON) += radeon_vid.c SRCS_MPLAYER-$(VIDIX_RAGE128) += rage128_vid.c -SRCS_MPLAYER-$(VIDIX_SAVAGE) += savage_vid.c +SRCS_MPLAYER-$(VIDIX_S3) += s3_vid.c SRCS_MPLAYER-$(VIDIX_SIS) += sis_vid.c sis_bridge.c SRCS_MPLAYER-$(VIDIX_UNICHROME) += unichrome_vid.c
--- a/vidix/drivers.c Fri Feb 29 17:44:54 2008 +0000 +++ b/vidix/drivers.c Fri Feb 29 20:01:28 2008 +0000 @@ -42,7 +42,7 @@ extern VDXDriver pm3_drv; extern VDXDriver radeon_drv; extern VDXDriver rage128_drv; -extern VDXDriver savage_drv; +extern VDXDriver s3_drv; extern VDXDriver sis_drv; extern VDXDriver unichrome_drv; @@ -89,8 +89,8 @@ #ifdef CONFIG_VIDIX_DRV_RAGE128 vidix_register_driver (&rage128_drv); #endif -#ifdef CONFIG_VIDIX_DRV_SAVAGE - vidix_register_driver (&savage_drv); +#ifdef CONFIG_VIDIX_DRV_S3 + vidix_register_driver (&s3_drv); #endif #ifdef CONFIG_VIDIX_DRV_SIS vidix_register_driver (&sis_drv);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vidix/s3_regs.h Fri Feb 29 20:01:28 2008 +0000 @@ -0,0 +1,214 @@ +#ifndef _SAVAGE_REGS_H +#define _SAVAGE_REGS_H + +#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_TRIO64V, + S3_VIRGE, + S3_SAVAGE3D, + S3_SAVAGE_MX, + S3_SAVAGE4, + S3_PROSAVAGE, + S3_SUPERSAVAGE, + S3_SAVAGE2000, + S3_LAST +}; + +#define BIOS_BSIZE 1024 +#define BIOS_BASE 0xc0000 + +#define S3_NEWMMIO_REGBASE 0x1000000 /* 16MB */ +#define S3_NEWMMIO_REGSIZE 0x0010000 /* 64KB */ +#define S3_NEWMMIO_REGSIZE_SAVAGE 0x0080000 /* 512KB */ + +#define BASE_FREQ 14.31818 + +/* + * There are two different streams engines used in the S3 line. + * The old engine is in the Trio64, Virge, + * Savage3D, Savage4, SavagePro, and SavageTwister. + * The new engine is in the Savage2000, SavageMX, + * SavageIX, and SuperSavage. + */ + +/* Old engine registers */ +#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 OPAQUE_OVERLAY_CONTROL_REG 0x81DC +#define K1_VSCALE_REG 0x81E0 +#define SSTREAM_VSCALE_REG 0x81E0 +#define K2_VSCALE_REG 0x81E4 +#define SSTREAM_VINITIAL_REG 0x81E4 +#define DDA_VERT_REG 0x81E8 +#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 + +/* New engine registers */ +#define PRI_STREAM_FBUF_ADDR0 0x81c0 +#define PRI_STREAM_FBUF_ADDR1 0x81c4 +#define PRI_STREAM_STRIDE 0x81c8 +#define PRI_STREAM_BUFFERSIZE 0x8214 +#define SEC_STREAM_CKEY_LOW 0x8184 +#define SEC_STREAM_CKEY_UPPER 0x8194 +#define BLEND_CONTROL 0x8190 +#define SEC_STREAM_COLOR_CONVERT1 0x8198 +#define SEC_STREAM_COLOR_CONVERT2 0x819c +#define SEC_STREAM_COLOR_CONVERT3 0x81e4 +#define SEC_STREAM_HSCALING 0x81a0 +#define SEC_STREAM_BUFFERSIZE 0x81a8 +#define SEC_STREAM_HSCALE_NORMALIZE 0x81ac +#define SEC_STREAM_VSCALING 0x81e8 +#define SEC_STREAM_FBUF_ADDR0 0x81d0 +#define SEC_STREAM_FBUF_ADDR1 0x81d4 +#define SEC_STREAM_FBUF_ADDR2 0x81ec +#define SEC_STREAM_STRIDE 0x81d8 +#define SEC_STREAM_WINDOW_START 0x81f8 +#define SEC_STREAM_WINDOW_SZ 0x81fc +#define SEC_STREAM_TILE_OFF 0x821c +#define SEC_STREAM_OPAQUE_OVERLAY 0x81dc + +/* Savage 2000 registers */ +#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 + +/* Virge+ registers */ +#define FIFO_CONTROL_REG 0x8200 +#define MIU_CONTROL_REG 0x8204 +#define STREAMS_TIMEOUT_REG 0x8208 +#define MISC_TIMEOUT_REG 0x820c + +/* VGA stuff */ +#define vgaCRIndex 0x3d4 +#define vgaCRReg 0x3d5 + +/* CRT Control registers */ +#define EXT_MEM_CTRL1 0x53 +#define LIN_ADDR_CTRL 0x58 +#define EXT_MISC_CTRL2 0x67 + +/* Old engine constants */ +#define ENABLE_NEWMMIO 0x08 +#define ENABLE_LFB 0x10 +#define ENABLE_STREAMS_OLD 0x0c +#define NO_STREAMS_OLD 0xf3 + +/* New engine constants */ +#define ENABLE_STREAM1 0x04 +#define NO_STREAMS 0xF9 + +#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) + +/* Scaling operations */ +#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) + +/* Scaling factors */ +#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) + +/* Window parameters */ +#define OS_XY(x,y) (((x+1)<<16)|(y+1)) +#define OS_WH(x,y) (((x-1)<<16)|(y)) + +/* PCI stuff */ + +/* 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)) + +#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)) + +#endif /* _S3_REGS_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vidix/s3_vid.c Fri Feb 29 20:01:28 2008 +0000 @@ -0,0 +1,929 @@ +/* + * VIDIX driver for S3 chipsets. + * Copyright (C) 2004 Reza Jelveh + * + * This file is part of MPlayer. + * + * MPlayer 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. + * + * MPlayer 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 MPlayer; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Thanks to Alex Deucher for Support + * + * Trio/Virge support by Michael Kostylev + * + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <unistd.h> +#include <math.h> + +#include "vidix.h" +#include "vidixlib.h" +#include "fourcc.h" +#include "dha.h" +#include "pci_ids.h" +#include "pci_names.h" +#include "config.h" + +#include "s3_regs.h" + +static void S3SetColorKeyOld (void); +static void S3SetColorKeyNew (void); +static void S3SetColorKey2000 (void); +static void (*S3SetColorKey) (void) = NULL; + +static void S3SetColorOld (void); +static void S3SetColorNew (void); +static void S3SetColor2000 (void); +static void (*S3SetColor) (void) = NULL; + +static void S3DisplayVideoOld (void); +static void S3DisplayVideoNew (void); +static void S3DisplayVideo2000 (void); +static void (*S3DisplayVideo) (void) = NULL; + +static void S3InitStreamsOld (void); +static void S3InitStreamsNew (void); +static void S3InitStreams2000 (void); +static void (*S3InitStreams) (void) = NULL; + +pciinfo_t pci_info; + +struct s3_chip +{ + int arch; + unsigned long fbsize; + void (*lock) (struct s3_chip *, int); +}; +typedef struct s3_chip s3_chip; + +struct s3_info +{ + vidix_video_eq_t eq; + unsigned int use_colorkey; + unsigned int colorkey; + unsigned int vidixcolorkey; + unsigned int depth; + unsigned int bpp; + unsigned int format; + unsigned int pitch; + unsigned int blendBase; + unsigned int displayWidth, displayHeight; + unsigned int src_w, src_h; + unsigned int drw_w, drw_h; + unsigned int wx, wy; + unsigned int screen_x; + unsigned int screen_y; + unsigned long frame_size; + struct s3_chip chip; + void *video_base; + void *control_base; + unsigned long picture_base; + unsigned long picture_offset; + unsigned int num_frames; + int bps; +}; +typedef struct s3_info s3_info; + +static s3_info *info; + +static vidix_capability_t s3_cap = { + "S3 BES", + "Reza Jelveh, Michael Kostylev", + TYPE_OUTPUT, + {0, 0, 0, 0}, + 4096, + 4096, + 4, + 4, + -1, + FLAG_UPSCALER | FLAG_DOWNSCALER, + VENDOR_S3_INC, + -1, + {0, 0, 0, 0} +}; + +struct s3_cards +{ + unsigned short chip_id; + unsigned short arch; +}; + +static struct s3_cards s3_card_ids[] = { + /* Trio64V */ + {DEVICE_S3_INC_86C764_765_TRIO32_64_64V, S3_TRIO64V}, + {DEVICE_S3_INC_86C767_TRIO_64UV, S3_TRIO64V}, + {DEVICE_S3_INC_86C755_TRIO_64V2_DX, S3_TRIO64V}, + {DEVICE_S3_INC_86C775_86C785_TRIO_64V2_DX, S3_TRIO64V}, + {DEVICE_S3_INC_TRIO_64V_FAMILY, S3_TRIO64V}, + {DEVICE_S3_INC_TRIO_64V_FAMILY2, S3_TRIO64V}, + {DEVICE_S3_INC_TRIO_64V_FAMILY3, S3_TRIO64V}, + {DEVICE_S3_INC_TRIO_64V_FAMILY4, S3_TRIO64V}, + {DEVICE_S3_INC_TRIO_64V_FAMILY5, S3_TRIO64V}, + {DEVICE_S3_INC_TRIO_64V_FAMILY6, S3_TRIO64V}, + {DEVICE_S3_INC_TRIO_64V_FAMILY7, S3_TRIO64V}, + {DEVICE_S3_INC_TRIO_64V_FAMILY8, S3_TRIO64V}, + {DEVICE_S3_INC_TRIO_64V_FAMILY9, S3_TRIO64V}, + {DEVICE_S3_INC_TRIO_64V_FAMILY10, S3_TRIO64V}, + {DEVICE_S3_INC_TRIO_64V_FAMILY11, S3_TRIO64V}, + /* Virge */ + {DEVICE_S3_INC_86C325_VIRGE, S3_VIRGE}, + {DEVICE_S3_INC_86C988_VIRGE_VX, S3_VIRGE}, + {DEVICE_S3_INC_VIRGE_DX_OR_GX, S3_VIRGE}, + {DEVICE_S3_INC_VIRGE_GX2, S3_VIRGE}, + {DEVICE_S3_INC_VIRGE_M3, S3_VIRGE}, + {DEVICE_S3_INC_VIRGE_MX, S3_VIRGE}, + {DEVICE_S3_INC_VIRGE_MX2, S3_VIRGE}, + {DEVICE_S3_INC_VIRGE_MX_MV, S3_VIRGE}, + /* Savage3D */ + {DEVICE_S3_INC_86C794_SAVAGE_3D, S3_SAVAGE3D}, + {DEVICE_S3_INC_86C390_SAVAGE_3D_MV, S3_SAVAGE3D}, + /* Savage4 */ + {DEVICE_S3_INC_SAVAGE_4, S3_SAVAGE4}, + {DEVICE_S3_INC_SAVAGE_42, S3_SAVAGE4}, + /* SavageMX */ + {DEVICE_S3_INC_86C270_294_SAVAGE_MX_MV, S3_SAVAGE_MX}, + {DEVICE_S3_INC_82C270_294_SAVAGE_MX, S3_SAVAGE_MX}, + {DEVICE_S3_INC_86C270_294_SAVAGE_IX_MV, S3_SAVAGE_MX}, + /* SuperSavage */ + {DEVICE_S3_INC_SUPERSAVAGE_MX_128, S3_SUPERSAVAGE}, + {DEVICE_S3_INC_SUPERSAVAGE_MX_64, S3_SUPERSAVAGE}, + {DEVICE_S3_INC_SUPERSAVAGE_MX_64C, S3_SUPERSAVAGE}, + {DEVICE_S3_INC_SUPERSAVAGE_IX_128_SDR, S3_SUPERSAVAGE}, + {DEVICE_S3_INC_SUPERSAVAGE_IX_128_DDR, S3_SUPERSAVAGE}, + {DEVICE_S3_INC_SUPERSAVAGE_IX_64_SDR, S3_SUPERSAVAGE}, + {DEVICE_S3_INC_SUPERSAVAGE_IX_64_DDR, S3_SUPERSAVAGE}, + {DEVICE_S3_INC_SUPERSAVAGE_IX_C_SDR, S3_SUPERSAVAGE}, + {DEVICE_S3_INC_SUPERSAVAGE_IX_C_DDR, S3_SUPERSAVAGE}, + /* ProSavage */ + {DEVICE_S3_INC_PROSAVAGE_PM133, S3_PROSAVAGE}, + {DEVICE_S3_INC_PROSAVAGE_KM133, S3_PROSAVAGE}, + {DEVICE_S3_INC_86C380_PROSAVAGEDDR_K4M266, S3_PROSAVAGE}, + {DEVICE_S3_INC_VT8636A_PROSAVAGE_KN133, S3_PROSAVAGE}, + {DEVICE_S3_INC_VT8751_PROSAVAGEDDR_P4M266, S3_PROSAVAGE}, + {DEVICE_S3_INC_VT8375_PROSAVAGE8_KM266_KL266, S3_PROSAVAGE}, + /* Savage2000 */ + {DEVICE_S3_INC_86C410_SAVAGE_2000, S3_SAVAGE2000} +}; + +static unsigned int GetBlendForFourCC (int id) +{ + switch (id) + { + case IMGFMT_UYVY: + return 0; + case IMGFMT_YUY2: + return 1; + case IMGFMT_Y211: + return 4; + case IMGFMT_BGR15: + return 3; + case IMGFMT_BGR16: + return 5; + case IMGFMT_BGR24: + return 6; + case IMGFMT_BGR32: + return 7; + default: + return 1; + } +} + +static void S3SetColorOld (void) +{ + char sat = (info->eq.saturation + 1000) * 15 / 2000; + double hue = info->eq.hue * 3.1415926 / 1000.0; + char hsx = ((char) (sat * cos (hue))) & 0x1f; + char hsy = ((char) (sat * sin (hue))) & 0x1f; + + OUTREG (COLOR_ADJUSTMENT_REG, 0x80008000 | hsy << 24 | hsx << 16 | + ((info->eq.contrast + 1000) * 31 / 2000) << 8 | + (info->eq.brightness + 1000) * 255 / 2000); +} + +static void S3SetColorNew (void) +{ + /* not yet */ +} + +static void S3SetColor2000 (void) +{ + /* not yet */ +} + +static void S3SetColorKeyOld (void) +{ + 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) + { + 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 S3SetColorKeyNew (void) +{ + /* not yet */ +} + +static void S3SetColorKey2000 (void) +{ + /* not yet */ +} + +static void S3DisplayVideoOld (void) +{ + unsigned int ssControl; + int cr92; + + /* Set surface location and stride */ + OUTREG (SSTREAM_FBADDR0_REG, info->picture_offset); + OUTREG (SSTREAM_FBADDR1_REG, 0); + OUTREG (SSTREAM_STRIDE_REG, info->pitch); + /* Set window parameters */ + OUTREG (SSTREAM_WINDOW_START_REG, OS_XY (info->wx, info->wy)); + OUTREG (SSTREAM_WINDOW_SIZE_REG, OS_WH (info->drw_w, info->drw_h)); + + /* Set surface format and adjust scaling */ + if (info->chip.arch <= S3_VIRGE) + { + ssControl = ((info->src_w - 1) << 1) - ((info->drw_w - 1) & 0xffff); + ssControl |= GetBlendForFourCC (info->format) << 24; + if (info->src_w != info->drw_w) + ssControl |= 2 << 28; + + OUTREG (SSTREAM_CONTROL_REG, ssControl); + OUTREG (SSTREAM_STRETCH_REG, (((info->src_w - info->drw_w) & 0x7ff) << 16) | (info->src_w - 1)); + /* Calculate vertical scale factor */ + OUTREG (K1_VSCALE_REG, info->src_h - 1); + OUTREG (K2_VSCALE_REG, (info->src_h - info->drw_h) & 0x7ff); + OUTREG (DDA_VERT_REG, (1 - info->drw_h) & 0xfff); + } + else + { + ssControl = GetBlendForFourCC (info->format) << 24 | info->src_w; + 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; + } + + OUTREG (SSTREAM_CONTROL_REG, ssControl); + OUTREG (SSTREAM_STRETCH_REG, (info->src_w << 15) / info->drw_w); + OUTREG (SSTREAM_LINES_REG, info->src_h); + /* Calculate vertical scale factor. */ + OUTREG (SSTREAM_VSCALE_REG, VSCALING (info->src_h, info->drw_h)); + } + + if (info->chip.arch == S3_TRIO64V) + OUTREG (STREAMS_FIFO_REG, (6 << 10) | (14 << 5) | 16); + else + { + // 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); + } +} + +static void S3DisplayVideoNew (void) +{ + /* not yet */ +} + +static void S3DisplayVideo2000 (void) +{ + /* not yet */ +} + +static void S3InitStreamsOld (void) +{ + /*unsigned long jDelta; */ + unsigned long format = 0; + + /*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 (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); +} + +static void S3InitStreamsNew (void) +{ + /* not yet */ +} + +static void S3InitStreams2000 (void) +{ + /* not yet */ +} + +static void S3StreamsOn (void) +{ + unsigned char jStreamsControl; + + VGAOUT8 (vgaCRIndex, EXT_MISC_CTRL2); + + if (S3_SAVAGE_MOBILE_SERIES (info->chip.arch)) + { + jStreamsControl = VGAIN8 (vgaCRReg) | ENABLE_STREAM1; + VerticalRetraceWait (); + VGAOUT16 (vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2); + + S3InitStreams = S3InitStreamsNew; + S3SetColor = S3SetColorNew; + S3SetColorKey = S3SetColorKeyNew; + S3DisplayVideo = S3DisplayVideoNew; + } + else if (info->chip.arch == S3_SAVAGE2000) + { + jStreamsControl = VGAIN8 (vgaCRReg) | ENABLE_STREAM1; + VerticalRetraceWait (); + VGAOUT16 (vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2); + + S3InitStreams = S3InitStreams2000; + S3SetColor = S3SetColor2000; + S3SetColorKey = S3SetColorKey2000; + S3DisplayVideo = S3DisplayVideo2000; + } + else + { + jStreamsControl = VGAIN8 (vgaCRReg) | ENABLE_STREAMS_OLD; + VerticalRetraceWait (); + VGAOUT16 (vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2); + + S3InitStreams = S3InitStreamsOld; + S3SetColor = S3SetColorOld; + S3SetColorKey = S3SetColorKeyOld; + S3DisplayVideo = S3DisplayVideoOld; + } + + S3InitStreams (); + + VerticalRetraceWait (); + /* Turn on secondary stream TV flicker filter, once we support TV. */ + /* SR70 |= 0x10 */ +} + +static void S3GetScrProp (struct s3_info *info) +{ + unsigned char bpp = 0; + + VGAOUT8 (vgaCRIndex, EXT_MISC_CTRL2); + 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; + VGAOUT8 (vgaCRIndex, 0x12); + info->screen_y = VGAIN8 (vgaCRReg); + VGAOUT8 (vgaCRIndex, 0x07); + info->screen_y |= (VGAIN8 (vgaCRReg) & 0x02) << 7; + info->screen_y |= (VGAIN8 (vgaCRReg) & 0x40) << 3; + ++info->screen_y; + + printf ("[s3_vid] x = %d, y = %d, bpp = %d\n", info->screen_x, info->screen_y, info->bpp); +} + +static void S3StreamsOff (void) +{ + unsigned char jStreamsControl; + + if (info->chip.arch == S3_TRIO64V) + OUTREG (STREAMS_FIFO_REG, (20 << 10)); + + 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 + jStreamsControl = VGAIN8 (vgaCRReg) & NO_STREAMS_OLD; + + VerticalRetraceWait (); + VGAOUT16 (vgaCRIndex, (jStreamsControl << 8) | EXT_MISC_CTRL2); + + if (S3_SAVAGE_SERIES (info->chip.arch)) + { + VGAOUT16 (vgaCRIndex, 0x0093); + VGAOUT8 (vgaCRIndex, 0x92); + VGAOUT8 (vgaCRReg, VGAIN8 (vgaCRReg) & 0x40); + } +} + +static int find_chip (unsigned chip_id) +{ + unsigned i; + + for (i = 0; i < sizeof (s3_card_ids) / sizeof (struct s3_cards); i++) + if (chip_id == s3_card_ids[i].chip_id) + return i; + return -1; +} + +static int s3_probe (int verbose, int force) +{ + pciinfo_t lst[MAX_PCI_DEVICES]; + unsigned i, num_pci; + int err; + + if (force) + printf ("[s3_vid] Warning: forcing not supported yet!\n"); + err = pci_scan (lst, &num_pci); + if (err) + { + printf ("[s3_vid] Error occurred during pci scan: %s\n", strerror (err)); + return err; + } + else + { + err = ENXIO; + for (i = 0; i < num_pci; i++) + { + if (lst[i].vendor == VENDOR_S3_INC) + { + int idx; + const char *dname; + idx = find_chip (lst[i].device); + if (idx == -1) + continue; + dname = pci_device_name (lst[i].vendor, lst[i].device); + dname = dname ? dname : "Unknown chip"; + printf ("[s3_vid] Found chip: %s\n", dname); + // FIXME: whats wrong here? + if ((lst[i].command & PCI_COMMAND_IO) == 0) + { + printf ("[s3_vid] Device is disabled, ignoring\n"); + continue; + } + s3_cap.device_id = lst[i].device; + err = 0; + memcpy (&pci_info, &lst[i], sizeof (pciinfo_t)); + break; + } + } + } + if (err && verbose) + printf ("[s3_vid] Can't find chip\n"); + return err; +} + +static int s3_init (const char *args __attribute__ ((unused))) +{ + unsigned char cr36; + int mtrr, videoRam; + static unsigned char RamTrioVirge[] = { 4, 0, 3, 8, 2, 6, 1, 0 }; + static unsigned char RamSavage3D[] = { 8, 4, 4, 2 }; + static unsigned char RamSavage4[] = { 2, 4, 8, 12, 16, 32, 64, 32 }; + static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 }; + static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 16, 2 }; + + enable_app_io (); + + info = calloc (1, sizeof (s3_info)); + + info->chip.arch = s3_card_ids[find_chip (pci_info.device)].arch; + + /* Switch to vga registers */ + OUTPORT8 (0x3c3, INPORT8 (0x3c3) | 0x01); + OUTPORT8 (0x3c2, INPORT8 (0x3cc) | 0x01); + /* Unlock extended registers */ + OUTPORT8 (vgaCRIndex, 0x38); + OUTPORT8 (vgaCRReg, 0x48); + OUTPORT8 (vgaCRIndex, 0x39); + OUTPORT8 (vgaCRReg, 0xa0); + + if (info->chip.arch <= S3_VIRGE) + { + /* TODO: Improve detecting code */ + + /* Enable LFB */ + OUTPORT8 (vgaCRIndex, LIN_ADDR_CTRL); + OUTPORT8 (vgaCRReg, INPORT8 (vgaCRReg) | ENABLE_LFB); + /* Enable NewMMIO */ + OUTPORT8 (vgaCRIndex, EXT_MEM_CTRL1); + OUTPORT8 (vgaCRReg, INPORT8 (vgaCRReg) | ENABLE_NEWMMIO); + } + + if (info->chip.arch < S3_SAVAGE3D) + info->control_base = map_phys_mem (pci_info.base0 + S3_NEWMMIO_REGBASE, S3_NEWMMIO_REGSIZE); + else if (info->chip.arch == S3_SAVAGE3D) + info->control_base = map_phys_mem (pci_info.base0 + S3_NEWMMIO_REGBASE, S3_NEWMMIO_REGSIZE_SAVAGE); + else + info->control_base = map_phys_mem (pci_info.base0, S3_NEWMMIO_REGSIZE_SAVAGE); + + /* Unlock CRTC[0-7] */ + VGAOUT8 (vgaCRIndex, 0x11); + VGAOUT8 (vgaCRReg, VGAIN8 (vgaCRReg) & 0x7f); + /* Unlock sequencer */ + VGAOUT16 (0x3c4, 0x0608); + /* Detect amount of installed ram */ + VGAOUT8 (vgaCRIndex, 0x36); + cr36 = VGAIN8 (vgaCRReg); + + switch (info->chip.arch) + { + case S3_TRIO64V: + case S3_VIRGE: + videoRam = RamTrioVirge[(cr36 & 0xE0) >> 5] * 1024; + break; + + case S3_SAVAGE3D: + videoRam = RamSavage3D[(cr36 & 0xC0) >> 6] * 1024; + break; + + case S3_SAVAGE4: + /* + * The Savage4 has one ugly special case to consider. On + * systems with 4 banks of 2Mx32 SDRAM, the BIOS says 4MB + * when it really means 8MB. Why do it the same when you + * can do it different... + */ + VGAOUT8 (vgaCRIndex, 0x68); + if ((VGAIN8 (vgaCRReg) & 0xC0) == (0x01 << 6)) + RamSavage4[1] = 8; + + case S3_SAVAGE2000: + videoRam = RamSavage4[(cr36 & 0xE0) >> 5] * 1024; + break; + + case S3_SAVAGE_MX: + videoRam = RamSavageMX[(cr36 & 0x0E) >> 1] * 1024; + break; + + case S3_PROSAVAGE: + videoRam = RamSavageNB[(cr36 & 0xE0) >> 5] * 1024; + break; + + default: + /* How did we get here? */ + videoRam = 0; + break; + } + + printf ("[s3_vid] VideoRam = %d\n", videoRam); + info->chip.fbsize = videoRam * 1024; + + if (info->chip.arch <= S3_SAVAGE3D) + mtrr = mtrr_set_type (pci_info.base0, info->chip.fbsize, MTRR_TYPE_WRCOMB); + else + mtrr = mtrr_set_type (pci_info.base1, info->chip.fbsize, MTRR_TYPE_WRCOMB); + + if (mtrr != 0) + printf ("[s3_vid] Unable to setup MTRR: %s\n", strerror (mtrr)); + else + printf ("[s3_vid] MTRR set up\n"); + + S3GetScrProp (info); + S3StreamsOn (); + + return 0; +} + +static void s3_destroy (void) +{ + unmap_phys_mem (info->video_base, info->chip.fbsize); + if (S3_SAVAGE_SERIES (info->chip.arch)) + unmap_phys_mem (info->control_base, S3_NEWMMIO_REGSIZE_SAVAGE); + else + unmap_phys_mem (info->control_base, S3_NEWMMIO_REGSIZE); + + free (info); +} + +static int s3_get_caps (vidix_capability_t * to) +{ + memcpy (to, &s3_cap, sizeof (vidix_capability_t)); + return 0; +} + +static int is_supported_fourcc (uint32_t fourcc) +{ + switch (fourcc) + { +//FIXME: Burst Command Interface should be used +// for planar to packed conversion +// case IMGFMT_YV12: +// case IMGFMT_I420: + case IMGFMT_UYVY: + case IMGFMT_YUY2: + case IMGFMT_Y211: + case IMGFMT_BGR15: + case IMGFMT_BGR16: + case IMGFMT_BGR24: + case IMGFMT_BGR32: + return 1; + default: + return 0; + } +} + +static int s3_query_fourcc (vidix_fourcc_t * to) +{ + if (is_supported_fourcc (to->fourcc)) + { + to->depth = VID_DEPTH_ALL; + to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY; + return 0; + } + else + to->depth = to->flags = 0; + + return ENOSYS; +} + +#if 0 +static int s3_get_gkeys (vidix_grkey_t * grkey) +{ + return 0; +} +#endif + +static int s3_set_gkeys (const vidix_grkey_t * grkey) +{ + if (grkey->ckey.op == CKEY_FALSE) + { + info->use_colorkey = 0; + info->vidixcolorkey = 0; + printf ("[s3_vid] Colorkeying disabled\n"); + } + else + { + info->use_colorkey = 1; + info->vidixcolorkey = ((grkey->ckey.red << 16) | (grkey->ckey.green << 8) | grkey->ckey.blue); + printf ("[s3_vid] Set colorkey 0x%x\n", info->vidixcolorkey); + } + if (S3SetColorKey) + S3SetColorKey (); + return 0; +} + +static int s3_get_eq (vidix_video_eq_t * eq) +{ + memcpy (eq, &(info->eq), sizeof (vidix_video_eq_t)); + return 0; +} + +static int s3_set_eq (const vidix_video_eq_t * eq) +{ + if (eq->cap & VEQ_CAP_BRIGHTNESS) + info->eq.brightness = eq->brightness; + if (eq->cap & VEQ_CAP_CONTRAST) + info->eq.contrast = eq->contrast; + if (eq->cap & VEQ_CAP_SATURATION) + info->eq.saturation = eq->saturation; + if (eq->cap & VEQ_CAP_HUE) + info->eq.hue = eq->hue; + if (S3SetColor) + S3SetColor (); + return 0; +} + +static int s3_config_playback (vidix_playback_t * vinfo) +{ + unsigned int i, bpp; + + if (!is_supported_fourcc (vinfo->fourcc)) + return -1; + + info->src_w = vinfo->src.w; + info->src_h = vinfo->src.h; + + info->drw_w = vinfo->dest.w; + info->drw_h = vinfo->dest.h; + + info->wx = vinfo->dest.x; + info->wy = vinfo->dest.y; + info->format = vinfo->fourcc; + + info->eq.cap = VEQ_CAP_BRIGHTNESS | VEQ_CAP_CONTRAST | + VEQ_CAP_SATURATION | VEQ_CAP_HUE; + info->eq.brightness = 0; + info->eq.contrast = 0; + info->eq.saturation = 0; + info->eq.hue = 0; + + vinfo->offset.y = 0; + vinfo->offset.v = 0; + vinfo->offset.u = 0; + + vinfo->dest.pitch.y = 32; + vinfo->dest.pitch.u = 32; + vinfo->dest.pitch.v = 32; + + switch (vinfo->fourcc) + { + case IMGFMT_Y211: + bpp = 1; + break; + case IMGFMT_BGR24: + bpp = 3; + break; + case IMGFMT_BGR32: + bpp = 4; + break; + default: + bpp = 2; + break; + } + + info->pitch = ((info->src_w * bpp) + 15) & ~15; + info->pitch |= ((info->pitch / bpp) << 16); + + vinfo->frame_size = (info->pitch & 0xffff) * info->src_h; + info->frame_size = vinfo->frame_size; + + info->picture_offset = info->screen_x * info->screen_y * (info->bpp >> 3); + if (info->picture_offset > (info->chip.fbsize - vinfo->frame_size)) + { + printf ("[s3_vid] Not enough memory for overlay\n"); + return -1; + } + + if (info->chip.arch <= S3_SAVAGE3D) + info->video_base = map_phys_mem (pci_info.base0, info->chip.fbsize); + else + info->video_base = map_phys_mem (pci_info.base1, info->chip.fbsize); + + if (info->video_base == NULL) + { + printf ("[s3_vid] errno = %s\n", strerror (errno)); + return -1; + } + + info->picture_base = (uint32_t) info->video_base + info->picture_offset; + + vinfo->dga_addr = (void *) (info->picture_base); + + vinfo->num_frames = (info->chip.fbsize - info->picture_offset) / vinfo->frame_size; + if (vinfo->num_frames > VID_PLAY_MAXFRAMES) + vinfo->num_frames = VID_PLAY_MAXFRAMES; + + for (i = 0; i < vinfo->num_frames; i++) + vinfo->offsets[i] = vinfo->frame_size * i; + + return 0; +} + +static int s3_playback_on (void) +{ + S3DisplayVideo (); + return 0; +} + +static int s3_playback_off (void) +{ + S3StreamsOff (); + return 0; +} + +static int s3_frame_sel (unsigned int frame) +{ + OUTREG (SSTREAM_FBADDR0_REG, info->picture_offset + (info->frame_size * frame)); + return 0; +} + +VDXDriver s3_drv = { + "s3", + NULL, + .probe = s3_probe, + .get_caps = s3_get_caps, + .query_fourcc = s3_query_fourcc, + .init = s3_init, + .destroy = s3_destroy, + .config_playback = s3_config_playback, + .playback_on = s3_playback_on, + .playback_off = s3_playback_off, + .frame_sel = s3_frame_sel, + .get_eq = s3_get_eq, + .set_eq = s3_set_eq, + .set_gkey = s3_set_gkeys, +};