linux-old/drivers/video/matrox/matroxfb_DAC1064.c
<<
>>
Prefs
   1/*
   2 *
   3 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
   4 *
   5 * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
   6 *
   7 * Portions Copyright (c) 2001 Matrox Graphics Inc.
   8 *
   9 * Version: 1.64 2002/06/10
  10 *
  11 * See matroxfb_base.c for contributors.
  12 *
  13 */
  14
  15/* make checkconfig does not walk through include tree :-( */
  16#include <linux/config.h>
  17
  18#include "matroxfb_DAC1064.h"
  19#include "matroxfb_misc.h"
  20#include "matroxfb_accel.h"
  21#include "g450_pll.h"
  22#include <linux/matroxfb.h>
  23
  24#ifdef NEED_DAC1064
  25#define outDAC1064 matroxfb_DAC_out
  26#define inDAC1064 matroxfb_DAC_in
  27
  28#define DAC1064_OPT_SCLK_PCI    0x00
  29#define DAC1064_OPT_SCLK_PLL    0x01
  30#define DAC1064_OPT_SCLK_EXT    0x02
  31#define DAC1064_OPT_SCLK_MASK   0x03
  32#define DAC1064_OPT_GDIV1       0x04    /* maybe it is GDIV2 on G100 ?! */
  33#define DAC1064_OPT_GDIV3       0x00
  34#define DAC1064_OPT_MDIV1       0x08
  35#define DAC1064_OPT_MDIV2       0x00
  36#define DAC1064_OPT_RESERVED    0x10
  37
  38static void matroxfb_DAC1064_flashcursor(unsigned long ptr) {
  39        unsigned long flags;
  40
  41#define minfo ((struct matrox_fb_info*)ptr)
  42        matroxfb_DAC_lock_irqsave(flags);
  43        outDAC1064(PMINFO M1064_XCURCTRL, inDAC1064(PMINFO M1064_XCURCTRL) ^ M1064_XCURCTRL_DIS ^ M1064_XCURCTRL_XGA);
  44        ACCESS_FBINFO(cursor.timer.expires) = jiffies + HZ/2;
  45        add_timer(&ACCESS_FBINFO(cursor.timer));
  46        matroxfb_DAC_unlock_irqrestore(flags);
  47#undef minfo
  48}
  49
  50static void matroxfb_DAC1064_createcursor(WPMINFO struct display* p) {
  51        vaddr_t cursorbase;
  52        u_int32_t xline;
  53        unsigned int i;
  54        unsigned int h, to;
  55        CRITFLAGS
  56
  57        if (ACCESS_FBINFO(currcon_display) != p)
  58                return;
  59
  60        matroxfb_createcursorshape(PMINFO p, p->var.vmode);
  61
  62        xline = (~0) << (32 - ACCESS_FBINFO(cursor.w));
  63        cursorbase = ACCESS_FBINFO(video.vbase);
  64        h = ACCESS_FBINFO(features.DAC1064.cursorimage);
  65
  66        CRITBEGIN
  67
  68#ifdef __BIG_ENDIAN
  69        WaitTillIdle();
  70        mga_outl(M_OPMODE, M_OPMODE_32BPP);
  71#endif
  72        to = ACCESS_FBINFO(cursor.u);
  73        for (i = 0; i < to; i++) {
  74                mga_writel(cursorbase, h, 0);
  75                mga_writel(cursorbase, h+4, 0);
  76                mga_writel(cursorbase, h+8, ~0);
  77                mga_writel(cursorbase, h+12, ~0);
  78                h += 16;
  79        }
  80        to = ACCESS_FBINFO(cursor.d);
  81        for (; i < to; i++) {
  82                mga_writel(cursorbase, h, 0);
  83                mga_writel(cursorbase, h+4, xline);
  84                mga_writel(cursorbase, h+8, ~0);
  85                mga_writel(cursorbase, h+12, ~0);
  86                h += 16;
  87        }
  88        for (; i < 64; i++) {
  89                mga_writel(cursorbase, h, 0);
  90                mga_writel(cursorbase, h+4, 0);
  91                mga_writel(cursorbase, h+8, ~0);
  92                mga_writel(cursorbase, h+12, ~0);
  93                h += 16;
  94        }
  95#ifdef __BIG_ENDIAN
  96        mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
  97#endif
  98
  99        CRITEND
 100}
 101
 102static void matroxfb_DAC1064_cursor(struct display* p, int mode, int x, int y) {
 103        unsigned long flags;
 104        MINFO_FROM_DISP(p);
 105
 106        if (ACCESS_FBINFO(currcon_display) != p)
 107                return;
 108
 109        if (mode == CM_ERASE) {
 110                if (ACCESS_FBINFO(cursor.state) != CM_ERASE) {
 111                        del_timer_sync(&ACCESS_FBINFO(cursor.timer));
 112                        matroxfb_DAC_lock_irqsave(flags);
 113                        ACCESS_FBINFO(cursor.state) = CM_ERASE;
 114                        outDAC1064(PMINFO M1064_XCURCTRL, M1064_XCURCTRL_DIS);
 115                        matroxfb_DAC_unlock_irqrestore(flags);
 116                }
 117                return;
 118        }
 119        if ((p->conp->vc_cursor_type & CUR_HWMASK) != ACCESS_FBINFO(cursor.type))
 120                matroxfb_DAC1064_createcursor(PMINFO p);
 121        x *= fontwidth(p);
 122        y *= fontheight(p);
 123        y -= p->var.yoffset;
 124        if (p->var.vmode & FB_VMODE_DOUBLE)
 125                y *= 2;
 126        del_timer_sync(&ACCESS_FBINFO(cursor.timer));
 127        matroxfb_DAC_lock_irqsave(flags);
 128        if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y)) || ACCESS_FBINFO(cursor.redraw)) {
 129                ACCESS_FBINFO(cursor.redraw) = 0;
 130                ACCESS_FBINFO(cursor.x) = x;
 131                ACCESS_FBINFO(cursor.y) = y;
 132                x += 64;
 133                y += 64;
 134                outDAC1064(PMINFO M1064_XCURCTRL, M1064_XCURCTRL_DIS);
 135                mga_outb(M_RAMDAC_BASE+M1064_CURPOSXL, x);
 136                mga_outb(M_RAMDAC_BASE+M1064_CURPOSXH, x >> 8);
 137                mga_outb(M_RAMDAC_BASE+M1064_CURPOSYL, y);
 138                mga_outb(M_RAMDAC_BASE+M1064_CURPOSYH, y >> 8);
 139        }
 140        ACCESS_FBINFO(cursor.state) = CM_DRAW;
 141        if (ACCESS_FBINFO(devflags.blink))
 142                mod_timer(&ACCESS_FBINFO(cursor.timer), jiffies + HZ/2);
 143        outDAC1064(PMINFO M1064_XCURCTRL, M1064_XCURCTRL_XGA);
 144        matroxfb_DAC_unlock_irqrestore(flags);
 145}
 146
 147static int matroxfb_DAC1064_setfont(struct display* p, int width, int height) {
 148        if (p && p->conp)
 149                matroxfb_DAC1064_createcursor(PMXINFO(p) p);
 150        return 0;
 151}
 152
 153static int DAC1064_selhwcursor(WPMINFO struct display* p) {
 154        ACCESS_FBINFO(dispsw.cursor) = matroxfb_DAC1064_cursor;
 155        ACCESS_FBINFO(dispsw.set_font) = matroxfb_DAC1064_setfont;
 156        return 0;
 157}
 158
 159static void DAC1064_calcclock(CPMINFO unsigned int freq, unsigned int fmax, unsigned int* in, unsigned int* feed, unsigned int* post) {
 160        unsigned int fvco;
 161        unsigned int p;
 162
 163        DBG("DAC1064_calcclock")
 164        
 165        /* only for devices older than G450 */
 166
 167        fvco = PLL_calcclock(PMINFO freq, fmax, in, feed, &p);
 168        
 169        p = (1 << p) - 1;
 170        if (fvco <= 100000)
 171                ;
 172        else if (fvco <= 140000)
 173                p |= 0x08;
 174        else if (fvco <= 180000)
 175                p |= 0x10;
 176        else
 177                p |= 0x18;
 178        *post = p;
 179}
 180
 181/* they must be in POS order */
 182static const unsigned char MGA1064_DAC_regs[] = {
 183                M1064_XCURADDL, M1064_XCURADDH, M1064_XCURCTRL,
 184                M1064_XCURCOL0RED, M1064_XCURCOL0GREEN, M1064_XCURCOL0BLUE,
 185                M1064_XCURCOL1RED, M1064_XCURCOL1GREEN, M1064_XCURCOL1BLUE,
 186                M1064_XCURCOL2RED, M1064_XCURCOL2GREEN, M1064_XCURCOL2BLUE,
 187                DAC1064_XVREFCTRL, M1064_XMULCTRL, M1064_XPIXCLKCTRL, M1064_XGENCTRL,
 188                M1064_XMISCCTRL,
 189                M1064_XGENIOCTRL, M1064_XGENIODATA, M1064_XZOOMCTRL, M1064_XSENSETEST,
 190                M1064_XCRCBITSEL,
 191                M1064_XCOLKEYMASKL, M1064_XCOLKEYMASKH, M1064_XCOLKEYL, M1064_XCOLKEYH };
 192
 193static const unsigned char MGA1064_DAC[] = {
 194                0x00, 0x00, M1064_XCURCTRL_DIS,
 195                0x00, 0x00, 0x00,       /* black */
 196                0xFF, 0xFF, 0xFF,       /* white */
 197                0xFF, 0x00, 0x00,       /* red */
 198                0x00, 0,
 199                M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL,
 200                M1064_XGENCTRL_VS_0 | M1064_XGENCTRL_ALPHA_DIS | M1064_XGENCTRL_BLACK_0IRE | M1064_XGENCTRL_NO_SYNC_ON_GREEN,
 201                M1064_XMISCCTRL_DAC_8BIT,
 202                0x00, 0x00, M1064_XZOOMCTRL_1, M1064_XSENSETEST_BCOMP | M1064_XSENSETEST_GCOMP | M1064_XSENSETEST_RCOMP | M1064_XSENSETEST_PDOWN,
 203                0x00,
 204                0x00, 0x00, 0xFF, 0xFF};
 205
 206static void DAC1064_setpclk(WPMINFO unsigned long fout) {
 207        unsigned int m, n, p;
 208
 209        DBG("DAC1064_setpclk")
 210
 211        DAC1064_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p);
 212        ACCESS_FBINFO(hw).DACclk[0] = m;
 213        ACCESS_FBINFO(hw).DACclk[1] = n;
 214        ACCESS_FBINFO(hw).DACclk[2] = p;
 215}
 216
 217static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) {
 218        u_int32_t mx;
 219        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 220
 221        DBG("DAC1064_setmclk")
 222
 223        if (ACCESS_FBINFO(devflags.noinit)) {
 224                /* read MCLK and give up... */
 225                hw->DACclk[3] = inDAC1064(PMINFO DAC1064_XSYSPLLM);
 226                hw->DACclk[4] = inDAC1064(PMINFO DAC1064_XSYSPLLN);
 227                hw->DACclk[5] = inDAC1064(PMINFO DAC1064_XSYSPLLP);
 228                return;
 229        }
 230        mx = hw->MXoptionReg | 0x00000004;
 231        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx);
 232        mx &= ~0x000000BB;
 233        if (oscinfo & DAC1064_OPT_GDIV1)
 234                mx |= 0x00000008;
 235        if (oscinfo & DAC1064_OPT_MDIV1)
 236                mx |= 0x00000010;
 237        if (oscinfo & DAC1064_OPT_RESERVED)
 238                mx |= 0x00000080;
 239        if ((oscinfo & DAC1064_OPT_SCLK_MASK) == DAC1064_OPT_SCLK_PLL) {
 240                /* select PCI clock until we have setup oscilator... */
 241                int clk;
 242                unsigned int m, n, p;
 243
 244                /* powerup system PLL, select PCI clock */
 245                mx |= 0x00000020;
 246                pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx);
 247                mx &= ~0x00000004;
 248                pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx);
 249
 250                /* !!! you must not access device if MCLK is not running !!!
 251                   Doing so cause immediate PCI lockup :-( Maybe they should
 252                   generate ABORT or I/O (parity...) error and Linux should
 253                   recover from this... (kill driver/process). But world is not
 254                   perfect... */
 255                /* (bit 2 of PCI_OPTION_REG must be 0... and bits 0,1 must not
 256                   select PLL... because of PLL can be stopped at this time) */
 257                DAC1064_calcclock(PMINFO fmem, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p);
 258                outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3] = m);
 259                outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4] = n);
 260                outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5] = p);
 261                for (clk = 65536; clk; --clk) {
 262                        if (inDAC1064(PMINFO DAC1064_XSYSPLLSTAT) & 0x40)
 263                                break;
 264                }
 265                if (!clk)
 266                        printk(KERN_ERR "matroxfb: aiee, SYSPLL not locked\n");
 267                /* select PLL */
 268                mx |= 0x00000005;
 269        } else {
 270                /* select specified system clock source */
 271                mx |= oscinfo & DAC1064_OPT_SCLK_MASK;
 272        }
 273        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx);
 274        mx &= ~0x00000004;
 275        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx);
 276        hw->MXoptionReg = mx;
 277}
 278
 279#ifdef CONFIG_FB_MATROX_G450
 280static void g450_set_plls(WPMINFO2) {
 281        u_int32_t c2_ctl;
 282        unsigned int pxc;
 283        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 284        int pixelmnp;
 285        int videomnp;
 286        
 287        c2_ctl = hw->crtc2.ctl & ~0x4007;       /* Clear PLL + enable for CRTC2 */
 288        c2_ctl |= 0x0001;                       /* Enable CRTC2 */
 289        hw->DACreg[POS1064_XPWRCTRL] &= ~0x02;  /* Stop VIDEO PLL */
 290        pixelmnp = ACCESS_FBINFO(crtc1).mnp;
 291        videomnp = ACCESS_FBINFO(crtc2).mnp;
 292        if (videomnp < 0) {
 293                c2_ctl &= ~0x0001;                      /* Disable CRTC2 */
 294                hw->DACreg[POS1064_XPWRCTRL] &= ~0x10;  /* Powerdown CRTC2 */
 295        } else if (ACCESS_FBINFO(crtc2).pixclock == ACCESS_FBINFO(features).pll.ref_freq) {
 296                c2_ctl |=  0x4002;      /* Use reference directly */
 297        } else if (videomnp == pixelmnp) {
 298                c2_ctl |=  0x0004;      /* Use pixel PLL */
 299        } else {
 300                if (0 == ((videomnp ^ pixelmnp) & 0xFFFFFF00)) {
 301                        /* PIXEL and VIDEO PLL must not use same frequency. We modify N
 302                           of PIXEL PLL in such case because of VIDEO PLL may be source
 303                           of TVO clocks, and chroma subcarrier is derived from its
 304                           pixel clocks */
 305                        pixelmnp += 0x000100;
 306                }
 307                c2_ctl |=  0x0006;      /* Use video PLL */
 308                hw->DACreg[POS1064_XPWRCTRL] |= 0x02;
 309                
 310                outDAC1064(PMINFO M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
 311                matroxfb_g450_setpll_cond(PMINFO videomnp, M_VIDEO_PLL);
 312        }
 313
 314        hw->DACreg[POS1064_XPIXCLKCTRL] &= ~M1064_XPIXCLKCTRL_PLL_UP;
 315        if (pixelmnp >= 0) {
 316                hw->DACreg[POS1064_XPIXCLKCTRL] |= M1064_XPIXCLKCTRL_PLL_UP;
 317                
 318                outDAC1064(PMINFO M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
 319                matroxfb_g450_setpll_cond(PMINFO pixelmnp, M_PIXEL_PLL_C);
 320        }
 321        if (c2_ctl != hw->crtc2.ctl) {
 322                hw->crtc2.ctl = c2_ctl;
 323                mga_outl(0x3C10, c2_ctl);
 324        }
 325
 326        pxc = ACCESS_FBINFO(crtc1).pixclock;
 327        if (pxc == 0 || ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC2) {
 328                pxc = ACCESS_FBINFO(crtc2).pixclock;
 329        }
 330        if (ACCESS_FBINFO(chip) == MGA_G550) {
 331                if (pxc < 45000) {
 332                        hw->DACreg[POS1064_XPANMODE] = 0x00;    /* 0-50 */
 333                } else if (pxc < 55000) {
 334                        hw->DACreg[POS1064_XPANMODE] = 0x08;    /* 34-62 */
 335                } else if (pxc < 70000) {
 336                        hw->DACreg[POS1064_XPANMODE] = 0x10;    /* 42-78 */
 337                } else if (pxc < 85000) {
 338                        hw->DACreg[POS1064_XPANMODE] = 0x18;    /* 62-92 */
 339                } else if (pxc < 100000) {
 340                        hw->DACreg[POS1064_XPANMODE] = 0x20;    /* 74-108 */
 341                } else if (pxc < 115000) {
 342                        hw->DACreg[POS1064_XPANMODE] = 0x28;    /* 94-122 */
 343                } else if (pxc < 125000) {
 344                        hw->DACreg[POS1064_XPANMODE] = 0x30;    /* 108-132 */
 345                } else {
 346                        hw->DACreg[POS1064_XPANMODE] = 0x38;    /* 120-168 */
 347                }
 348        } else {
 349                /* G450 */
 350                if (pxc < 45000) {
 351                        hw->DACreg[POS1064_XPANMODE] = 0x00;    /* 0-54 */
 352                } else if (pxc < 65000) {
 353                        hw->DACreg[POS1064_XPANMODE] = 0x08;    /* 38-70 */
 354                } else if (pxc < 85000) {
 355                        hw->DACreg[POS1064_XPANMODE] = 0x10;    /* 56-96 */
 356                } else if (pxc < 105000) {
 357                        hw->DACreg[POS1064_XPANMODE] = 0x18;    /* 80-114 */
 358                } else if (pxc < 135000) {
 359                        hw->DACreg[POS1064_XPANMODE] = 0x20;    /* 102-144 */
 360                } else if (pxc < 160000) {
 361                        hw->DACreg[POS1064_XPANMODE] = 0x28;    /* 132-166 */
 362                } else if (pxc < 175000) {
 363                        hw->DACreg[POS1064_XPANMODE] = 0x30;    /* 154-182 */
 364                } else {
 365                        hw->DACreg[POS1064_XPANMODE] = 0x38;    /* 170-204 */
 366                }
 367        }
 368}
 369#endif
 370
 371void DAC1064_global_init(WPMINFO2) {
 372        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 373
 374        hw->DACreg[POS1064_XMISCCTRL] &= M1064_XMISCCTRL_DAC_WIDTHMASK;
 375        hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN;
 376        hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL;
 377#ifdef CONFIG_FB_MATROX_G450
 378        if (ACCESS_FBINFO(devflags.g450dac)) {
 379                hw->DACreg[POS1064_XPWRCTRL] = 0x1F;    /* powerup everything */
 380                hw->DACreg[POS1064_XOUTPUTCONN] = 0x00; /* disable outputs */
 381                hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
 382                switch (ACCESS_FBINFO(outputs[0]).src) {
 383                        case MATROXFB_SRC_CRTC1:
 384                        case MATROXFB_SRC_CRTC2:
 385                                hw->DACreg[POS1064_XOUTPUTCONN] |= 0x01;        /* enable output; CRTC1/2 selection is in CRTC2 ctl */
 386                                break;
 387                        case MATROXFB_SRC_NONE:
 388                                hw->DACreg[POS1064_XMISCCTRL] &= ~M1064_XMISCCTRL_DAC_EN;
 389                                break;
 390                }
 391                switch (ACCESS_FBINFO(outputs[1]).src) {
 392                        case MATROXFB_SRC_CRTC1:
 393                                hw->DACreg[POS1064_XOUTPUTCONN] |= 0x04;
 394                                break;
 395                        case MATROXFB_SRC_CRTC2:
 396                                if (ACCESS_FBINFO(outputs[1]).mode == MATROXFB_OUTPUT_MODE_MONITOR) {
 397                                        hw->DACreg[POS1064_XOUTPUTCONN] |= 0x08;
 398                                } else {
 399                                        hw->DACreg[POS1064_XOUTPUTCONN] |= 0x0C;
 400                                }
 401                                break;
 402                        case MATROXFB_SRC_NONE:
 403                                hw->DACreg[POS1064_XPWRCTRL] &= ~0x01;          /* Poweroff DAC2 */
 404                                break;
 405                }
 406                switch (ACCESS_FBINFO(outputs[2]).src) {
 407                        case MATROXFB_SRC_CRTC1:
 408                                hw->DACreg[POS1064_XOUTPUTCONN] |= 0x20;
 409                                break;
 410                        case MATROXFB_SRC_CRTC2:
 411                                hw->DACreg[POS1064_XOUTPUTCONN] |= 0x40;
 412                                break;
 413                        case MATROXFB_SRC_NONE:
 414#if 0
 415                                /* HELP! If we boot without DFP connected to DVI, we can
 416                                   poweroff TMDS. But if we boot with DFP connected,
 417                                   TMDS generated clocks are used instead of ALL pixclocks
 418                                   available... If someone knows which register
 419                                   handles it, please reveal this secret to me... */                    
 420                                hw->DACreg[POS1064_XPWRCTRL] &= ~0x04;          /* Poweroff TMDS */
 421#endif                          
 422                                break;
 423                }
 424                /* Now set timming related variables... */
 425                g450_set_plls(PMINFO2);
 426        } else
 427#endif
 428        {
 429                if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC1) {
 430                        hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_EXT;
 431                        hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12;
 432                } else if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) {
 433                        hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12;
 434                } else if (ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1)
 435                        hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12;
 436                else
 437                        hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS;
 438
 439                if (ACCESS_FBINFO(outputs[0]).src != MATROXFB_SRC_NONE)
 440                        hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
 441        }
 442}
 443
 444void DAC1064_global_restore(WPMINFO2) {
 445        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 446
 447        outDAC1064(PMINFO M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
 448        outDAC1064(PMINFO M1064_XMISCCTRL, hw->DACreg[POS1064_XMISCCTRL]);
 449        if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) {
 450                outDAC1064(PMINFO 0x20, 0x04);
 451                outDAC1064(PMINFO 0x1F, ACCESS_FBINFO(devflags.dfp_type));
 452                if (ACCESS_FBINFO(devflags.g450dac)) {
 453                        outDAC1064(PMINFO M1064_XSYNCCTRL, 0xCC);
 454                        outDAC1064(PMINFO M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
 455                        outDAC1064(PMINFO M1064_XPANMODE, hw->DACreg[POS1064_XPANMODE]);
 456                        outDAC1064(PMINFO M1064_XOUTPUTCONN, hw->DACreg[POS1064_XOUTPUTCONN]);
 457                }
 458        }
 459}
 460
 461static int DAC1064_init_1(WPMINFO struct my_timming* m, struct display *p) {
 462        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 463
 464        DBG("DAC1064_init_1")
 465
 466        memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
 467        if (p->type == FB_TYPE_TEXT) {
 468                hw->DACreg[POS1064_XMISCCTRL] = M1064_XMISCCTRL_DAC_6BIT;
 469                hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP
 470                                             | M1064_XMULCTRL_GRAPHICS_PALETIZED;
 471        } else {
 472                switch (p->var.bits_per_pixel) {
 473                /* case 4: not supported by MGA1064 DAC */
 474                case 8:
 475                        hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
 476                        break;
 477                case 16:
 478                        if (p->var.green.length == 5)
 479                                hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_15BPP_1BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
 480                        else
 481                                hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_16BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
 482                        break;
 483                case 24:
 484                        hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_24BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
 485                        break;
 486                case 32:
 487                        hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_32BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
 488                        break;
 489                default:
 490                        return 1;       /* unsupported depth */
 491                }
 492        }
 493        hw->DACreg[POS1064_XVREFCTRL] = ACCESS_FBINFO(features.DAC1064.xvrefctrl);
 494        hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK;
 495        hw->DACreg[POS1064_XGENCTRL] |= (m->sync & FB_SYNC_ON_GREEN)?M1064_XGENCTRL_SYNC_ON_GREEN:M1064_XGENCTRL_NO_SYNC_ON_GREEN;
 496        hw->DACreg[POS1064_XCURADDL] = ACCESS_FBINFO(features.DAC1064.cursorimage) >> 10;
 497        hw->DACreg[POS1064_XCURADDH] = ACCESS_FBINFO(features.DAC1064.cursorimage) >> 18;
 498
 499        DAC1064_global_init(PMINFO2);
 500        return 0;
 501}
 502
 503static int DAC1064_init_2(WPMINFO struct my_timming* m, struct display* p) {
 504        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 505
 506        DBG("DAC1064_init_2")
 507
 508        if (p->var.bits_per_pixel > 16) {       /* 256 entries */
 509                int i;
 510
 511                for (i = 0; i < 256; i++) {
 512                        hw->DACpal[i * 3 + 0] = i;
 513                        hw->DACpal[i * 3 + 1] = i;
 514                        hw->DACpal[i * 3 + 2] = i;
 515                }
 516        } else if (p->var.bits_per_pixel > 8) {
 517                if (p->var.green.length == 5) { /* 0..31, 128..159 */
 518                        int i;
 519
 520                        for (i = 0; i < 32; i++) {
 521                                /* with p15 == 0 */
 522                                hw->DACpal[i * 3 + 0] = i << 3;
 523                                hw->DACpal[i * 3 + 1] = i << 3;
 524                                hw->DACpal[i * 3 + 2] = i << 3;
 525                                /* with p15 == 1 */
 526                                hw->DACpal[(i + 128) * 3 + 0] = i << 3;
 527                                hw->DACpal[(i + 128) * 3 + 1] = i << 3;
 528                                hw->DACpal[(i + 128) * 3 + 2] = i << 3;
 529                        }
 530                } else {
 531                        int i;
 532
 533                        for (i = 0; i < 64; i++) {              /* 0..63 */
 534                                hw->DACpal[i * 3 + 0] = i << 3;
 535                                hw->DACpal[i * 3 + 1] = i << 2;
 536                                hw->DACpal[i * 3 + 2] = i << 3;
 537                        }
 538                }
 539        } else {
 540                memset(hw->DACpal, 0, 768);
 541        }
 542        return 0;
 543}
 544
 545static void DAC1064_restore_1(WPMINFO2) {
 546        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 547
 548        CRITFLAGS
 549
 550        DBG("DAC1064_restore_1")
 551
 552        CRITBEGIN
 553
 554        if ((inDAC1064(PMINFO DAC1064_XSYSPLLM) != hw->DACclk[3]) ||
 555            (inDAC1064(PMINFO DAC1064_XSYSPLLN) != hw->DACclk[4]) ||
 556            (inDAC1064(PMINFO DAC1064_XSYSPLLP) != hw->DACclk[5])) {
 557                outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3]);
 558                outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4]);
 559                outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5]);
 560        }
 561        {
 562                unsigned int i;
 563
 564                for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
 565                        if ((i != POS1064_XPIXCLKCTRL) && (i != POS1064_XMISCCTRL))
 566                                outDAC1064(PMINFO MGA1064_DAC_regs[i], hw->DACreg[i]);
 567                }
 568        }
 569
 570        DAC1064_global_restore(PMINFO2);
 571
 572        CRITEND
 573};
 574
 575static void DAC1064_restore_2(WPMINFO struct display* p) {
 576#ifdef DEBUG
 577        unsigned int i;
 578#endif
 579
 580        DBG("DAC1064_restore_2")
 581
 582        matrox_init_putc(PMINFO p, matroxfb_DAC1064_createcursor);
 583#ifdef DEBUG
 584        dprintk(KERN_DEBUG "DAC1064regs ");
 585        for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
 586                dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], ACCESS_FBINFO(hw).DACreg[i]);
 587                if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... ");
 588        }
 589        dprintk("\n" KERN_DEBUG "DAC1064clk ");
 590        for (i = 0; i < 6; i++)
 591                dprintk("C%02X=%02X ", i, ACCESS_FBINFO(hw).DACclk[i]);
 592        dprintk("\n");
 593#endif
 594}
 595
 596static int m1064_compute(void* out, struct my_timming* m) {
 597#define minfo ((struct matrox_fb_info*)out)
 598        {
 599                int i;
 600                int tmout;
 601                CRITFLAGS
 602
 603                DAC1064_setpclk(PMINFO m->pixclock);
 604
 605                CRITBEGIN
 606
 607                for (i = 0; i < 3; i++)
 608                        outDAC1064(PMINFO M1064_XPIXPLLCM + i, ACCESS_FBINFO(hw).DACclk[i]);
 609                for (tmout = 500000; tmout; tmout--) {
 610                        if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40)
 611                                break;
 612                        udelay(10);
 613                };
 614
 615                CRITEND
 616
 617                if (!tmout)
 618                        printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
 619        }
 620#undef minfo
 621        return 0;
 622}
 623
 624static struct matrox_altout m1064 = {
 625        .owner   = THIS_MODULE,
 626        .name    = "Primary output",
 627        .compute = m1064_compute,
 628};
 629
 630#ifdef CONFIG_FB_MATROX_G450
 631static int g450_compute(void* out, struct my_timming* m) {
 632#define minfo ((struct matrox_fb_info*)out)
 633        if (m->mnp < 0) {
 634                m->mnp = matroxfb_g450_setclk(PMINFO m->pixclock, (m->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
 635                if (m->mnp >= 0) {
 636                        m->pixclock = g450_mnp2f(PMINFO m->mnp);
 637                }
 638        }
 639#undef minfo
 640        return 0;
 641}
 642
 643static struct matrox_altout g450out = {
 644        .owner   = THIS_MODULE,
 645        .name    = "Primary output",
 646        .compute = g450_compute,
 647};
 648#endif
 649
 650#endif /* NEED_DAC1064 */
 651
 652#ifdef CONFIG_FB_MATROX_MYSTIQUE
 653static int MGA1064_init(WPMINFO struct my_timming* m, struct display* p) {
 654        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 655
 656        DBG("MGA1064_init")
 657
 658        if (DAC1064_init_1(PMINFO m, p)) return 1;
 659        if (matroxfb_vgaHWinit(PMINFO m, p)) return 1;
 660
 661        hw->MiscOutReg = 0xCB;
 662        if (m->sync & FB_SYNC_HOR_HIGH_ACT)
 663                hw->MiscOutReg &= ~0x40;
 664        if (m->sync & FB_SYNC_VERT_HIGH_ACT)
 665                hw->MiscOutReg &= ~0x80;
 666        if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
 667                hw->CRTCEXT[3] |= 0x40;
 668
 669        if (DAC1064_init_2(PMINFO m, p)) return 1;
 670        return 0;
 671}
 672#endif
 673
 674#ifdef CONFIG_FB_MATROX_G100
 675static int MGAG100_init(WPMINFO struct my_timming* m, struct display* p) {
 676        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 677
 678        DBG("MGAG100_init")
 679
 680        if (DAC1064_init_1(PMINFO m, p)) return 1;
 681        hw->MXoptionReg &= ~0x2000;
 682        if (matroxfb_vgaHWinit(PMINFO m, p)) return 1;
 683
 684        hw->MiscOutReg = 0xEF;
 685        if (m->sync & FB_SYNC_HOR_HIGH_ACT)
 686                hw->MiscOutReg &= ~0x40;
 687        if (m->sync & FB_SYNC_VERT_HIGH_ACT)
 688                hw->MiscOutReg &= ~0x80;
 689        if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
 690                hw->CRTCEXT[3] |= 0x40;
 691
 692        if (DAC1064_init_2(PMINFO m, p)) return 1;
 693        return 0;
 694}
 695#endif  /* G100 */
 696
 697#ifdef CONFIG_FB_MATROX_MYSTIQUE
 698static void MGA1064_ramdac_init(WPMINFO2) {
 699
 700        DBG("MGA1064_ramdac_init");
 701
 702        /* ACCESS_FBINFO(features.DAC1064.vco_freq_min) = 120000; */
 703        ACCESS_FBINFO(features.pll.vco_freq_min) = 62000;
 704        ACCESS_FBINFO(features.pll.ref_freq)     = 14318;
 705        ACCESS_FBINFO(features.pll.feed_div_min) = 100;
 706        ACCESS_FBINFO(features.pll.feed_div_max) = 127;
 707        ACCESS_FBINFO(features.pll.in_div_min)   = 1;
 708        ACCESS_FBINFO(features.pll.in_div_max)   = 31;
 709        ACCESS_FBINFO(features.pll.post_shift_max) = 3;
 710        ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_EXTERNAL;
 711        /* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */
 712        DAC1064_setmclk(PMINFO DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333);
 713}
 714#endif
 715
 716#ifdef CONFIG_FB_MATROX_G100
 717/* BIOS environ */
 718static int x7AF4 = 0x10;        /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */
 719                                /* G100 wants 0x10, G200 SGRAM does not care... */
 720#if 0
 721static int def50 = 0;   /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
 722#endif
 723
 724static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p) {
 725        int reg;
 726        int selClk;
 727        int clk;
 728
 729        DBG("MGAG100_progPixClock")
 730
 731        outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS |
 732                   M1064_XPIXCLKCTRL_PLL_UP);
 733        switch (flags & 3) {
 734                case 0:         reg = M1064_XPIXPLLAM; break;
 735                case 1:         reg = M1064_XPIXPLLBM; break;
 736                default:        reg = M1064_XPIXPLLCM; break;
 737        }
 738        outDAC1064(PMINFO reg++, m);
 739        outDAC1064(PMINFO reg++, n);
 740        outDAC1064(PMINFO reg, p);
 741        selClk = mga_inb(M_MISC_REG_READ) & ~0xC;
 742        /* there should be flags & 0x03 & case 0/1/else */
 743        /* and we should first select source and after that we should wait for PLL */
 744        /* and we are waiting for PLL with oscilator disabled... Is it right? */
 745        switch (flags & 0x03) {
 746                case 0x00:      break;
 747                case 0x01:      selClk |= 4; break;
 748                default:        selClk |= 0x0C; break;
 749        }
 750        mga_outb(M_MISC_REG, selClk);
 751        for (clk = 500000; clk; clk--) {
 752                if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40)
 753                        break;
 754                udelay(10);
 755        };
 756        if (!clk)
 757                printk(KERN_ERR "matroxfb: Pixel PLL%c not locked after usual time\n", (reg-M1064_XPIXPLLAM-2)/4 + 'A');
 758        selClk = inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK;
 759        switch (flags & 0x0C) {
 760                case 0x00:      selClk |= M1064_XPIXCLKCTRL_SRC_PCI; break;
 761                case 0x04:      selClk |= M1064_XPIXCLKCTRL_SRC_PLL; break;
 762                default:        selClk |= M1064_XPIXCLKCTRL_SRC_EXT; break;
 763        }
 764        outDAC1064(PMINFO M1064_XPIXCLKCTRL, selClk);
 765        outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS);
 766}
 767
 768static void MGAG100_setPixClock(CPMINFO int flags, int freq) {
 769        unsigned int m, n, p;
 770
 771        DBG("MGAG100_setPixClock")
 772
 773        DAC1064_calcclock(PMINFO freq, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p);
 774        MGAG100_progPixClock(PMINFO flags, m, n, p);
 775}
 776#endif
 777
 778#ifdef CONFIG_FB_MATROX_MYSTIQUE
 779static int MGA1064_preinit(WPMINFO2) {
 780        static const int vxres_mystique[] = { 512,        640, 768,  800,  832,  960,
 781                                             1024, 1152, 1280,      1600, 1664, 1920,
 782                                             2048,    0};
 783        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 784
 785        DBG("MGA1064_preinit")
 786
 787        /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
 788        ACCESS_FBINFO(capable.text) = 1;
 789        ACCESS_FBINFO(capable.vxres) = vxres_mystique;
 790        ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
 791        ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor;
 792
 793        ACCESS_FBINFO(outputs[0]).output = &m1064;
 794        ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1;
 795        ACCESS_FBINFO(outputs[0]).data = MINFO;
 796        ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
 797
 798        if (ACCESS_FBINFO(devflags.noinit))
 799                return 0;       /* do not modify settings */
 800        hw->MXoptionReg &= 0xC0000100;
 801        hw->MXoptionReg |= 0x00094E20;
 802        if (ACCESS_FBINFO(devflags.novga))
 803                hw->MXoptionReg &= ~0x00000100;
 804        if (ACCESS_FBINFO(devflags.nobios))
 805                hw->MXoptionReg &= ~0x40000000;
 806        if (ACCESS_FBINFO(devflags.nopciretry))
 807                hw->MXoptionReg |=  0x20000000;
 808        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
 809        mga_setr(M_SEQ_INDEX, 0x01, 0x20);
 810        mga_outl(M_CTLWTST, 0x00000000);
 811        udelay(200);
 812        mga_outl(M_MACCESS, 0x00008000);
 813        udelay(100);
 814        mga_outl(M_MACCESS, 0x0000C000);
 815        return 0;
 816}
 817
 818static void MGA1064_reset(WPMINFO2) {
 819
 820        DBG("MGA1064_reset");
 821
 822        ACCESS_FBINFO(features.DAC1064.cursorimage) = ACCESS_FBINFO(video.len_usable) - 1024;
 823        if (ACCESS_FBINFO(devflags.hwcursor))
 824                ACCESS_FBINFO(video.len_usable) -= 1024;
 825        matroxfb_fastfont_init(MINFO);
 826        MGA1064_ramdac_init(PMINFO2);
 827}
 828#endif
 829
 830#ifdef CONFIG_FB_MATROX_G100
 831#ifdef CONFIG_FB_MATROX_G450
 832static void g450_mclk_init(WPMINFO2) {
 833        /* switch all clocks to PCI source */
 834        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg | 4);
 835        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION3_REG, ACCESS_FBINFO(values).reg.opt3 & ~0x00300C03);
 836        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);
 837        
 838        if (((ACCESS_FBINFO(values).reg.opt3 & 0x000003) == 0x000003) ||
 839            ((ACCESS_FBINFO(values).reg.opt3 & 0x000C00) == 0x000C00) ||
 840            ((ACCESS_FBINFO(values).reg.opt3 & 0x300000) == 0x300000)) {
 841                matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.video), M_VIDEO_PLL);
 842        } else {
 843                unsigned long flags;
 844                unsigned int pwr;
 845                
 846                matroxfb_DAC_lock_irqsave(flags);
 847                pwr = inDAC1064(PMINFO M1064_XPWRCTRL) & ~0x02;
 848                outDAC1064(PMINFO M1064_XPWRCTRL, pwr);
 849                matroxfb_DAC_unlock_irqrestore(flags);
 850        }
 851        matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.system), M_SYSTEM_PLL);
 852        
 853        /* switch clocks to their real PLL source(s) */
 854        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg | 4);
 855        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION3_REG, ACCESS_FBINFO(values).reg.opt3);
 856        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);
 857
 858}
 859
 860static void g450_memory_init(WPMINFO2) {
 861        /* disable memory refresh */
 862        ACCESS_FBINFO(hw).MXoptionReg &= ~0x001F8000;
 863        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);
 864        
 865        /* set memory interface parameters */
 866        ACCESS_FBINFO(hw).MXoptionReg &= ~0x00207E00;
 867        ACCESS_FBINFO(hw).MXoptionReg |= 0x00207E00 & ACCESS_FBINFO(values).reg.opt;
 868        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);
 869        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ACCESS_FBINFO(values).reg.opt2);
 870        
 871        mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst);
 872        
 873        /* first set up memory interface with disabled memory interface clocks */
 874        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MEMMISC_REG, ACCESS_FBINFO(values).reg.memmisc & ~0x80000000U);
 875        mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk);
 876        mga_outl(M_MACCESS, ACCESS_FBINFO(values).reg.maccess);
 877        /* start memory clocks */
 878        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MEMMISC_REG, ACCESS_FBINFO(values).reg.memmisc | 0x80000000U);
 879
 880        udelay(200);
 881        
 882        if (ACCESS_FBINFO(values).memory.ddr && (!ACCESS_FBINFO(values).memory.emrswen || !ACCESS_FBINFO(values).memory.dll)) {
 883                mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk & ~0x1000);
 884        }
 885        mga_outl(M_MACCESS, ACCESS_FBINFO(values).reg.maccess | 0x8000);
 886        
 887        udelay(200);
 888        
 889        ACCESS_FBINFO(hw).MXoptionReg |= 0x001F8000 & ACCESS_FBINFO(values).reg.opt;
 890        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);
 891        
 892        /* value is written to memory chips only if old != new */
 893        mga_outl(M_PLNWT, 0);
 894        mga_outl(M_PLNWT, ~0);
 895        
 896        if (ACCESS_FBINFO(values).reg.mctlwtst != ACCESS_FBINFO(values).reg.mctlwtst_core) {
 897                mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst_core);
 898        }
 899        
 900}
 901
 902static void g450_preinit(WPMINFO2) {
 903        u_int32_t c2ctl;
 904        u_int8_t curctl;
 905        u_int8_t c1ctl;
 906        
 907        /* ACCESS_FBINFO(hw).MXoptionReg = minfo->values.reg.opt; */
 908        ACCESS_FBINFO(hw).MXoptionReg &= 0xC0000100;
 909        ACCESS_FBINFO(hw).MXoptionReg |= 0x00000020;
 910        if (ACCESS_FBINFO(devflags.novga))
 911                ACCESS_FBINFO(hw).MXoptionReg &= ~0x00000100;
 912        if (ACCESS_FBINFO(devflags.nobios))
 913                ACCESS_FBINFO(hw).MXoptionReg &= ~0x40000000;
 914        if (ACCESS_FBINFO(devflags.nopciretry))
 915                ACCESS_FBINFO(hw).MXoptionReg |=  0x20000000;
 916        ACCESS_FBINFO(hw).MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x03400040;
 917        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg);
 918
 919        /* Init system clocks */
 920                
 921        /* stop crtc2 */
 922        c2ctl = mga_inl(M_C2CTL);
 923        mga_outl(M_C2CTL, c2ctl & ~1);
 924        /* stop cursor */
 925        curctl = inDAC1064(PMINFO M1064_XCURCTRL);
 926        outDAC1064(PMINFO M1064_XCURCTRL, 0);
 927        /* stop crtc1 */
 928        c1ctl = mga_readr(M_SEQ_INDEX, 1);
 929        mga_setr(M_SEQ_INDEX, 1, c1ctl | 0x20);
 930
 931        g450_mclk_init(PMINFO2);
 932        g450_memory_init(PMINFO2);
 933        
 934        /* set legacy VGA clock sources for DOSEmu or VMware... */
 935        matroxfb_g450_setclk(PMINFO 25175, M_PIXEL_PLL_A);
 936        matroxfb_g450_setclk(PMINFO 28322, M_PIXEL_PLL_B);
 937
 938        /* restore crtc1 */
 939        mga_setr(M_SEQ_INDEX, 1, c1ctl);
 940        
 941        /* restore cursor */
 942        outDAC1064(PMINFO M1064_XCURCTRL, curctl);
 943
 944        /* restore crtc2 */
 945        mga_outl(M_C2CTL, c2ctl);
 946        
 947        return;
 948}
 949#else
 950static inline void g450_preinit(WPMINFO2) {
 951}
 952#endif
 953
 954static int MGAG100_preinit(WPMINFO2) {
 955        static const int vxres_g100[] = {  512,        640, 768,  800,  832,  960,
 956                                          1024, 1152, 1280,      1600, 1664, 1920,
 957                                          2048, 0};
 958        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
 959
 960        u_int32_t reg50;
 961#if 0
 962        u_int32_t q;
 963#endif
 964
 965        DBG("MGAG100_preinit")
 966
 967        /* there are some instabilities if in_div > 19 && vco < 61000 */
 968        if (ACCESS_FBINFO(devflags.g450dac)) {
 969                ACCESS_FBINFO(features.pll.vco_freq_min) = 130000;      /* my sample: >118 */
 970        } else {
 971                ACCESS_FBINFO(features.pll.vco_freq_min) = 62000;
 972        }
 973        if (!ACCESS_FBINFO(features.pll.ref_freq)) {
 974                ACCESS_FBINFO(features.pll.ref_freq)     = 27000;
 975        }
 976        ACCESS_FBINFO(features.pll.feed_div_min) = 7;
 977        ACCESS_FBINFO(features.pll.feed_div_max) = 127;
 978        ACCESS_FBINFO(features.pll.in_div_min)   = 1;
 979        ACCESS_FBINFO(features.pll.in_div_max)   = 31;
 980        ACCESS_FBINFO(features.pll.post_shift_max) = 3;
 981        ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_G100_DEFAULT;
 982        /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
 983        ACCESS_FBINFO(capable.text) = 1;
 984        ACCESS_FBINFO(capable.vxres) = vxres_g100;
 985        ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
 986        ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor;
 987        ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100
 988                        ? ACCESS_FBINFO(devflags.sgram) : 1;
 989
 990#ifdef CONFIG_FB_MATROX_G450
 991        if (ACCESS_FBINFO(devflags.g450dac)) {
 992                ACCESS_FBINFO(outputs[0]).output = &g450out;
 993        } else
 994#endif
 995        {
 996                ACCESS_FBINFO(outputs[0]).output = &m1064;
 997        }
 998        ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1;
 999        ACCESS_FBINFO(outputs[0]).data = MINFO;
1000        ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
1001
1002        if (ACCESS_FBINFO(devflags.g450dac)) {
1003                /* we must do this always, BIOS does not do it for us
1004                   and accelerator dies without it */
1005                mga_outl(0x1C0C, 0);
1006        }
1007        if (ACCESS_FBINFO(devflags.noinit))
1008                return 0;
1009        if (ACCESS_FBINFO(devflags.g450dac)) {
1010                g450_preinit(PMINFO2);
1011                return 0;
1012        }
1013        hw->MXoptionReg &= 0xC0000100;
1014        hw->MXoptionReg |= 0x00000020;
1015        if (ACCESS_FBINFO(devflags.novga))
1016                hw->MXoptionReg &= ~0x00000100;
1017        if (ACCESS_FBINFO(devflags.nobios))
1018                hw->MXoptionReg &= ~0x40000000;
1019        if (ACCESS_FBINFO(devflags.nopciretry))
1020                hw->MXoptionReg |=  0x20000000;
1021        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
1022        DAC1064_setmclk(PMINFO DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333);
1023
1024        if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100) {
1025                pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, &reg50);
1026                reg50 &= ~0x3000;
1027                pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50);
1028
1029                hw->MXoptionReg |= 0x1080;
1030                pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
1031                mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst);
1032                udelay(100);
1033                mga_outb(0x1C05, 0x00);
1034                mga_outb(0x1C05, 0x80);
1035                udelay(100);
1036                mga_outb(0x1C05, 0x40);
1037                mga_outb(0x1C05, 0xC0);
1038                udelay(100);
1039                reg50 &= ~0xFF;
1040                reg50 |=  0x07;
1041                pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50);
1042                /* it should help with G100 */
1043                mga_outb(M_GRAPHICS_INDEX, 6);
1044                mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4);
1045                mga_setr(M_EXTVGA_INDEX, 0x03, 0x81);
1046                mga_setr(M_EXTVGA_INDEX, 0x04, 0x00);
1047                mga_writeb(ACCESS_FBINFO(video.vbase), 0x0000, 0xAA);
1048                mga_writeb(ACCESS_FBINFO(video.vbase), 0x0800, 0x55);
1049                mga_writeb(ACCESS_FBINFO(video.vbase), 0x4000, 0x55);
1050#if 0
1051                if (mga_readb(ACCESS_FBINFO(video.vbase), 0x0000) != 0xAA) {
1052                        hw->MXoptionReg &= ~0x1000;
1053                }
1054#endif
1055                hw->MXoptionReg |= 0x00078020;
1056        } else if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG200) {
1057                pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, &reg50);
1058                reg50 &= ~0x3000;
1059                pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50);
1060
1061                if (ACCESS_FBINFO(devflags.memtype) == -1)
1062                        hw->MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x1C00;
1063                else
1064                        hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10;
1065                if (ACCESS_FBINFO(devflags.sgram))
1066                        hw->MXoptionReg |= 0x4000;
1067                mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst);
1068                mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk);
1069                udelay(200);
1070                mga_outl(M_MACCESS, 0x00000000);
1071                mga_outl(M_MACCESS, 0x00008000);
1072                udelay(100);
1073                mga_outw(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk);
1074                hw->MXoptionReg |= 0x00078020;
1075        } else {
1076                pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, &reg50);
1077                reg50 &= ~0x00000100;
1078                reg50 |=  0x00000000;
1079                pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50);
1080
1081                if (ACCESS_FBINFO(devflags.memtype) == -1)
1082                        hw->MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x1C00;
1083                else
1084                        hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10;
1085                if (ACCESS_FBINFO(devflags.sgram))
1086                        hw->MXoptionReg |= 0x4000;
1087                mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst);
1088                mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk);
1089                udelay(200);
1090                mga_outl(M_MACCESS, 0x00000000);
1091                mga_outl(M_MACCESS, 0x00008000);
1092                udelay(100);
1093                mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk);
1094                hw->MXoptionReg |= 0x00040020;
1095        }
1096        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
1097        return 0;
1098}
1099
1100static void MGAG100_reset(WPMINFO2) {
1101        u_int8_t b;
1102        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
1103
1104        DBG("MGAG100_reset")
1105
1106        ACCESS_FBINFO(features.DAC1064.cursorimage) = ACCESS_FBINFO(video.len_usable) - 1024;
1107        if (ACCESS_FBINFO(devflags.hwcursor))
1108                ACCESS_FBINFO(video.len_usable) -= 1024;
1109        matroxfb_fastfont_init(MINFO);
1110
1111        {
1112#ifdef G100_BROKEN_IBM_82351
1113                u_int32_t d;
1114
1115                find 1014/22 (IBM/82351); /* if found and bridging Matrox, do some strange stuff */
1116                pci_read_config_byte(ibm, PCI_SECONDARY_BUS, &b);
1117                if (b == ACCESS_FBINFO(pcidev)->bus->number) {
1118                        pci_write_config_byte(ibm, PCI_COMMAND+1, 0);   /* disable back-to-back & SERR */
1119                        pci_write_config_byte(ibm, 0x41, 0xF4);         /* ??? */
1120                        pci_write_config_byte(ibm, PCI_IO_BASE, 0xF0);  /* ??? */
1121                        pci_write_config_byte(ibm, PCI_IO_LIMIT, 0x00); /* ??? */
1122                }
1123#endif
1124                if (!ACCESS_FBINFO(devflags.noinit)) {
1125                        if (x7AF4 & 8) {
1126                                hw->MXoptionReg |= 0x40;        /* FIXME... */
1127                                pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
1128                        }
1129                        mga_setr(M_EXTVGA_INDEX, 0x06, 0x50);
1130                }
1131        }
1132        if (ACCESS_FBINFO(devflags.g450dac)) {
1133                /* either leave MCLK as is... or they were set in preinit */
1134                hw->DACclk[3] = inDAC1064(PMINFO DAC1064_XSYSPLLM);
1135                hw->DACclk[4] = inDAC1064(PMINFO DAC1064_XSYSPLLN);
1136                hw->DACclk[5] = inDAC1064(PMINFO DAC1064_XSYSPLLP);
1137        } else {
1138                DAC1064_setmclk(PMINFO DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333);
1139        }
1140        if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) {
1141                if (ACCESS_FBINFO(devflags.dfp_type) == -1) {
1142                        ACCESS_FBINFO(devflags.dfp_type) = inDAC1064(PMINFO 0x1F);
1143                }
1144        }
1145        if (ACCESS_FBINFO(devflags.noinit))
1146                return;
1147        if (ACCESS_FBINFO(devflags.g450dac)) {
1148        } else {
1149                MGAG100_setPixClock(PMINFO 4, 25175);
1150                MGAG100_setPixClock(PMINFO 5, 28322);
1151                if (x7AF4 & 0x10) {
1152                        b = inDAC1064(PMINFO M1064_XGENIODATA) & ~1;
1153                        outDAC1064(PMINFO M1064_XGENIODATA, b);
1154                        b = inDAC1064(PMINFO M1064_XGENIOCTRL) | 1;
1155                        outDAC1064(PMINFO M1064_XGENIOCTRL, b);
1156                }
1157        }
1158}
1159#endif
1160
1161#ifdef CONFIG_FB_MATROX_MYSTIQUE
1162static void MGA1064_restore(WPMINFO struct display* p) {
1163        int i;
1164        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
1165
1166        CRITFLAGS
1167
1168        DBG("MGA1064_restore")
1169
1170        CRITBEGIN
1171
1172        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
1173        mga_outb(M_IEN, 0x00);
1174        mga_outb(M_CACHEFLUSH, 0x00);
1175
1176        CRITEND
1177
1178        DAC1064_restore_1(PMINFO2);
1179        matroxfb_vgaHWrestore(PMINFO2);
1180        ACCESS_FBINFO(crtc1.panpos) = -1;
1181        for (i = 0; i < 6; i++)
1182                mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
1183        DAC1064_restore_2(PMINFO p);
1184}
1185#endif
1186
1187#ifdef CONFIG_FB_MATROX_G100
1188static void MGAG100_restore(WPMINFO struct display* p) {
1189        int i;
1190        struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
1191
1192        CRITFLAGS
1193
1194        DBG("MGAG100_restore")
1195
1196        CRITBEGIN
1197
1198        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
1199        CRITEND
1200
1201        DAC1064_restore_1(PMINFO2);
1202        matroxfb_vgaHWrestore(PMINFO2);
1203#ifdef CONFIG_FB_MATROX_32MB
1204        if (ACCESS_FBINFO(devflags.support32MB))
1205                mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]);
1206#endif
1207        ACCESS_FBINFO(crtc1.panpos) = -1;
1208        for (i = 0; i < 6; i++)
1209                mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
1210        DAC1064_restore_2(PMINFO p);
1211}
1212#endif
1213
1214#ifdef CONFIG_FB_MATROX_MYSTIQUE
1215struct matrox_switch matrox_mystique = {
1216        MGA1064_preinit, MGA1064_reset, MGA1064_init, MGA1064_restore, DAC1064_selhwcursor
1217};
1218EXPORT_SYMBOL(matrox_mystique);
1219#endif
1220
1221#ifdef CONFIG_FB_MATROX_G100
1222struct matrox_switch matrox_G100 = {
1223        MGAG100_preinit, MGAG100_reset, MGAG100_init, MGAG100_restore, DAC1064_selhwcursor
1224};
1225EXPORT_SYMBOL(matrox_G100);
1226#endif
1227
1228#ifdef NEED_DAC1064
1229EXPORT_SYMBOL(DAC1064_global_init);
1230EXPORT_SYMBOL(DAC1064_global_restore);
1231#endif
1232MODULE_LICENSE("GPL");
1233
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.