diff --git a/configure b/configure index e0129dacba..e939efd63b 100755 --- a/configure +++ b/configure @@ -337,7 +337,7 @@ Video output: --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 @@ _def_vidix_drv_radeon='#undef CONFIG_VIDIX_DRV_RADEON' _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 @@ if test "$_vidix" = yes ; then _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_PM2=$_vidix_drv_pm2 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_nvidia $_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 diff --git a/vidix/Makefile b/vidix/Makefile index 258d0ebaa4..28ebefe898 100644 --- a/vidix/Makefile +++ b/vidix/Makefile @@ -20,7 +20,7 @@ SRCS_MPLAYER-$(VIDIX_PM2) += pm2_vid.c 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 diff --git a/vidix/drivers.c b/vidix/drivers.c index 65a09a65ac..c7f1f864bf 100644 --- a/vidix/drivers.c +++ b/vidix/drivers.c @@ -42,7 +42,7 @@ extern VDXDriver pm2_drv; 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 @@ void vidix_register_all_drivers (void) #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); diff --git a/vidix/s3_regs.h b/vidix/s3_regs.h new file mode 100644 index 0000000000..7ba0e212b5 --- /dev/null +++ b/vidix/s3_regs.h @@ -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 */ diff --git a/vidix/s3_vid.c b/vidix/s3_vid.c new file mode 100644 index 0000000000..849c28e0bb --- /dev/null +++ b/vidix/s3_vid.c @@ -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 +#include +#include +#include +#include +#include +#include + +#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, +};