uboot/drivers/video/smiLynxEM.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 1997-2002 ELTEC Elektronik AG
   3 * Frank Gottschling <fgottschling@eltec.de>
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8/*
   9 * smiLynxEM.c
  10 *
  11 * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator
  12 *
  13 * modification history
  14 * --------------------
  15 * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>.
  16 *
  17 * 18-03-2004 - Unify videomodes handling with the ct69000
  18 *            - The video output can be set via the variable "videoout"
  19 *              in the environment.
  20 *              videoout=1 output on LCD
  21 *              videoout=2 output on CRT (default value)
  22 *                      <p.aubert@staubli.com>
  23 */
  24
  25#include <common.h>
  26
  27#include <pci.h>
  28#include <video_fb.h>
  29#include "videomodes.h"
  30/*
  31 * Export Graphic Device
  32 */
  33GraphicDevice smi;
  34
  35/*
  36 * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
  37 */
  38#define VIDEO_MEM_SIZE  0x400000
  39
  40
  41/*
  42 * ISA mapped regs
  43 */
  44#define SMI_INDX_C4             (pGD->isaBase + 0x03c4)    /* index reg */
  45#define SMI_DATA_C5             (pGD->isaBase + 0x03c5)    /* data reg */
  46#define SMI_INDX_D4             (pGD->isaBase + 0x03d4)    /* index reg */
  47#define SMI_DATA_D5             (pGD->isaBase + 0x03d5)    /* data reg */
  48#define SMI_ISR1                (pGD->isaBase + 0x03ca)
  49#define SMI_INDX_CE             (pGD->isaBase + 0x03ce)    /* index reg */
  50#define SMI_DATA_CF             (pGD->isaBase + 0x03cf)    /* data reg */
  51#define SMI_LOCK_REG            (pGD->isaBase + 0x03c3)    /* unlock/lock ext crt reg */
  52#define SMI_MISC_REG            (pGD->isaBase + 0x03c2)    /* misc reg */
  53#define SMI_LUT_MASK            (pGD->isaBase + 0x03c6)    /* lut mask reg */
  54#define SMI_LUT_START           (pGD->isaBase + 0x03c8)    /* lut start index */
  55#define SMI_LUT_RGB             (pGD->isaBase + 0x03c9)    /* lut colors auto incr.*/
  56#define SMI_INDX_ATTR           (pGD->isaBase + 0x03c0)    /* attributes index reg */
  57
  58/*
  59 * Video processor control
  60 */
  61typedef struct {
  62        unsigned int   control;
  63        unsigned int   colorKey;
  64        unsigned int   colorKeyMask;
  65        unsigned int   start;
  66        unsigned short offset;
  67        unsigned short width;
  68        unsigned int   fifoPrio;
  69        unsigned int   fifoERL;
  70        unsigned int   YUVtoRGB;
  71} SmiVideoProc;
  72
  73/*
  74 * Video window control
  75 */
  76typedef struct {
  77        unsigned short top;
  78        unsigned short left;
  79        unsigned short bottom;
  80        unsigned short right;
  81        unsigned int   srcStart;
  82        unsigned short width;
  83        unsigned short offset;
  84        unsigned char  hStretch;
  85        unsigned char  vStretch;
  86} SmiVideoWin;
  87
  88/*
  89 * Capture port control
  90 */
  91typedef struct {
  92        unsigned int   control;
  93        unsigned short topClip;
  94        unsigned short leftClip;
  95        unsigned short srcHeight;
  96        unsigned short srcWidth;
  97        unsigned int   srcBufStart1;
  98        unsigned int   srcBufStart2;
  99        unsigned short srcOffset;
 100        unsigned short fifoControl;
 101} SmiCapturePort;
 102
 103
 104/*
 105 * Register values for common video modes
 106 */
 107static char SMI_SCR[] = {
 108        /* all modes */
 109        0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x15, 0x90,
 110        0x17, 0x20, 0x18, 0xb1, 0x19, 0x00,
 111};
 112static char SMI_EXT_CRT[] = {
 113        0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
 114        0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00,
 115};
 116static char SMI_ATTR [] = {
 117        0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05,
 118        0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b,
 119        0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x41, 0x11, 0x00,
 120        0x12, 0x0f, 0x13, 0x00, 0x14, 0x00,
 121};
 122static char SMI_GCR[18] = {
 123        0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
 124        0x06, 0x05, 0x07, 0x0f, 0x08, 0xff,
 125};
 126static char SMI_SEQR[] = {
 127        0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03,
 128};
 129static char SMI_PCR [] = {
 130        0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00,
 131};
 132static char SMI_MCR[] = {
 133        0x60, 0x01, 0x61, 0x00,
 134#ifdef CONFIG_HMI1001
 135        0x62, 0x74, /* Memory type is not configured by pins on HMI1001 */
 136#endif
 137};
 138
 139static char SMI_HCR[] = {
 140        0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
 141        0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00,
 142};
 143
 144
 145/*******************************************************************************
 146 *
 147 * Write SMI ISA register
 148 */
 149static void smiWrite (unsigned short index, char reg, char val)
 150{
 151        register GraphicDevice *pGD = (GraphicDevice *)&smi;
 152
 153        out8 ((pGD->isaBase + index), reg);
 154        out8 ((pGD->isaBase + index + 1), val);
 155}
 156
 157/*******************************************************************************
 158 *
 159 * Write a table of SMI ISA register
 160 */
 161static void smiLoadRegs (
 162        unsigned int iReg,
 163        unsigned int dReg,
 164        char         *regTab,
 165        unsigned int tabSize
 166        )
 167{
 168        register GraphicDevice *pGD  = (GraphicDevice *)&smi;
 169        register int i;
 170
 171        for (i=0; i<tabSize; i+=2) {
 172                if (iReg == SMI_INDX_ATTR) {
 173                        /* Reset the Flip Flop */
 174                        in8 (SMI_ISR1);
 175                        out8 (iReg, regTab[i]);
 176                        out8 (iReg, regTab[i+1]);
 177                } else {
 178                        out8 (iReg, regTab[i]);
 179                        out8 (dReg, regTab[i+1]);
 180                }
 181        }
 182}
 183
 184/*******************************************************************************
 185 *
 186 * Init capture port registers
 187 */
 188static void smiInitCapturePort (void)
 189{
 190        SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
 191        register GraphicDevice *pGD  = (GraphicDevice *)&smi;
 192        register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
 193
 194        out32r ((pGD->cprBase + 0x0004), ((pCP->topClip<<16)   | pCP->leftClip));
 195        out32r ((pGD->cprBase + 0x0008), ((pCP->srcHeight<<16) | pCP->srcWidth));
 196        out32r ((pGD->cprBase + 0x000c), pCP->srcBufStart1/8);
 197        out32r ((pGD->cprBase + 0x0010), pCP->srcBufStart2/8);
 198        out32r ((pGD->cprBase + 0x0014), pCP->srcOffset/8);
 199        out32r ((pGD->cprBase + 0x0018), pCP->fifoControl);
 200        out32r ((pGD->cprBase + 0x0000), pCP->control);
 201}
 202
 203
 204/*******************************************************************************
 205 *
 206 * Init video processor registers
 207 */
 208static void smiInitVideoProcessor (void)
 209{
 210        SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed };
 211        SmiVideoWin  smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 };
 212        register GraphicDevice *pGD = (GraphicDevice *)&smi;
 213        register SmiVideoProc  *pVP = (SmiVideoProc *)&smiVP;
 214        register SmiVideoWin *pVWin = (SmiVideoWin *)&smiVW;
 215
 216        pVP->width    = pGD->plnSizeX * pGD->gdfBytesPP;
 217        pVP->control |= pGD->gdfIndex << 16;
 218        pVWin->bottom = pGD->winSizeY - 1;
 219        pVWin->right  = pGD->winSizeX - 1;
 220        pVWin->width  = pVP->width;
 221
 222        /* color key */
 223        out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
 224
 225        /* color key mask */
 226        out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
 227
 228        /* data src start adrs */
 229        out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
 230
 231        /* data width and offset */
 232        out32r ((pGD->vprBase + 0x0010),
 233                ((pVP->offset   / 8 * pGD->gdfBytesPP) << 16) |
 234                (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
 235
 236        /* video window 1 */
 237        out32r ((pGD->vprBase + 0x0014),
 238                ((pVWin->top << 16) | pVWin->left));
 239
 240        out32r ((pGD->vprBase + 0x0018),
 241                ((pVWin->bottom << 16) | pVWin->right));
 242
 243        out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
 244
 245        out32r ((pGD->vprBase + 0x0020),
 246                (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
 247
 248        out32r ((pGD->vprBase + 0x0024),
 249                (((pVWin->hStretch) << 8) | pVWin->vStretch));
 250
 251        /* video window 2 */
 252        out32r ((pGD->vprBase + 0x0028),
 253                ((pVWin->top << 16) | pVWin->left));
 254
 255        out32r ((pGD->vprBase + 0x002c),
 256                ((pVWin->bottom << 16) | pVWin->right));
 257
 258        out32r ((pGD->vprBase + 0x0030),
 259                pVWin->srcStart / 8);
 260
 261        out32r ((pGD->vprBase + 0x0034),
 262                (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
 263
 264        out32r ((pGD->vprBase + 0x0038),
 265                (((pVWin->hStretch) << 8) | pVWin->vStretch));
 266
 267        /* fifo prio control */
 268        out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
 269
 270        /* fifo empty request levell */
 271        out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
 272
 273        /* conversion constant */
 274        out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
 275
 276        /* vpr control word */
 277        out32r ((pGD->vprBase + 0x0000), pVP->control);
 278}
 279
 280/******************************************************************************
 281 *
 282 * Init drawing engine registers
 283 */
 284static void smiInitDrawingEngine (void)
 285{
 286        GraphicDevice *pGD = (GraphicDevice *)&smi;
 287        unsigned int val;
 288
 289        /* don't start now */
 290        out32r ((pGD->dprBase + 0x000c), 0x000f0000);
 291
 292        /* set rop2 to copypen */
 293        val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
 294        out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
 295
 296        /* set clip rect */
 297        out32r ((pGD->dprBase + 0x002c), 0);
 298        out32r ((pGD->dprBase + 0x0030),
 299                ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
 300
 301        /* src row pitch */
 302        val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
 303        out32r ((pGD->dprBase + 0x0010),
 304                (val | pGD->plnSizeX * pGD->gdfBytesPP));
 305
 306        /* dst row pitch */
 307        val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
 308        out32r ((pGD->dprBase + 0x0010),
 309                (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
 310
 311        /* window width src/dst */
 312        out32r ((pGD->dprBase + 0x003c),
 313                (((pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)<<16) |
 314                 (pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)));
 315        out16r ((pGD->dprBase + 0x001e), 0x0000);
 316
 317        /* src base adrs */
 318        out32r ((pGD->dprBase + 0x0040),
 319                (((pGD->frameAdrs/8) & 0x000fffff)));
 320
 321        /* dst base adrs */
 322        out32r ((pGD->dprBase + 0x0044),
 323                (((pGD->frameAdrs/8) & 0x000fffff)));
 324
 325        /* foreground color */
 326        out32r ((pGD->dprBase + 0x0014), pGD->fg);
 327
 328        /* background color */
 329        out32r ((pGD->dprBase + 0x0018), pGD->bg);
 330
 331        /* xcolor */
 332        out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
 333
 334        /* xcolor mask */
 335        out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
 336
 337        /* bit mask */
 338        out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
 339
 340        /* load mono pattern */
 341        out32r ((pGD->dprBase + 0x0034), 0);
 342        out32r ((pGD->dprBase + 0x0038), 0);
 343}
 344
 345static struct pci_device_id supported[] = {
 346        { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_710 },
 347        { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_712 },
 348        { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_810 },
 349        { }
 350};
 351
 352/*****************************************************************************/
 353static void smiLoadMsr (struct ctfb_res_modes *mode)
 354{
 355        unsigned char h_synch_high, v_synch_high;
 356        register GraphicDevice *pGD  = (GraphicDevice *)&smi;
 357
 358        h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40;  /* horizontal Synch High active */
 359        v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */
 360        out8 (SMI_MISC_REG, (h_synch_high | v_synch_high | 0x29));
 361        /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
 362         * Selects the upper 64KB page.Bit5=1
 363         * CLK2 (left reserved in standard VGA) Bit3|2=1|0
 364         * Disables CPU access to frame buffer. Bit1=0
 365         * Sets the I/O address decode for ST01, FCR, and all CR registers
 366         * to the 3Dx I/O address range (CGA emulation). Bit0=1
 367         */
 368}
 369/*****************************************************************************/
 370static void smiLoadCrt (struct ctfb_res_modes *var, int bits_per_pixel)
 371{
 372        unsigned char cr[0x7a];
 373        int i;
 374        unsigned int hd, hs, he, ht, hbs, hbe;  /* Horizontal.  */
 375        unsigned int vd, vs, ve, vt, vbs, vbe;  /* vertical */
 376        unsigned int bpp, wd, dblscan, interlaced;
 377
 378        const int LineCompare = 0x3ff;
 379        unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor   */
 380        register GraphicDevice *pGD  = (GraphicDevice *)&smi;
 381
 382        /* Horizontal */
 383        hd = (var->xres) / 8;   /* HDisp.  */
 384        hs = (var->xres + var->right_margin) / 8;       /* HsStrt  */
 385        he = (var->xres + var->right_margin + var->hsync_len) / 8;      /* HsEnd   */
 386        ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8;   /* HTotal  */
 387        /* Blank */
 388        hbs = hd;
 389        hbe = 0; /* Blank end at 0 */
 390
 391        /* Vertical */
 392        vd = var->yres;         /* VDisplay   */
 393        vs = var->yres + var->lower_margin;     /* VSyncStart */
 394        ve = var->yres + var->lower_margin + var->vsync_len;    /* VSyncEnd */
 395        vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len;        /* VTotal  */
 396        vbs = vd;
 397        vbe = 0;
 398
 399        bpp = bits_per_pixel;
 400        dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
 401        interlaced = var->vmode & FB_VMODE_INTERLACED;
 402
 403
 404        if (bpp == 15)
 405                bpp = 16;
 406        wd = var->xres * bpp / 64;      /* double words per line */
 407        if (interlaced) {       /* we divide all vertical timings, exept vd */
 408                vs >>= 1;
 409                vbs >>= 1;
 410                ve >>= 1;
 411                vt >>= 1;
 412        }
 413
 414        memset (cr, 0, sizeof (cr));
 415        cr[0x00] = ht - 5;
 416        cr[0x01] = hd - 1;
 417        cr[0x02] = hbs - 1;
 418        cr[0x03] = (hbe & 0x1F);
 419        cr[0x04] = hs;
 420        cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
 421
 422        cr[0x06] = (vt - 2) & 0xFF;
 423        cr[0x07] = (((vt - 2) & 0x100) >> 8)
 424                | (((vd - 1) & 0x100) >> 7)
 425                | ((vs & 0x100) >> 6)
 426                | (((vbs - 1) & 0x100) >> 5)
 427                | ((LineCompare & 0x100) >> 4)
 428                | (((vt - 2) & 0x200) >> 4)
 429                | (((vd - 1) & 0x200) >> 3)
 430                | ((vs & 0x200) >> 2);
 431
 432        cr[0x30] = ((vt - 2) & 0x400) >> 7
 433                | (((vd - 1) & 0x400) >> 8)
 434                | (((vbs - 1) & 0x400) >> 9)
 435                | ((vs & 0x400) >> 10)
 436                | (interlaced) ? 0x80 : 0;
 437
 438
 439        cr[0x08] = 0x00;
 440        cr[0x09] = (dblscan << 7)
 441                | ((LineCompare & 0x200) >> 3)
 442                | (((vbs - 1) & 0x200) >> 4)
 443                | (TextScanLines - 1);
 444
 445        cr[0x10] = vs & 0xff;   /* VSyncPulseStart */
 446        cr[0x11] = (ve & 0x0f);
 447        cr[0x12] = (vd - 1) & 0xff;     /* LineCount  */
 448        cr[0x13] = wd & 0xff;
 449        cr[0x14] = 0x40;
 450        cr[0x15] = (vbs - 1) & 0xff;
 451        cr[0x16] = vbe & 0xff;
 452        cr[0x17] = 0xe3;        /* but it does not work */
 453        cr[0x18] = 0xff & LineCompare;
 454        cr[0x22] = 0x00;        /* todo? */
 455
 456
 457        /* now set the registers */
 458        for (i = 0; i <= 0x18; i++) {   /*CR00 .. CR18 */
 459                smiWrite (SMI_INDX_D4, i, cr[i]);
 460        }
 461        i = 0x22;               /*CR22 */
 462        smiWrite (SMI_INDX_D4, i, cr[i]);
 463        i = 0x30;               /*CR30 */
 464        smiWrite (SMI_INDX_D4, i, cr[i]);
 465}
 466
 467/*****************************************************************************/
 468#define REF_FREQ        14318180
 469#define PMIN            1
 470#define PMAX            255
 471#define QMIN            1
 472#define QMAX            63
 473
 474static unsigned int FindPQ (unsigned int freq, unsigned int *pp, unsigned int *pq)
 475{
 476        unsigned int n = QMIN, m = 0;
 477        long long int L = 0, P = freq, Q = REF_FREQ, H = P >> 1;
 478        long long int D = 0x7ffffffffffffffLL;
 479
 480        for (n = QMIN; n <= QMAX; n++) {
 481                m = PMIN;       /* p/q ~ freq/ref -> p*ref-freq*q ~ 0 */
 482                L = P * n - m * Q;
 483                while (L > 0 && m < PMAX) {
 484                        L -= REF_FREQ;  /* difference is greater as 0 subtract fref */
 485                        m++;    /* and increment m */
 486                }
 487                /* difference is less or equal than 0 or m > maximum */
 488                if (m > PMAX)
 489                        break;  /* no solution: if we increase n we get the same situation */
 490                /* L is <= 0 now */
 491                if (-L > H && m > PMIN) {       /* if difference > the half fref */
 492                        L += REF_FREQ;  /* we take the situation before */
 493                        m--;    /* because its closer to 0 */
 494                }
 495                L = (L < 0) ? -L : +L;  /* absolute value */
 496                if (D < L)      /* if last difference was better take next n */
 497                        continue;
 498                D = L;
 499                *pp = m;
 500                *pq = n;        /*  keep improved data */
 501                if (D == 0)
 502                        break;  /* best result we can get */
 503        }
 504        return (unsigned int) (0xffffffff & D);
 505}
 506
 507/*****************************************************************************/
 508static void smiLoadCcr (struct ctfb_res_modes *var, unsigned short device_id)
 509{
 510        unsigned int p = 0;
 511        unsigned int q = 0;
 512        long long freq;
 513        register GraphicDevice *pGD  = (GraphicDevice *)&smi;
 514
 515        smiWrite (SMI_INDX_C4, 0x65, 0);
 516        smiWrite (SMI_INDX_C4, 0x66, 0);
 517        smiWrite (SMI_INDX_C4, 0x68, 0x50);
 518        if (device_id == PCI_DEVICE_ID_SMI_810) {
 519                smiWrite (SMI_INDX_C4, 0x69, 0x3);
 520        } else {
 521                smiWrite (SMI_INDX_C4, 0x69, 0x0);
 522        }
 523
 524        /* Memory clock */
 525        switch (device_id) {
 526        case PCI_DEVICE_ID_SMI_710 :
 527                smiWrite (SMI_INDX_C4, 0x6a, 0x75);
 528                break;
 529        case PCI_DEVICE_ID_SMI_712 :
 530                smiWrite (SMI_INDX_C4, 0x6a, 0x80);
 531                break;
 532        default :
 533                smiWrite (SMI_INDX_C4, 0x6a, 0x53);
 534                break;
 535        }
 536        smiWrite (SMI_INDX_C4, 0x6b, 0x15);
 537
 538        /* VCLK */
 539        freq = 1000000000000LL / var -> pixclock;
 540
 541        FindPQ ((unsigned int)freq, &p, &q);
 542
 543        smiWrite (SMI_INDX_C4, 0x6c, p);
 544        smiWrite (SMI_INDX_C4, 0x6d, q);
 545
 546}
 547
 548/*******************************************************************************
 549 *
 550 * Init video chip with common Linux graphic modes (lilo)
 551 */
 552void *video_hw_init (void)
 553{
 554        GraphicDevice *pGD = (GraphicDevice *)&smi;
 555        unsigned short device_id;
 556        pci_dev_t devbusfn;
 557        int videomode;
 558        unsigned long t1, hsynch, vsynch;
 559        unsigned int pci_mem_base, *vm;
 560        char *penv;
 561        int tmp, i, bits_per_pixel;
 562        struct ctfb_res_modes *res_mode;
 563        struct ctfb_res_modes var_mode;
 564        unsigned char videoout;
 565
 566        /* Search for video chip */
 567        printf("Video: ");
 568
 569        if ((devbusfn = pci_find_devices(supported, 0)) < 0)
 570        {
 571                printf ("Controller not found !\n");
 572                return (NULL);
 573        }
 574
 575        /* PCI setup */
 576        pci_write_config_dword (devbusfn, PCI_COMMAND, (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
 577        pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
 578        pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
 579        pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
 580
 581        tmp = 0;
 582
 583        videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE;
 584        /* get video mode via environment */
 585        if ((penv = getenv ("videomode")) != NULL) {
 586                /* deceide if it is a string */
 587                if (penv[0] <= '9') {
 588                        videomode = (int) simple_strtoul (penv, NULL, 16);
 589                        tmp = 1;
 590                }
 591        } else {
 592                tmp = 1;
 593        }
 594        if (tmp) {
 595                /* parameter are vesa modes */
 596                /* search params */
 597                for (i = 0; i < VESA_MODES_COUNT; i++) {
 598                        if (vesa_modes[i].vesanr == videomode)
 599                                break;
 600                }
 601                if (i == VESA_MODES_COUNT) {
 602                        printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE);
 603                        i = 0;
 604                }
 605                res_mode =
 606                        (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
 607                                                                 resindex];
 608                bits_per_pixel = vesa_modes[i].bits_per_pixel;
 609        } else {
 610
 611                res_mode = (struct ctfb_res_modes *) &var_mode;
 612                bits_per_pixel = video_get_params (res_mode, penv);
 613        }
 614
 615        /* calculate hsynch and vsynch freq (info only) */
 616        t1 = (res_mode->left_margin + res_mode->xres +
 617              res_mode->right_margin + res_mode->hsync_len) / 8;
 618        t1 *= 8;
 619        t1 *= res_mode->pixclock;
 620        t1 /= 1000;
 621        hsynch = 1000000000L / t1;
 622        t1 *=
 623                (res_mode->upper_margin + res_mode->yres +
 624                 res_mode->lower_margin + res_mode->vsync_len);
 625        t1 /= 1000;
 626        vsynch = 1000000000L / t1;
 627
 628        /* fill in Graphic device struct */
 629        sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
 630                 res_mode->yres, bits_per_pixel, (hsynch / 1000),
 631                 (vsynch / 1000));
 632        printf ("%s\n", pGD->modeIdent);
 633        pGD->winSizeX = res_mode->xres;
 634        pGD->winSizeY = res_mode->yres;
 635        pGD->plnSizeX = res_mode->xres;
 636        pGD->plnSizeY = res_mode->yres;
 637        switch (bits_per_pixel) {
 638        case 8:
 639                pGD->gdfBytesPP = 1;
 640                pGD->gdfIndex = GDF__8BIT_INDEX;
 641                break;
 642        case 15:
 643                pGD->gdfBytesPP = 2;
 644                pGD->gdfIndex = GDF_15BIT_555RGB;
 645                break;
 646        case 16:
 647                pGD->gdfBytesPP = 2;
 648                pGD->gdfIndex = GDF_16BIT_565RGB;
 649                break;
 650        case 24:
 651                pGD->gdfBytesPP = 3;
 652                pGD->gdfIndex = GDF_24BIT_888RGB;
 653                break;
 654        }
 655
 656        pGD->isaBase = CONFIG_SYS_ISA_IO;
 657        pGD->pciBase = pci_mem_base;
 658        pGD->dprBase = (pci_mem_base + 0x400000 + 0x8000);
 659        pGD->vprBase = (pci_mem_base + 0x400000 + 0xc000);
 660        pGD->cprBase = (pci_mem_base + 0x400000 + 0xe000);
 661        pGD->frameAdrs = pci_mem_base;
 662        pGD->memSize = VIDEO_MEM_SIZE;
 663
 664        /* Set up hardware : select color mode,
 665           set Register base to isa 3dx for 3?x regs*/
 666        out8 (SMI_MISC_REG, 0x01);
 667
 668        /* Turn off display */
 669        smiWrite (SMI_INDX_C4, 0x01, 0x20);
 670
 671        /* Unlock ext. crt regs */
 672        out8 (SMI_LOCK_REG, 0x40);
 673
 674        /* Unlock crt regs 0-7 */
 675        smiWrite (SMI_INDX_D4, 0x11, 0x0e);
 676
 677        /* Sytem Control Register */
 678        smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SCR, sizeof(SMI_SCR));
 679
 680        /* extented CRT Register */
 681        smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, SMI_EXT_CRT, sizeof(SMI_EXT_CRT));
 682
 683        /* Attributes controller registers */
 684        smiLoadRegs (SMI_INDX_ATTR, SMI_INDX_ATTR, SMI_ATTR, sizeof(SMI_ATTR));
 685
 686        /* Graphics Controller Register */
 687        smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF, SMI_GCR, sizeof(SMI_GCR));
 688
 689        /* Sequencer Register */
 690        smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SEQR, sizeof(SMI_SEQR));
 691
 692        /* Power Control Register */
 693        smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_PCR, sizeof(SMI_PCR));
 694
 695        /* Memory Control Register */
 696        /* Register MSR62 is a power on configurable register. We don't */
 697        /* modify it */
 698        smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_MCR, sizeof(SMI_MCR));
 699
 700        /* Set misc output register */
 701        smiLoadMsr (res_mode);
 702
 703        /* Set CRT and Clock control registers */
 704        smiLoadCrt (res_mode, bits_per_pixel);
 705
 706        smiLoadCcr (res_mode, device_id);
 707
 708        /* Hardware Cusor Register */
 709        smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_HCR, sizeof(SMI_HCR));
 710
 711        /* Enable  Display  */
 712        videoout = 2;       /* Default output is CRT */
 713        if ((penv = getenv ("videoout")) != NULL) {
 714                /* deceide if it is a string */
 715                videoout = (int) simple_strtoul (penv, NULL, 16);
 716        }
 717        smiWrite (SMI_INDX_C4, 0x31, videoout);
 718
 719        /* Video processor default setup */
 720        smiInitVideoProcessor ();
 721
 722        /* Capture port default setup */
 723        smiInitCapturePort ();
 724
 725        /* Drawing engine default setup */
 726        smiInitDrawingEngine ();
 727
 728        /* Turn on display */
 729        smiWrite (0x3c4, 0x01, 0x01);
 730
 731        /* Clear video memory */
 732        i = pGD->memSize/4;
 733        vm = (unsigned int *)pGD->pciBase;
 734        while(i--)
 735                *vm++ = 0;
 736        return ((void*)&smi);
 737}
 738
 739/*******************************************************************************
 740 *
 741 * Drawing engine fill on screen region
 742 */
 743void video_hw_rectfill (
 744        unsigned int bpp,             /* bytes per pixel */
 745        unsigned int dst_x,           /* dest pos x */
 746        unsigned int dst_y,           /* dest pos y */
 747        unsigned int dim_x,           /* frame width */
 748        unsigned int dim_y,           /* frame height */
 749        unsigned int color            /* fill color */
 750        )
 751{
 752        register GraphicDevice *pGD = (GraphicDevice *)&smi;
 753        register unsigned int control;
 754
 755        dim_x *= bpp;
 756
 757        out32r ((pGD->dprBase + 0x0014), color);
 758        out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
 759        out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
 760
 761        control = 0x0000ffff &  in32r ((pGD->dprBase + 0x000c));
 762
 763        control |= 0x80010000;
 764
 765        out32r ((pGD->dprBase + 0x000c),  control);
 766
 767        /* Wait for drawing processor */
 768        do
 769        {
 770                out8 ((pGD->isaBase + 0x3c4), 0x16);
 771        } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
 772}
 773
 774/*******************************************************************************
 775 *
 776 * Drawing engine bitblt with screen region
 777 */
 778void video_hw_bitblt (
 779        unsigned int bpp,             /* bytes per pixel */
 780        unsigned int src_x,           /* source pos x */
 781        unsigned int src_y,           /* source pos y */
 782        unsigned int dst_x,           /* dest pos x */
 783        unsigned int dst_y,           /* dest pos y */
 784        unsigned int dim_x,           /* frame width */
 785        unsigned int dim_y            /* frame height */
 786        )
 787{
 788        register GraphicDevice *pGD = (GraphicDevice *)&smi;
 789        register unsigned int control;
 790
 791        dim_x *= bpp;
 792
 793        if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x)))
 794        {
 795                out32r ((pGD->dprBase + 0x0000), (((src_x+dim_x-1)<<16) | (src_y+dim_y-1)));
 796                out32r ((pGD->dprBase + 0x0004), (((dst_x+dim_x-1)<<16) | (dst_y+dim_y-1)));
 797                control = 0x88000000;
 798        } else {
 799                out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y));
 800                out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
 801                control = 0x80000000;
 802        }
 803
 804        out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
 805        control |= (0x0000ffff &  in32r ((pGD->dprBase + 0x000c)));
 806        out32r ((pGD->dprBase + 0x000c), control);
 807
 808        /* Wait for drawing processor */
 809        do
 810        {
 811                out8 ((pGD->isaBase + 0x3c4), 0x16);
 812        } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
 813}
 814
 815/*******************************************************************************
 816 *
 817 * Set a RGB color in the LUT (8 bit index)
 818 */
 819void video_set_lut (
 820        unsigned int index,           /* color number */
 821        unsigned char r,              /* red */
 822        unsigned char g,              /* green */
 823        unsigned char b               /* blue */
 824        )
 825{
 826        register GraphicDevice *pGD = (GraphicDevice *)&smi;
 827
 828        out8 (SMI_LUT_MASK,  0xff);
 829
 830        out8 (SMI_LUT_START, (char)index);
 831
 832        out8 (SMI_LUT_RGB, r>>2);    /* red */
 833        udelay (10);
 834        out8 (SMI_LUT_RGB, g>>2);    /* green */
 835        udelay (10);
 836        out8 (SMI_LUT_RGB, b>>2);    /* blue */
 837        udelay (10);
 838}
 839