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 + -
显示快捷键?