?? sisusb_init.c
字號:
/* * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles * * Display mode initializing code * * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria * * If distributed as part of the Linux kernel, this code is licensed under the * terms of the GPL v2. * * Otherwise, the following license terms apply: * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * 1) Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * 2) Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * 3) The name of the author may not be used to endorse or promote products * * derived from this software without specific prior written permission. * * * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Author: Thomas Winischhofer <thomas@winischhofer.net> * */#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/poll.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/spinlock.h>#include <linux/kref.h>#include "sisusb.h"#ifdef INCL_SISUSB_CON#include "sisusb_init.h"/*********************************************//* POINTER INITIALIZATION *//*********************************************/static void SiSUSB_InitPtr(struct SiS_Private *SiS_Pr){ SiS_Pr->SiS_ModeResInfo = SiSUSB_ModeResInfo; SiS_Pr->SiS_StandTable = SiSUSB_StandTable; SiS_Pr->SiS_SModeIDTable = SiSUSB_SModeIDTable; SiS_Pr->SiS_EModeIDTable = SiSUSB_EModeIDTable; SiS_Pr->SiS_RefIndex = SiSUSB_RefIndex; SiS_Pr->SiS_CRT1Table = SiSUSB_CRT1Table; SiS_Pr->SiS_VCLKData = SiSUSB_VCLKData;}/*********************************************//* HELPER: SetReg, GetReg *//*********************************************/static voidSiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port, unsigned short index, unsigned short data){ sisusb_setidxreg(SiS_Pr->sisusb, port, index, data);}static voidSiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port, unsigned short data){ sisusb_setreg(SiS_Pr->sisusb, port, data);}static unsigned charSiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port, unsigned short index){ u8 data; sisusb_getidxreg(SiS_Pr->sisusb, port, index, &data); return data;}static unsigned charSiS_GetRegByte(struct SiS_Private *SiS_Pr, unsigned long port){ u8 data; sisusb_getreg(SiS_Pr->sisusb, port, &data); return data;}static voidSiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port, unsigned short index, unsigned short DataAND, unsigned short DataOR){ sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR);}static voidSiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port, unsigned short index, unsigned short DataAND){ sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND);}static voidSiS_SetRegOR(struct SiS_Private *SiS_Pr, unsigned long port, unsigned short index, unsigned short DataOR){ sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR);}/*********************************************//* HELPER: DisplayOn, DisplayOff *//*********************************************/static void SiS_DisplayOn(struct SiS_Private *SiS_Pr){ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF);}/*********************************************//* HELPER: Init Port Addresses *//*********************************************/static void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr){ SiS_Pr->SiS_P3c4 = BaseAddr + 0x14; SiS_Pr->SiS_P3d4 = BaseAddr + 0x24; SiS_Pr->SiS_P3c0 = BaseAddr + 0x10; SiS_Pr->SiS_P3ce = BaseAddr + 0x1e; SiS_Pr->SiS_P3c2 = BaseAddr + 0x12; SiS_Pr->SiS_P3ca = BaseAddr + 0x1a; SiS_Pr->SiS_P3c6 = BaseAddr + 0x16; SiS_Pr->SiS_P3c7 = BaseAddr + 0x17; SiS_Pr->SiS_P3c8 = BaseAddr + 0x18; SiS_Pr->SiS_P3c9 = BaseAddr + 0x19; SiS_Pr->SiS_P3cb = BaseAddr + 0x1b; SiS_Pr->SiS_P3cc = BaseAddr + 0x1c; SiS_Pr->SiS_P3cd = BaseAddr + 0x1d; SiS_Pr->SiS_P3da = BaseAddr + 0x2a; SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;}/*********************************************//* HELPER: GetSysFlags *//*********************************************/static void SiS_GetSysFlags(struct SiS_Private *SiS_Pr){ SiS_Pr->SiS_MyCR63 = 0x63;}/*********************************************//* HELPER: Init PCI & Engines *//*********************************************/static void SiSInitPCIetc(struct SiS_Private *SiS_Pr){ SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1); /* - Enable 2D (0x40) * - Enable 3D (0x02) * - Enable 3D vertex command fetch (0x10) * - Enable 3D command parser (0x08) * - Enable 3D G/L transformation engine (0x80) */ SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1E, 0xDA);}/*********************************************//* HELPER: SET SEGMENT REGISTERS *//*********************************************/static void SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value){ unsigned short temp; value &= 0x00ff; temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0xf0; temp |= (value >> 4); SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp); temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0xf0; temp |= (value & 0x0f); SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);}static void SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value){ unsigned short temp; value &= 0x00ff; temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0x0f; temp |= (value & 0xf0); SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp); temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0x0f; temp |= (value << 4); SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);}static void SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value){ SiS_SetSegRegLower(SiS_Pr, value); SiS_SetSegRegUpper(SiS_Pr, value);}static void SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr){ SiS_SetSegmentReg(SiS_Pr, 0);}static voidSiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value){ unsigned short temp = value >> 8; temp &= 0x07; temp |= (temp << 4); SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1d, temp); SiS_SetSegmentReg(SiS_Pr, value);}static void SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr){ SiS_SetSegmentRegOver(SiS_Pr, 0);}static void SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr){ SiS_ResetSegmentReg(SiS_Pr); SiS_ResetSegmentRegOver(SiS_Pr);}/*********************************************//* HELPER: SearchModeID *//*********************************************/static intSiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo, unsigned short *ModeIdIndex){ if ((*ModeNo) <= 0x13) { if ((*ModeNo) != 0x03) return 0; (*ModeIdIndex) = 0; } else { for (*ModeIdIndex = 0;; (*ModeIdIndex)++) { if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo)) break; if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF) return 0; } } return 1;}/*********************************************//* HELPER: ENABLE CRT1 *//*********************************************/static void SiS_HandleCRT1(struct SiS_Private *SiS_Pr){ /* Enable CRT1 gating */ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf);}/*********************************************//* HELPER: GetColorDepth *//*********************************************/static unsigned shortSiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex){ static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 }; unsigned short modeflag; short index; if (ModeNo <= 0x13) { modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; } else { modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; } index = (modeflag & ModeTypeMask) - ModeEGA; if (index < 0) index = 0; return ColorDepth[index];}/*********************************************//* HELPER: GetOffset *//*********************************************/static unsigned shortSiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short rrti){ unsigned short xres, temp, colordepth, infoflag; infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag; xres = SiS_Pr->SiS_RefIndex[rrti].XRes; colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex); temp = xres / 16; if (infoflag & InterlaceMode) temp <<= 1; temp *= colordepth; if (xres % 16) temp += (colordepth >> 1); return temp;}/*********************************************//* SEQ *//*********************************************/static voidSiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex){ unsigned char SRdata; int i; SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x00, 0x03); SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20; SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata); for (i = 2; i <= 4; i++) { SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1]; SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata); }}/*********************************************//* MISC *//*********************************************/static voidSiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex){ unsigned char Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC; SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, Miscdata);}/*********************************************//* CRTC *//*********************************************/static voidSiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex){ unsigned char CRTCdata; unsigned short i; SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f); for (i = 0; i <= 0x18; i++) { CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i]; SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata); }}/*********************************************//* ATT *//*********************************************/static voidSiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex){ unsigned char ARdata; unsigned short i; for (i = 0; i <= 0x13; i++) { ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i]; SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da); SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i); SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, ARdata); } SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da); SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x14); SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x00); SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da); SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x20); SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);}/*********************************************//* GRC *//*********************************************/static voidSiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex){ unsigned char GRdata; unsigned short i; for (i = 0; i <= 0x08; i++) { GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i]; SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata); } if (SiS_Pr->SiS_ModeType > ModeVGA) { /* 256 color disable */ SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3ce, 0x05, 0xBF); }}/*********************************************//* CLEAR EXTENDED REGISTERS *//*********************************************/static void SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo){ int i; for (i = 0x0A; i <= 0x0E; i++) { SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00); } SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x37, 0xFE);}/*********************************************//* Get rate index *//*********************************************/static unsigned shortSiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex){ unsigned short rrti, i, index, temp; if (ModeNo <= 0x13) return 0xFFFF; index = SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x33) & 0x0F; if (index > 0) index--; rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID; i = 0; do { if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo) break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -