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