📄 mga_vid.c
字号:
/* * Matrox MGA driver * * ported to VIDIX by Alex Beregszaszi * * YUY2 support (see config.format) added by A'rpi/ESP-team * double buffering added by A'rpi/ESP-team * * Brightness/contrast support by Nick Kurshev/Dariush Pietrzak (eyck) and me * * Fixed Brightness/Contrast * Rewrite or read/write kabi@users.sf.net * * TODO: * * fix memory size detection (current reading pci userconfig isn't * working as requested - returns the max avail. ram on arch?) * * translate all non-english comments to english *//* * Original copyright: * * mga_vid.c * * Copyright (C) 1999 Aaron Holtzman * * Module skeleton based on gutted agpgart module by Jeff Hartmann * <slicer@ionet.net> * * Matrox MGA G200/G400 YUV Video Interface module Version 0.1.0 * * BES == Back End Scaler * * This software has been released under the terms of the GNU Public * license. See http://www.gnu.org/copyleft/gpl.html for details. *///#define CRTC2// Set this value, if autodetection fails! (video ram size in megabytes)//#define MGA_MEMORY_SIZE 16/* No irq support in userspace implemented yet, do not enable this! *//* disable irq */#undef MGA_ALLOW_IRQ#define MGA_VSYNC_POS 2#undef MGA_PCICONFIG_MEMDETECT#define MGA_DEFAULT_FRAMES 64#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include <inttypes.h>#include "../vidix.h"#include "../fourcc.h"#include "../../libdha/libdha.h"#include "../../libdha/pci_ids.h"#include "../../libdha/pci_names.h"#if !defined(ENOTSUP) && defined(EOPNOTSUPP)#define ENOTSUP EOPNOTSUPP#endif#ifdef CRTC2#define VIDIX_STATIC mga_crtc2_#else#define VIDIX_STATIC mga_#endif/* from radeon_vid */#define GETREG(TYPE,PTR,OFFZ) (*((volatile TYPE*)((PTR)+(OFFZ))))#define SETREG(TYPE,PTR,OFFZ,VAL) (*((volatile TYPE*)((PTR)+(OFFZ))))=VAL#define readb(addr) GETREG(uint8_t,(uint32_t)(mga_mmio_base + addr),0)#define writeb(addr, val) SETREG(uint8_t,(uint32_t)(mga_mmio_base + addr),0,val)#define readl(addr) GETREG(uint32_t,(uint32_t)(mga_mmio_base + addr),0)#define writel(addr, val) SETREG(uint32_t,(uint32_t)(mga_mmio_base + addr),0,val)static int mga_verbose = 0;/* for device detection */static int probed = 0;static pciinfo_t pci_info;/* internal booleans */static int mga_vid_in_use = 0;static int is_g400 = 0;static int vid_src_ready = 0;static int vid_overlay_on = 0;/* mapped physical addresses */static uint8_t *mga_mmio_base = 0;static uint8_t* mga_mem_base = 0;static int mga_src_base = 0; /* YUV buffer position in video memory */static uint32_t mga_ram_size = 0; /* how much megabytes videoram we have *//* Graphic keys */static vidix_grkey_t mga_grkey;static int colkey_saved = 0;static int colkey_on = 0;static unsigned char colkey_color[4];static unsigned char colkey_mask[4];/* for IRQ */static int mga_irq = -1;static int mga_next_frame = 0;static vidix_capability_t mga_cap ={ "Matrox MGA G200/G4x0/G5x0 YUV Video", "Aaron Holtzman, Arpad Gereoffy, Alex Beregszaszi, Nick Kurshev", TYPE_OUTPUT, { 0, 0, 0, 0 }, 2048, 2048, 4, 4, -1, FLAG_UPSCALER | FLAG_DOWNSCALER | FLAG_EQUALIZER, VENDOR_MATROX, -1, /* will be set in VIDIX_NAME(vixProbe) */ { 0, 0, 0, 0}};/* MATROX BES registers */typedef struct bes_registers_s{ //BES Control uint32_t besctl; //BES Global control uint32_t besglobctl; //Luma control (brightness and contrast) uint32_t beslumactl; //Line pitch uint32_t bespitch; //Buffer A-1 Chroma 3 plane org uint32_t besa1c3org; //Buffer A-1 Chroma org uint32_t besa1corg; //Buffer A-1 Luma org uint32_t besa1org; //Buffer A-2 Chroma 3 plane org uint32_t besa2c3org; //Buffer A-2 Chroma org uint32_t besa2corg; //Buffer A-2 Luma org uint32_t besa2org; //Buffer B-1 Chroma 3 plane org uint32_t besb1c3org; //Buffer B-1 Chroma org uint32_t besb1corg; //Buffer B-1 Luma org uint32_t besb1org; //Buffer B-2 Chroma 3 plane org uint32_t besb2c3org; //Buffer B-2 Chroma org uint32_t besb2corg; //Buffer B-2 Luma org uint32_t besb2org; //BES Horizontal coord uint32_t beshcoord; //BES Horizontal inverse scaling [5.14] uint32_t beshiscal; //BES Horizontal source start [10.14] (for scaling) uint32_t beshsrcst; //BES Horizontal source ending [10.14] (for scaling) uint32_t beshsrcend; //BES Horizontal source last uint32_t beshsrclst; //BES Vertical coord uint32_t besvcoord; //BES Vertical inverse scaling [5.14] uint32_t besviscal; //BES Field 1 vertical source last position uint32_t besv1srclst; //BES Field 1 weight start uint32_t besv1wght; //BES Field 2 vertical source last position uint32_t besv2srclst; //BES Field 2 weight start uint32_t besv2wght;} bes_registers_t;static bes_registers_t regs;#ifdef CRTC2typedef struct crtc2_registers_s{ uint32_t c2ctl; uint32_t c2datactl; uint32_t c2misc; uint32_t c2hparam; uint32_t c2hsync; uint32_t c2offset; uint32_t c2pl2startadd0; uint32_t c2pl2startadd1; uint32_t c2pl3startadd0; uint32_t c2pl3startadd1; uint32_t c2preload; uint32_t c2spicstartadd0; uint32_t c2spicstartadd1; uint32_t c2startadd0; uint32_t c2startadd1; uint32_t c2subpiclut; uint32_t c2vcount; uint32_t c2vparam; uint32_t c2vsync;} crtc2_registers_t;static crtc2_registers_t cregs;static crtc2_registers_t cregs_save;#endif//All register offsets are converted to word aligned offsets (32 bit)//because we want all our register accesses to be 32 bits#define VCOUNT 0x1e20#define PALWTADD 0x3c00 // Index register for X_DATAREG port#define X_DATAREG 0x3c0a#define XMULCTRL 0x19#define BPP_8 0x00#define BPP_15 0x01#define BPP_16 0x02#define BPP_24 0x03#define BPP_32_DIR 0x04#define BPP_32_PAL 0x07#define XCOLMSK 0x40#define X_COLKEY 0x42#define XKEYOPMODE 0x51#define XCOLMSK0RED 0x52#define XCOLMSK0GREEN 0x53#define XCOLMSK0BLUE 0x54#define XCOLKEY0RED 0x55#define XCOLKEY0GREEN 0x56#define XCOLKEY0BLUE 0x57#ifdef CRTC2/*CRTC2 registers*/#define XMISCCTRL 0x1e#define C2CTL 0x3c10#define C2DATACTL 0x3c4c#define C2MISC 0x3c44#define C2HPARAM 0x3c14#define C2HSYNC 0x3c18#define C2OFFSET 0x3c40#define C2PL2STARTADD0 0x3c30 // like BESA1CORG#define C2PL2STARTADD1 0x3c34 // like BESA2CORG#define C2PL3STARTADD0 0x3c38 // like BESA1C3ORG#define C2PL3STARTADD1 0x3c3c // like BESA2C3ORG#define C2PRELOAD 0x3c24#define C2SPICSTARTADD0 0x3c54#define C2SPICSTARTADD1 0x3c58#define C2STARTADD0 0x3c28 // like BESA1ORG#define C2STARTADD1 0x3c2c // like BESA2ORG#define C2SUBPICLUT 0x3c50#define C2VCOUNT 0x3c48#define C2VPARAM 0x3c1c#define C2VSYNC 0x3c20#endif /* CRTC2 */// Backend Scaler registers#define BESCTL 0x3d20#define BESGLOBCTL 0x3dc0#define BESLUMACTL 0x3d40#define BESPITCH 0x3d24#define BESA1C3ORG 0x3d60#define BESA1CORG 0x3d10#define BESA1ORG 0x3d00#define BESA2C3ORG 0x3d64#define BESA2CORG 0x3d14#define BESA2ORG 0x3d04#define BESB1C3ORG 0x3d68#define BESB1CORG 0x3d18#define BESB1ORG 0x3d08#define BESB2C3ORG 0x3d6C#define BESB2CORG 0x3d1C#define BESB2ORG 0x3d0C#define BESHCOORD 0x3d28#define BESHISCAL 0x3d30#define BESHSRCEND 0x3d3C#define BESHSRCLST 0x3d50#define BESHSRCST 0x3d38#define BESV1WGHT 0x3d48#define BESV2WGHT 0x3d4c#define BESV1SRCLST 0x3d54#define BESV2SRCLST 0x3d58#define BESVISCAL 0x3d34#define BESVCOORD 0x3d2c#define BESSTATUS 0x3dc4#define CRTCX 0x1fd4#define CRTCD 0x1fd5#define IEN 0x1e1c#define ICLEAR 0x1e18#define STATUS 0x1e14#define CRTCEXTX 0x1fde#define CRTCEXTD 0x1fdf#ifdef CRTC2static void crtc2_frame_sel(int frame){ switch(frame) { case 0: cregs.c2pl2startadd0=regs.besa1corg; cregs.c2pl3startadd0=regs.besa1c3org; cregs.c2startadd0=regs.besa1org; break; case 1: cregs.c2pl2startadd0=regs.besa2corg; cregs.c2pl3startadd0=regs.besa2c3org; cregs.c2startadd0=regs.besa2org; break; case 2: cregs.c2pl2startadd0=regs.besb1corg; cregs.c2pl3startadd0=regs.besb1c3org; cregs.c2startadd0=regs.besb1org; break; case 3: cregs.c2pl2startadd0=regs.besb2corg; cregs.c2pl3startadd0=regs.besb2c3org; cregs.c2startadd0=regs.besb2org; break; } writel(C2STARTADD0, cregs.c2startadd0);// writel(C2PL2STARTADD0, cregs.c2pl2startadd0);// writel(C2PL3STARTADD0, cregs.c2pl3startadd0);}#endifint VIDIX_NAME(vixPlaybackFrameSelect)(unsigned int frame){ mga_next_frame = frame; if (mga_verbose>1) printf("[mga] frameselect: %d\n", mga_next_frame);#if MGA_ALLOW_IRQ if (mga_irq == -1)#endif { //we don't need the vcount protection as we're only hitting //one register (and it doesn't seem to be double buffered) regs.besctl = (regs.besctl & ~0x07000000) + (mga_next_frame << 25); writel(BESCTL, regs.besctl); // writel( regs.besglobctl + ((readl(VCOUNT)+2)<<16), writel(BESGLOBCTL, regs.besglobctl + (MGA_VSYNC_POS<<16));#ifdef CRTC2 crtc2_frame_sel(mga_next_frame);#endif } return(0);}static void mga_vid_write_regs(int restore){ //Make sure internal registers don't get updated until we're done writel(BESGLOBCTL, (readl(VCOUNT)-1)<<16); // color or coordinate keying if (restore && colkey_saved) { // restore it colkey_saved = 0; // Set color key registers: writeb(PALWTADD, XKEYOPMODE); writeb(X_DATAREG, colkey_on); writeb(PALWTADD, XCOLKEY0RED); writeb(X_DATAREG, colkey_color[0]); writeb(PALWTADD, XCOLKEY0GREEN); writeb(X_DATAREG, colkey_color[1]); writeb(PALWTADD, XCOLKEY0BLUE); writeb(X_DATAREG, colkey_color[2]); writeb(PALWTADD, X_COLKEY); writeb(X_DATAREG, colkey_color[3]); writeb(PALWTADD, XCOLMSK0RED); writeb(X_DATAREG, colkey_mask[0]); writeb(PALWTADD, XCOLMSK0GREEN); writeb(X_DATAREG, colkey_mask[1]); writeb(PALWTADD, XCOLMSK0BLUE); writeb(X_DATAREG, colkey_mask[2]); writeb(PALWTADD, XCOLMSK); writeb(X_DATAREG, colkey_mask[3]); printf("[mga] Restored colorkey (ON: %d %02X:%02X:%02X)\n", colkey_on,colkey_color[0],colkey_color[1],colkey_color[2]); } else if (!colkey_saved) { // save it colkey_saved=1; // Get color key registers: writeb(PALWTADD, XKEYOPMODE); colkey_on = readb(X_DATAREG) & 1; writeb(PALWTADD, XCOLKEY0RED); colkey_color[0]=(unsigned char)readb(X_DATAREG); writeb(PALWTADD, XCOLKEY0GREEN); colkey_color[1]=(unsigned char)readb(X_DATAREG); writeb(PALWTADD, XCOLKEY0BLUE); colkey_color[2]=(unsigned char)readb(X_DATAREG); writeb(PALWTADD, X_COLKEY); colkey_color[3]=(unsigned char)readb(X_DATAREG); writeb(PALWTADD, XCOLMSK0RED); colkey_mask[0]=(unsigned char)readb(X_DATAREG); writeb(PALWTADD, XCOLMSK0GREEN); colkey_mask[1]=(unsigned char)readb(X_DATAREG); writeb(PALWTADD, XCOLMSK0BLUE); colkey_mask[2]=(unsigned char)readb(X_DATAREG); writeb(PALWTADD, XCOLMSK); colkey_mask[3]=(unsigned char)readb(X_DATAREG); printf("[mga] Saved colorkey (ON: %d %02X:%02X:%02X)\n", colkey_on,colkey_color[0],colkey_color[1],colkey_color[2]); } if (!restore) { writeb(PALWTADD, XKEYOPMODE); writeb(X_DATAREG, (mga_grkey.ckey.op == CKEY_TRUE)); if ( mga_grkey.ckey.op == CKEY_TRUE ) { uint32_t r=0, g=0, b=0; writeb(PALWTADD, XMULCTRL); switch (readb(X_DATAREG)) { case BPP_8: /* Need to look up the color index, just using color 0 for now. */ break; case BPP_15: r = mga_grkey.ckey.red >> 3; g = mga_grkey.ckey.green >> 3; b = mga_grkey.ckey.blue >> 3; break; case BPP_16: r = mga_grkey.ckey.red >> 3; g = mga_grkey.ckey.green >> 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -