📄 smilynxem.c
字号:
/* * (C) Copyright 1997-2002 ELTEC Elektronik AG * Frank Gottschling <fgottschling@eltec.de> * * See file CREDITS for list of people who contributed to this * project. * * This program 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. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA *//* * smiLynxEM.c * * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator * * modification history * -------------------- * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>. * * 18-03-2004 - Unify videomodes handling with the ct69000 * - The video output can be set via the variable "videoout" * in the environment. * videoout=1 output on LCD * videoout=2 output on CRT (default value) * <p.aubert@staubli.com> */#include <common.h>#if defined(CONFIG_VIDEO_SMI_LYNXEM)#include <pci.h>#include <video_fb.h>#include "videomodes.h"/* * Export Graphic Device */GraphicDevice smi;/* * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external */#define VIDEO_MEM_SIZE 0x400000/* * ISA mapped regs */#define SMI_INDX_C4 (pGD->isaBase + 0x03c4) /* index reg */#define SMI_DATA_C5 (pGD->isaBase + 0x03c5) /* data reg */#define SMI_INDX_D4 (pGD->isaBase + 0x03d4) /* index reg */#define SMI_DATA_D5 (pGD->isaBase + 0x03d5) /* data reg */#define SMI_ISR1 (pGD->isaBase + 0x03ca)#define SMI_INDX_CE (pGD->isaBase + 0x03ce) /* index reg */#define SMI_DATA_CF (pGD->isaBase + 0x03cf) /* data reg */#define SMI_LOCK_REG (pGD->isaBase + 0x03c3) /* unlock/lock ext crt reg */#define SMI_MISC_REG (pGD->isaBase + 0x03c2) /* misc reg */#define SMI_LUT_MASK (pGD->isaBase + 0x03c6) /* lut mask reg */#define SMI_LUT_START (pGD->isaBase + 0x03c8) /* lut start index */#define SMI_LUT_RGB (pGD->isaBase + 0x03c9) /* lut colors auto incr.*/#define SMI_INDX_ATTR (pGD->isaBase + 0x03c0) /* attributes index reg *//* * Video processor control */typedef struct { unsigned int control; unsigned int colorKey; unsigned int colorKeyMask; unsigned int start; unsigned short offset; unsigned short width; unsigned int fifoPrio; unsigned int fifoERL; unsigned int YUVtoRGB;} SmiVideoProc;/* * Video window control */typedef struct { unsigned short top; unsigned short left; unsigned short bottom; unsigned short right; unsigned int srcStart; unsigned short width; unsigned short offset; unsigned char hStretch; unsigned char vStretch;} SmiVideoWin;/* * Capture port control */typedef struct { unsigned int control; unsigned short topClip; unsigned short leftClip; unsigned short srcHeight; unsigned short srcWidth; unsigned int srcBufStart1; unsigned int srcBufStart2; unsigned short srcOffset; unsigned short fifoControl;} SmiCapturePort;/* * Register values for common video modes */static char SMI_SCR[] = { /* all modes */ 0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x15, 0x90, 0x17, 0x20, 0x18, 0xb1, 0x19, 0x00,};static char SMI_EXT_CRT[] = { 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00};static char SMI_ATTR [] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x41, 0x11, 0x00, 0x12, 0x0f, 0x13, 0x00, 0x14, 0x00,};static char SMI_GCR[18] = { 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40, 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff};static char SMI_SEQR[] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03};static char SMI_PCR [] = { 0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00};static char SMI_MCR[] = { 0x60, 0x01, 0x61, 0x00,};static char SMI_HCR[] = { 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00, 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00};/******************************************************************************* * * Write SMI ISA register */static void smiWrite (unsigned short index, char reg, char val){ register GraphicDevice *pGD = (GraphicDevice *)&smi; out8 ((pGD->isaBase + index), reg); out8 ((pGD->isaBase + index + 1), val);}/******************************************************************************* * * Write a table of SMI ISA register */static void smiLoadRegs ( unsigned int iReg, unsigned int dReg, char *regTab, unsigned int tabSize ){ register GraphicDevice *pGD = (GraphicDevice *)&smi; register int i; for (i=0; i<tabSize; i+=2) { if (iReg == SMI_INDX_ATTR) { /* Reset the Flip Flop */ in8 (SMI_ISR1); out8 (iReg, regTab[i]); out8 (iReg, regTab[i+1]); } else { out8 (iReg, regTab[i]); out8 (dReg, regTab[i+1]); } }}/******************************************************************************* * * Init capture port registers */static void smiInitCapturePort (void){ SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 }; register GraphicDevice *pGD = (GraphicDevice *)&smi; register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP; out32r ((pGD->cprBase + 0x0004), ((pCP->topClip<<16) | pCP->leftClip)); out32r ((pGD->cprBase + 0x0008), ((pCP->srcHeight<<16) | pCP->srcWidth)); out32r ((pGD->cprBase + 0x000c), pCP->srcBufStart1/8); out32r ((pGD->cprBase + 0x0010), pCP->srcBufStart2/8); out32r ((pGD->cprBase + 0x0014), pCP->srcOffset/8); out32r ((pGD->cprBase + 0x0018), pCP->fifoControl); out32r ((pGD->cprBase + 0x0000), pCP->control);}/******************************************************************************* * * Init video processor registers */static void smiInitVideoProcessor (void){ SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed }; SmiVideoWin smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 }; register GraphicDevice *pGD = (GraphicDevice *)&smi; register SmiVideoProc *pVP = (SmiVideoProc *)&smiVP; register SmiVideoWin *pVWin = (SmiVideoWin *)&smiVW; pVP->width = pGD->plnSizeX * pGD->gdfBytesPP; pVP->control |= pGD->gdfIndex << 16; pVWin->bottom = pGD->winSizeY - 1; pVWin->right = pGD->winSizeX - 1; pVWin->width = pVP->width; /* color key */ out32r ((pGD->vprBase + 0x0004), pVP->colorKey); /* color key mask */ out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask); /* data src start adrs */ out32r ((pGD->vprBase + 0x000c), pVP->start / 8); /* data width and offset */ out32r ((pGD->vprBase + 0x0010), ((pVP->offset / 8 * pGD->gdfBytesPP) << 16) | (pGD->plnSizeX / 8 * pGD->gdfBytesPP)); /* video window 1 */ out32r ((pGD->vprBase + 0x0014), ((pVWin->top << 16) | pVWin->left)); out32r ((pGD->vprBase + 0x0018), ((pVWin->bottom << 16) | pVWin->right)); out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8); out32r ((pGD->vprBase + 0x0020), (((pVWin->offset / 8) << 16) | (pVWin->width / 8))); out32r ((pGD->vprBase + 0x0024), (((pVWin->hStretch) << 8) | pVWin->vStretch)); /* video window 2 */ out32r ((pGD->vprBase + 0x0028), ((pVWin->top << 16) | pVWin->left)); out32r ((pGD->vprBase + 0x002c), ((pVWin->bottom << 16) | pVWin->right)); out32r ((pGD->vprBase + 0x0030), pVWin->srcStart / 8); out32r ((pGD->vprBase + 0x0034), (((pVWin->offset / 8) << 16) | (pVWin->width / 8))); out32r ((pGD->vprBase + 0x0038), (((pVWin->hStretch) << 8) | pVWin->vStretch)); /* fifo prio control */ out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio); /* fifo empty request levell */ out32r ((pGD->vprBase + 0x0058), pVP->fifoERL); /* conversion constant */ out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB); /* vpr control word */ out32r ((pGD->vprBase + 0x0000), pVP->control);}/****************************************************************************** * * Init drawing engine registers */static void smiInitDrawingEngine (void){ GraphicDevice *pGD = (GraphicDevice *)&smi; unsigned int val; /* don't start now */ out32r ((pGD->dprBase + 0x000c), 0x000f0000); /* set rop2 to copypen */ val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c)); out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c)); /* set clip rect */ out32r ((pGD->dprBase + 0x002c), 0); out32r ((pGD->dprBase + 0x0030), ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP )); /* src row pitch */ val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010))); out32r ((pGD->dprBase + 0x0010), (val | pGD->plnSizeX * pGD->gdfBytesPP)); /* dst row pitch */ val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010))); out32r ((pGD->dprBase + 0x0010), (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val)); /* window width src/dst */ out32r ((pGD->dprBase + 0x003c), (((pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)<<16) | (pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff))); out16r ((pGD->dprBase + 0x001e), 0x0000); /* src base adrs */ out32r ((pGD->dprBase + 0x0040), (((pGD->frameAdrs/8) & 0x000fffff))); /* dst base adrs */ out32r ((pGD->dprBase + 0x0044), (((pGD->frameAdrs/8) & 0x000fffff))); /* foreground color */ out32r ((pGD->dprBase + 0x0014), pGD->fg); /* background color */ out32r ((pGD->dprBase + 0x0018), pGD->bg); /* xcolor */ out32r ((pGD->dprBase + 0x0020), 0x00ffffff); /* xcolor mask */ out32r ((pGD->dprBase + 0x0024), 0x00ffffff); /* bit mask */ out32r ((pGD->dprBase + 0x0028), 0x00ffffff); /* load mono pattern */ out32r ((pGD->dprBase + 0x0034), 0); out32r ((pGD->dprBase + 0x0038), 0);}static struct pci_device_id supported[] = { { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_710 }, { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_712 }, { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_810 }, { }};/*****************************************************************************/static void smiLoadMsr (struct ctfb_res_modes *mode){ unsigned char h_synch_high, v_synch_high; register GraphicDevice *pGD = (GraphicDevice *)&smi; h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40; /* horizontal Synch High active */ v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */ out8 (SMI_MISC_REG, (h_synch_high | v_synch_high | 0x29)); /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01 * Selects the upper 64KB page.Bit5=1 * CLK2 (left reserved in standard VGA) Bit3|2=1|0 * Disables CPU access to frame buffer. Bit1=0 * Sets the I/O address decode for ST01, FCR, and all CR registers * to the 3Dx I/O address range (CGA emulation). Bit0=1 */}/*****************************************************************************/static void smiLoadCrt (struct ctfb_res_modes *var, int bits_per_pixel){ unsigned char cr[0x7a]; int i; unsigned int hd, hs, he, ht, hbs, hbe; /* Horizontal. */ unsigned int vd, vs, ve, vt, vbs, vbe; /* vertical */ unsigned int bpp, wd, dblscan, interlaced; const int LineCompare = 0x3ff; unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor */ register GraphicDevice *pGD = (GraphicDevice *)&smi; /* Horizontal */ hd = (var->xres) / 8; /* HDisp. */ hs = (var->xres + var->right_margin) / 8; /* HsStrt */ he = (var->xres + var->right_margin + var->hsync_len) / 8; /* HsEnd */ ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8; /* HTotal */ /* Blank */ hbs = hd; hbe = 0; /* Blank end at 0 */ /* Vertical */ vd = var->yres; /* VDisplay */ vs = var->yres + var->lower_margin; /* VSyncStart */ ve = var->yres + var->lower_margin + var->vsync_len; /* VSyncEnd */ vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; /* VTotal */ vbs = vd; vbe = 0; bpp = bits_per_pixel; dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0; interlaced = var->vmode & FB_VMODE_INTERLACED; if (bpp == 15) bpp = 16; wd = var->xres * bpp / 64; /* double words per line */ if (interlaced) { /* we divide all vertical timings, exept vd */ vs >>= 1; vbs >>= 1; ve >>= 1; vt >>= 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -