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