sis_vid.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,514 行 · 第 1/3 页

C
1,514
字号
/* * VIDIX driver for SiS chipsets. * Copyright (C) 2003 Jake Page, Sugar Media. * * 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 * * Based on SiS Xv driver * Copyright 2002-2003 by Thomas Winischhofer, Vienna, Austria. * 2003/10/08 integrated into mplayer/vidix architecture -- Alex Beregszaszi */#include <errno.h>#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <inttypes.h>#include <mplaylib.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 "sis_regs.h"#include "sis_defs.h"#undef memcpy#define memcpy uc_memcpy/** Random defines **/#define WATCHDOG_DELAY  500000	/* Watchdog counter for retrace waiting */#define IMAGE_MIN_WIDTH         32	/* Min and max source image sizes */#define IMAGE_MIN_HEIGHT        24#define IMAGE_MAX_WIDTH        720#define IMAGE_MAX_HEIGHT       576#define IMAGE_MAX_WIDTH_M650  1920#define IMAGE_MAX_HEIGHT_M650 1080#define OVERLAY_MIN_WIDTH       32	/* Minimum overlay sizes */#define OVERLAY_MIN_HEIGHT      24#define DISPMODE_SINGLE1 0x1	/* TW: CRT1 only */#define DISPMODE_SINGLE2 0x2	/* TW: CRT2 only */#define DISPMODE_MIRROR  0x4	/* TW: CRT1 + CRT2 MIRROR */#define VMODE_INTERLACED       0x1#define VMODE_DOUBLESCAN       0x2typedef struct {    short x1, y1, x2, y2;} BoxRec;typedef struct {    int pixelFormat;    uint16_t pitch;    uint16_t origPitch;    uint8_t keyOP;    uint16_t HUSF;    uint16_t VUSF;    uint8_t IntBit;    uint8_t wHPre;    uint16_t srcW;    uint16_t srcH;    BoxRec dstBox;    uint32_t PSY;    uint32_t PSV;    uint32_t PSU;    uint8_t bobEnable;    uint8_t contrastCtrl;    uint8_t contrastFactor;    uint8_t lineBufSize;     uint8_t(*VBlankActiveFunc) ();    uint16_t SCREENheight;} SISOverlayRec, *SISOverlayPtr;/** static variable definitions **/static int sis_probed = 0;static pciinfo_t pci_info;unsigned int sis_verbose = 0;static void *sis_mem_base;/* static void *sis_reg_base; */unsigned short sis_iobase;unsigned int sis_vga_engine = UNKNOWN_VGA;static unsigned int sis_displaymode = DISPMODE_SINGLE1;static unsigned int sis_has_two_overlays = 0;static unsigned int sis_bridge_is_slave = 0;static unsigned int sis_shift_value = 1;static unsigned int sis_vmode = 0;unsigned int sis_vbflags = DISPTYPE_DISP1;unsigned int sis_overlay_on_crt1 = 1;int sis_crt1_off = -1;unsigned int sis_detected_crt2_devices;unsigned int sis_force_crt2_type = CRT2_DEFAULT;int sis_device_id = -1;static int sis_format;static int sis_Yoff = 0;static int sis_Voff = 0;static int sis_Uoff = 0;static int sis_screen_width = 640;static int sis_screen_height = 480;static int sis_frames[VID_PLAY_MAXFRAMES];static vidix_grkey_t sis_grkey;static vidix_capability_t sis_cap = {    "SiS 300/310/325 Video Driver",    "Jake Page",    TYPE_OUTPUT,    {0, 0, 0, 0},    2048,    2048,    4,    4,    -1,    FLAG_UPSCALER | FLAG_DOWNSCALER | FLAG_EQUALIZER,    VENDOR_SIS,    -1,    {0, 0, 0, 0}};static vidix_video_eq_t sis_equal = {    VEQ_CAP_BRIGHTNESS | VEQ_CAP_CONTRAST,    200, 0, 0, 0, 0, 0, 0, 0};static unsigned short sis_card_ids[] = {    DEVICE_SIS_300,    DEVICE_SIS_315H,    DEVICE_SIS_315,    DEVICE_SIS_315PRO,    DEVICE_SIS_330,    DEVICE_SIS_540_VGA,    DEVICE_SIS_550_VGA,    DEVICE_SIS_630_VGA,    DEVICE_SIS_650_VGA};/** function declarations **/extern void sis_init_video_bridge(void);static void set_overlay(SISOverlayPtr pOverlay, int index);static void close_overlay(void);static void calc_scale_factor(SISOverlayPtr pOverlay,			      int index, int iscrt2);static void set_line_buf_size(SISOverlayPtr pOverlay);static void merge_line_buf(int enable);static void set_format(SISOverlayPtr pOverlay);static void set_colorkey(void);static void set_brightness(uint8_t brightness);static void set_contrast(uint8_t contrast);static void set_saturation(char saturation);static void set_hue(uint8_t hue);/* IO Port access functions */static uint8_t getvideoreg(uint8_t reg){    uint8_t ret;    inSISIDXREG(SISVID, reg, ret);    return (ret);}static void setvideoreg(uint8_t reg, uint8_t data){    outSISIDXREG(SISVID, reg, data);}static void setvideoregmask(uint8_t reg, uint8_t data, uint8_t mask){    uint8_t old;    inSISIDXREG(SISVID, reg, old);    data = (data & mask) | (old & (~mask));    outSISIDXREG(SISVID, reg, data);}static void setsrregmask(uint8_t reg, uint8_t data, uint8_t mask){    uint8_t old;    inSISIDXREG(SISSR, reg, old);    data = (data & mask) | (old & (~mask));    outSISIDXREG(SISSR, reg, data);}/* vblank checking*/static uint8_t vblank_active_CRT1(void){    /* this may be too simplistic? */    return (inSISREG(SISINPSTAT) & 0x08);}static uint8_t vblank_active_CRT2(void){    uint8_t ret;    if (sis_vga_engine == SIS_315_VGA) {	inSISIDXREG(SISPART1, Index_310_CRT2_FC_VR, ret);    } else {	inSISIDXREG(SISPART1, Index_CRT2_FC_VR, ret);    }    return ((ret & 0x02) ^ 0x02);}static int find_chip(unsigned chip_id){    unsigned i;    for (i = 0; i < sizeof(sis_card_ids) / sizeof(unsigned short); i++) {	if (chip_id == sis_card_ids[i])	    return i;    }    return -1;}static int sis_probe(int verbose, int force){    pciinfo_t lst[MAX_PCI_DEVICES];    unsigned i, num_pci;    int err;    sis_verbose = verbose;    force = force;    err = pci_scan(lst, &num_pci);    if (err) {	printf("[SiS] 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_SIS) {		int idx;		const char *dname;		idx = find_chip(lst[i].device);		if (idx == -1)		    continue;		dname = pci_device_name(VENDOR_SIS, lst[i].device);		dname = dname ? dname : "Unknown chip";		if (sis_verbose > 0)		    printf("[SiS] Found chip: %s (0x%X)\n",			   dname, lst[i].device);		sis_device_id = sis_cap.device_id = lst[i].device;		err = 0;		memcpy(&pci_info, &lst[i], sizeof(pciinfo_t));		sis_has_two_overlays = 0;		switch (sis_cap.device_id) {		case DEVICE_SIS_300:		case DEVICE_SIS_630_VGA:		    sis_has_two_overlays = 1;		case DEVICE_SIS_540_VGA:		    sis_vga_engine = SIS_300_VGA;		    break;		case DEVICE_SIS_330:		case DEVICE_SIS_550_VGA:		    sis_has_two_overlays = 1;		case DEVICE_SIS_315H:		case DEVICE_SIS_315:		case DEVICE_SIS_315PRO:		case DEVICE_SIS_650_VGA:		    /* M650 & 651 have 2 overlays */		    /* JCP: I think this works, but not really tested yet */		    if (enable_app_io() == 0 )		    {			unsigned char CR5F;			unsigned char tempreg1, tempreg2;			inSISIDXREG(SISCR, 0x5F, CR5F);			CR5F &= 0xf0;			andSISIDXREG(SISCR, 0x5c, 0x07);			inSISIDXREG(SISCR, 0x5c, tempreg1);			tempreg1 &= 0xf8;			setSISIDXREG(SISCR, 0x5c, 0x07, 0xf8);			inSISIDXREG(SISCR, 0x5c, tempreg2);			tempreg2 &= 0xf8;			if ((!tempreg1) || (tempreg2)) {			    if (CR5F & 0x80) {				sis_has_two_overlays = 1;			    }			} else {			    sis_has_two_overlays = 1;	/* ? */			}			if (sis_has_two_overlays) {			    if (sis_verbose > 0)				printf				    ("[SiS] detected M650/651 with 2 overlays\n");			}			disable_app_io();		    }		    sis_vga_engine = SIS_315_VGA;		    break;		default:		    /* should never get here */		    sis_vga_engine = UNKNOWN_VGA;		    break;		}	    }	}    }    if (err && sis_verbose) {	printf("[SiS] Can't find chip\n");    } else {	sis_probed = 1;    }    return err;}static int sis_init(void){    uint8_t sr_data, cr_data, cr_data2;    char *env_overlay_crt;    if (!sis_probed) {	printf("[SiS] driver was not probed but is being initialized\n");	return (EINTR);    }    if (enable_app_io() != 0)    {      printf("[SiS] can't enable register I/O\n");      return(EINTR);    }    /* JCP: this is WRONG.  Need to coordinate w/ sisfb to use correct mem */    /* map 16MB scary hack for now. */    sis_mem_base = map_phys_mem(pci_info.base0, 0x1000000);    /* sis_reg_base = map_phys_mem(pci_info.base1, 0x20000); */    sis_iobase = pci_info.base2 & 0xFFFC;    /* would like to use fb ioctl  - or some other method - here to get       current resolution. */    inSISIDXREG(SISCR, 0x12, cr_data);    inSISIDXREG(SISCR, 0x07, cr_data2);    sis_screen_height =	((cr_data & 0xff) | ((uint16_t) (cr_data2 & 0x02) << 7) |	 ((uint16_t) (cr_data2 & 0x40) << 3) | ((uint16_t) (cr_data & 0x02)						<< 9)) + 1;    inSISIDXREG(SISSR, 0x0b, sr_data);    inSISIDXREG(SISCR, 0x01, cr_data);    sis_screen_width = (((cr_data & 0xff) |			 ((uint16_t) (sr_data & 0x0C) << 6)) + 1) * 8;    inSISIDXREG(SISSR, Index_SR_Graphic_Mode, sr_data);    if (sr_data & 0x20)		/* interlaced mode */	sis_vmode |= VMODE_INTERLACED;    /* JCP: eventually I'd like to replace this with a call to sisfb       SISFB_GET_INFO ioctl to get video bridge info.  Not for now,       since it requires a very new and not widely distributed version. */    sis_init_video_bridge();    env_overlay_crt = getenv("VIDIX_CRT");    if (env_overlay_crt) {	int crt = atoi(env_overlay_crt);	if (crt == 1 || crt == 2) {	    sis_overlay_on_crt1 = (crt == 1);	    if (sis_verbose > 0) {		printf		    ("[SiS] override: using overlay on CRT%d from VIDIX_CRT\n",		     crt);	    }	}    }    return 0;}static void sis_destroy(void){    /* unmap_phys_mem(sis_reg_base, 0x20000); */    /* JCP: see above, hence also a hack. */    unmap_phys_mem(sis_mem_base, 0x1000000);    disable_app_io();}static int sis_get_caps(vidix_capability_t * to){    memcpy(to, &sis_cap, sizeof(vidix_capability_t));    return 0;}static int is_supported_fourcc(uint32_t fourcc){    switch (fourcc) {    case IMGFMT_YV12:    case IMGFMT_I420:    case IMGFMT_UYVY:    case IMGFMT_YUY2:    case IMGFMT_RGB15:    case IMGFMT_RGB16:	return 1;    default:	return 0;    }}static int sis_query_fourcc(vidix_fourcc_t * to){    if (is_supported_fourcc(to->fourcc)) {	to->depth = VID_DEPTH_8BPP | VID_DEPTH_16BPP | VID_DEPTH_32BPP;	to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY;	return 0;    } else	to->depth = to->flags = 0;    return ENOSYS;}static int bridge_in_slave_mode(void){    unsigned char usScratchP1_00;    if (!(sis_vbflags & VB_VIDEOBRIDGE))	return 0;    inSISIDXREG(SISPART1, 0x00, usScratchP1_00);    if (((sis_vga_engine == SIS_300_VGA)	 && (usScratchP1_00 & 0xa0) == 0x20)	|| ((sis_vga_engine == SIS_315_VGA)	    && (usScratchP1_00 & 0x50) == 0x10)) {	return 1;    } else {	return 0;    }}/* This does not handle X dual head mode, since 1) vidix doesn't support it   and 2) it doesn't make sense for other gfx drivers */static void set_dispmode(void){    sis_bridge_is_slave = 0;    if (bridge_in_slave_mode())	sis_bridge_is_slave = 1;    if ((sis_vbflags & VB_DISPMODE_MIRROR) ||	(sis_bridge_is_slave && (sis_vbflags & DISPTYPE_DISP2))) {	if (sis_has_two_overlays)	    sis_displaymode = DISPMODE_MIRROR;	/* TW: CRT1+CRT2 (2 overlays) */	else if (!sis_overlay_on_crt1)	    sis_displaymode = DISPMODE_SINGLE2;	else	    sis_displaymode = DISPMODE_SINGLE1;    } else {	if (sis_vbflags & DISPTYPE_DISP1) {	    sis_displaymode = DISPMODE_SINGLE1;	/* TW: CRT1 only */	} else {	    sis_displaymode = DISPMODE_SINGLE2;	/* TW: CRT2 only */	}    }}static void set_disptype_regs(void){    switch (sis_displaymode) {    case DISPMODE_SINGLE1:	/* TW: CRT1 only */	if (sis_verbose > 2) {	    printf("[SiS] Setting up overlay on CRT1\n");	}	if (sis_has_two_overlays) {	    setsrregmask(0x06, 0x00, 0xc0);	    setsrregmask(0x32, 0x00, 0xc0);	} else {	    setsrregmask(0x06, 0x00, 0xc0);	    setsrregmask(0x32, 0x00, 0xc0);	}	break;    case DISPMODE_SINGLE2:	/* TW: CRT2 only */	if (sis_verbose > 2) {	    printf("[SiS] Setting up overlay on CRT2\n");	}	if (sis_has_two_overlays) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?