Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *
0004  * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
0005  *
0006  * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
0007  *
0008  * Portions Copyright (c) 2001 Matrox Graphics Inc.
0009  *
0010  * Version: 1.65 2002/08/14
0011  *
0012  * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
0013  *
0014  * Contributors: "menion?" <menion@mindless.com>
0015  *                     Betatesting, fixes, ideas
0016  *
0017  *               "Kurt Garloff" <garloff@suse.de>
0018  *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
0019  *
0020  *               "Tom Rini" <trini@kernel.crashing.org>
0021  *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
0022  *
0023  *               "Bibek Sahu" <scorpio@dodds.net>
0024  *                     Access device through readb|w|l and write b|w|l
0025  *                     Extensive debugging stuff
0026  *
0027  *               "Daniel Haun" <haund@usa.net>
0028  *                     Testing, hardware cursor fixes
0029  *
0030  *               "Scott Wood" <sawst46+@pitt.edu>
0031  *                     Fixes
0032  *
0033  *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
0034  *                     Betatesting
0035  *
0036  *               "Kelly French" <targon@hazmat.com>
0037  *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
0038  *                     Betatesting, bug reporting
0039  *
0040  *               "Pablo Bianucci" <pbian@pccp.com.ar>
0041  *                     Fixes, ideas, betatesting
0042  *
0043  *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
0044  *                     Fixes, enhandcements, ideas, betatesting
0045  *
0046  *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
0047  *                     PPC betatesting, PPC support, backward compatibility
0048  *
0049  *               "Paul Womar" <Paul@pwomar.demon.co.uk>
0050  *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
0051  *                     PPC betatesting
0052  *
0053  *               "Thomas Pornin" <pornin@bolet.ens.fr>
0054  *                     Alpha betatesting
0055  *
0056  *               "Pieter van Leuven" <pvl@iae.nl>
0057  *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
0058  *                     G100 testing
0059  *
0060  *               "H. Peter Arvin" <hpa@transmeta.com>
0061  *                     Ideas
0062  *
0063  *               "Cort Dougan" <cort@cs.nmt.edu>
0064  *                     CHRP fixes and PReP cleanup
0065  *
0066  *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
0067  *                     G400 support
0068  *
0069  * (following author is not in any relation with this code, but his code
0070  *  is included in this driver)
0071  *
0072  * Based on framebuffer driver for VBE 2.0 compliant graphic boards
0073  *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
0074  *
0075  * (following author is not in any relation with this code, but his ideas
0076  *  were used when writing this driver)
0077  *
0078  *       FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
0079  *
0080  */
0081 
0082 
0083 #include "matroxfb_Ti3026.h"
0084 #include "matroxfb_misc.h"
0085 #include "matroxfb_accel.h"
0086 #include <linux/matroxfb.h>
0087 
0088 #ifdef CONFIG_FB_MATROX_MILLENIUM
0089 #define outTi3026 matroxfb_DAC_out
0090 #define inTi3026 matroxfb_DAC_in
0091 
0092 #define TVP3026_INDEX       0x00
0093 #define TVP3026_PALWRADD    0x00
0094 #define TVP3026_PALDATA     0x01
0095 #define TVP3026_PIXRDMSK    0x02
0096 #define TVP3026_PALRDADD    0x03
0097 #define TVP3026_CURCOLWRADD 0x04
0098 #define     TVP3026_CLOVERSCAN      0x00
0099 #define     TVP3026_CLCOLOR0        0x01
0100 #define     TVP3026_CLCOLOR1        0x02
0101 #define     TVP3026_CLCOLOR2        0x03
0102 #define TVP3026_CURCOLDATA  0x05
0103 #define TVP3026_CURCOLRDADD 0x07
0104 #define TVP3026_CURCTRL     0x09
0105 #define TVP3026_X_DATAREG   0x0A
0106 #define TVP3026_CURRAMDATA  0x0B
0107 #define TVP3026_CURPOSXL    0x0C
0108 #define TVP3026_CURPOSXH    0x0D
0109 #define TVP3026_CURPOSYL    0x0E
0110 #define TVP3026_CURPOSYH    0x0F
0111 
0112 #define TVP3026_XSILICONREV 0x01
0113 #define TVP3026_XCURCTRL    0x06
0114 #define     TVP3026_XCURCTRL_DIS    0x00    /* transparent, transparent, transparent, transparent */
0115 #define     TVP3026_XCURCTRL_3COLOR 0x01    /* transparent, 0, 1, 2 */
0116 #define     TVP3026_XCURCTRL_XGA    0x02    /* 0, 1, transparent, complement */
0117 #define     TVP3026_XCURCTRL_XWIN   0x03    /* transparent, transparent, 0, 1 */
0118 #define     TVP3026_XCURCTRL_BLANK2048  0x00
0119 #define     TVP3026_XCURCTRL_BLANK4096  0x10
0120 #define     TVP3026_XCURCTRL_INTERLACED 0x20
0121 #define     TVP3026_XCURCTRL_ODD    0x00 /* ext.signal ODD/\EVEN */
0122 #define     TVP3026_XCURCTRL_EVEN   0x40 /* ext.signal EVEN/\ODD */
0123 #define     TVP3026_XCURCTRL_INDIRECT   0x00
0124 #define     TVP3026_XCURCTRL_DIRECT 0x80
0125 #define TVP3026_XLATCHCTRL  0x0F
0126 #define     TVP3026_XLATCHCTRL_1_1  0x06
0127 #define     TVP3026_XLATCHCTRL_2_1  0x07
0128 #define     TVP3026_XLATCHCTRL_4_1  0x06
0129 #define     TVP3026_XLATCHCTRL_8_1  0x06
0130 #define     TVP3026_XLATCHCTRL_16_1 0x06
0131 #define     TVP3026A_XLATCHCTRL_4_3 0x06    /* ??? do not understand... but it works... !!! */
0132 #define     TVP3026A_XLATCHCTRL_8_3 0x07
0133 #define     TVP3026B_XLATCHCTRL_4_3 0x08
0134 #define     TVP3026B_XLATCHCTRL_8_3 0x06    /* ??? do not understand... but it works... !!! */
0135 #define TVP3026_XTRUECOLORCTRL  0x18
0136 #define     TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_ACCEL 0x00
0137 #define     TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_TVP   0x20
0138 #define     TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR      0x80
0139 #define     TVP3026_XTRUECOLORCTRL_TRUECOLOR        0x40 /* paletized */
0140 #define     TVP3026_XTRUECOLORCTRL_DIRECTCOLOR      0x00
0141 #define     TVP3026_XTRUECOLORCTRL_24_ALTERNATE     0x08 /* 5:4/5:2 instead of 4:3/8:3 */
0142 #define     TVP3026_XTRUECOLORCTRL_RGB_888      0x16 /* 4:3/8:3 (or 5:4/5:2) */
0143 #define     TVP3026_XTRUECOLORCTRL_BGR_888      0x17
0144 #define     TVP3026_XTRUECOLORCTRL_ORGB_8888        0x06
0145 #define     TVP3026_XTRUECOLORCTRL_BGRO_8888        0x07
0146 #define     TVP3026_XTRUECOLORCTRL_RGB_565      0x05
0147 #define     TVP3026_XTRUECOLORCTRL_ORGB_1555        0x04
0148 #define     TVP3026_XTRUECOLORCTRL_RGB_664      0x03
0149 #define     TVP3026_XTRUECOLORCTRL_RGBO_4444        0x01
0150 #define TVP3026_XMUXCTRL    0x19
0151 #define     TVP3026_XMUXCTRL_MEMORY_8BIT            0x01 /* - */
0152 #define     TVP3026_XMUXCTRL_MEMORY_16BIT           0x02 /* - */
0153 #define     TVP3026_XMUXCTRL_MEMORY_32BIT           0x03 /* 2MB RAM, 512K * 4 */
0154 #define     TVP3026_XMUXCTRL_MEMORY_64BIT           0x04 /* >2MB RAM, 512K * 8 & more */
0155 #define     TVP3026_XMUXCTRL_PIXEL_4BIT             0x40 /* L0,H0,L1,H1... */
0156 #define     TVP3026_XMUXCTRL_PIXEL_4BIT_SWAPPED         0x60 /* H0,L0,H1,L1... */
0157 #define     TVP3026_XMUXCTRL_PIXEL_8BIT             0x48
0158 #define     TVP3026_XMUXCTRL_PIXEL_16BIT            0x50
0159 #define     TVP3026_XMUXCTRL_PIXEL_32BIT            0x58
0160 #define     TVP3026_XMUXCTRL_VGA                0x98 /* VGA MEMORY, 8BIT PIXEL */
0161 #define TVP3026_XCLKCTRL    0x1A
0162 #define     TVP3026_XCLKCTRL_DIV1   0x00
0163 #define     TVP3026_XCLKCTRL_DIV2   0x10
0164 #define     TVP3026_XCLKCTRL_DIV4   0x20
0165 #define     TVP3026_XCLKCTRL_DIV8   0x30
0166 #define     TVP3026_XCLKCTRL_DIV16  0x40
0167 #define     TVP3026_XCLKCTRL_DIV32  0x50
0168 #define     TVP3026_XCLKCTRL_DIV64  0x60
0169 #define     TVP3026_XCLKCTRL_CLKSTOPPED 0x70
0170 #define     TVP3026_XCLKCTRL_SRC_CLK0   0x00
0171 #define     TVP3026_XCLKCTRL_SRC_CLK1   0x01
0172 #define     TVP3026_XCLKCTRL_SRC_CLK2   0x02    /* CLK2 is TTL source*/
0173 #define     TVP3026_XCLKCTRL_SRC_NCLK2  0x03    /* not CLK2 is TTL source */
0174 #define     TVP3026_XCLKCTRL_SRC_ECLK2  0x04    /* CLK2 and not CLK2 is ECL source */
0175 #define     TVP3026_XCLKCTRL_SRC_PLL    0x05
0176 #define     TVP3026_XCLKCTRL_SRC_DIS    0x06    /* disable & poweroff internal clock */
0177 #define     TVP3026_XCLKCTRL_SRC_CLK0VGA 0x07
0178 #define TVP3026_XPALETTEPAGE    0x1C
0179 #define TVP3026_XGENCTRL    0x1D
0180 #define     TVP3026_XGENCTRL_HSYNC_POS  0x00
0181 #define     TVP3026_XGENCTRL_HSYNC_NEG  0x01
0182 #define     TVP3026_XGENCTRL_VSYNC_POS  0x00
0183 #define     TVP3026_XGENCTRL_VSYNC_NEG  0x02
0184 #define     TVP3026_XGENCTRL_LITTLE_ENDIAN 0x00
0185 #define     TVP3026_XGENCTRL_BIG_ENDIAN    0x08
0186 #define     TVP3026_XGENCTRL_BLACK_0IRE     0x00
0187 #define     TVP3026_XGENCTRL_BLACK_75IRE    0x10
0188 #define     TVP3026_XGENCTRL_NO_SYNC_ON_GREEN   0x00
0189 #define     TVP3026_XGENCTRL_SYNC_ON_GREEN  0x20
0190 #define     TVP3026_XGENCTRL_OVERSCAN_DIS   0x00
0191 #define     TVP3026_XGENCTRL_OVERSCAN_EN    0x40
0192 #define TVP3026_XMISCCTRL   0x1E
0193 #define     TVP3026_XMISCCTRL_DAC_PUP   0x00
0194 #define     TVP3026_XMISCCTRL_DAC_PDOWN 0x01
0195 #define     TVP3026_XMISCCTRL_DAC_EXT   0x00 /* or 8, bit 3 is ignored */
0196 #define     TVP3026_XMISCCTRL_DAC_6BIT  0x04
0197 #define     TVP3026_XMISCCTRL_DAC_8BIT  0x0C
0198 #define     TVP3026_XMISCCTRL_PSEL_DIS  0x00
0199 #define     TVP3026_XMISCCTRL_PSEL_EN   0x10
0200 #define     TVP3026_XMISCCTRL_PSEL_LOW  0x00 /* PSEL high selects directcolor */
0201 #define     TVP3026_XMISCCTRL_PSEL_HIGH 0x20 /* PSEL high selects truecolor or pseudocolor */
0202 #define TVP3026_XGENIOCTRL  0x2A
0203 #define TVP3026_XGENIODATA  0x2B
0204 #define TVP3026_XPLLADDR    0x2C
0205 #define     TVP3026_XPLLADDR_X(LOOP,MCLK,PIX) (((LOOP)<<4) | ((MCLK)<<2) | (PIX))
0206 #define     TVP3026_XPLLDATA_N      0x00
0207 #define     TVP3026_XPLLDATA_M      0x01
0208 #define     TVP3026_XPLLDATA_P      0x02
0209 #define     TVP3026_XPLLDATA_STAT   0x03
0210 #define TVP3026_XPIXPLLDATA 0x2D
0211 #define TVP3026_XMEMPLLDATA 0x2E
0212 #define TVP3026_XLOOPPLLDATA    0x2F
0213 #define TVP3026_XCOLKEYOVRMIN   0x30
0214 #define TVP3026_XCOLKEYOVRMAX   0x31
0215 #define TVP3026_XCOLKEYREDMIN   0x32
0216 #define TVP3026_XCOLKEYREDMAX   0x33
0217 #define TVP3026_XCOLKEYGREENMIN 0x34
0218 #define TVP3026_XCOLKEYGREENMAX 0x35
0219 #define TVP3026_XCOLKEYBLUEMIN  0x36
0220 #define TVP3026_XCOLKEYBLUEMAX  0x37
0221 #define TVP3026_XCOLKEYCTRL 0x38
0222 #define     TVP3026_XCOLKEYCTRL_OVR_EN  0x01
0223 #define     TVP3026_XCOLKEYCTRL_RED_EN  0x02
0224 #define     TVP3026_XCOLKEYCTRL_GREEN_EN 0x04
0225 #define     TVP3026_XCOLKEYCTRL_BLUE_EN 0x08
0226 #define     TVP3026_XCOLKEYCTRL_NEGATE  0x10
0227 #define     TVP3026_XCOLKEYCTRL_ZOOM1   0x00
0228 #define     TVP3026_XCOLKEYCTRL_ZOOM2   0x20
0229 #define     TVP3026_XCOLKEYCTRL_ZOOM4   0x40
0230 #define     TVP3026_XCOLKEYCTRL_ZOOM8   0x60
0231 #define     TVP3026_XCOLKEYCTRL_ZOOM16  0x80
0232 #define     TVP3026_XCOLKEYCTRL_ZOOM32  0xA0
0233 #define TVP3026_XMEMPLLCTRL 0x39
0234 #define     TVP3026_XMEMPLLCTRL_DIV(X)  (((X)-1)>>1)    /* 2,4,6,8,10,12,14,16, division applied to LOOP PLL after divide by 2^P */
0235 #define     TVP3026_XMEMPLLCTRL_STROBEMKC4  0x08
0236 #define     TVP3026_XMEMPLLCTRL_MCLK_DOTCLOCK   0x00    /* MKC4 */
0237 #define     TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL    0x10    /* MKC4 */
0238 #define     TVP3026_XMEMPLLCTRL_RCLK_PIXPLL 0x00
0239 #define     TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL    0x20
0240 #define     TVP3026_XMEMPLLCTRL_RCLK_DOTDIVN    0x40    /* dot clock divided by loop pclk N prescaler */
0241 #define TVP3026_XSENSETEST  0x3A
0242 #define TVP3026_XTESTMODEDATA   0x3B
0243 #define TVP3026_XCRCREML    0x3C
0244 #define TVP3026_XCRCREMH    0x3D
0245 #define TVP3026_XCRCBITSEL  0x3E
0246 #define TVP3026_XID     0x3F
0247 
0248 static const unsigned char DACseq[] =
0249 { TVP3026_XLATCHCTRL, TVP3026_XTRUECOLORCTRL,
0250   TVP3026_XMUXCTRL, TVP3026_XCLKCTRL,
0251   TVP3026_XPALETTEPAGE,
0252   TVP3026_XGENCTRL,
0253   TVP3026_XMISCCTRL,
0254   TVP3026_XGENIOCTRL,
0255   TVP3026_XGENIODATA,
0256   TVP3026_XCOLKEYOVRMIN, TVP3026_XCOLKEYOVRMAX, TVP3026_XCOLKEYREDMIN, TVP3026_XCOLKEYREDMAX,
0257   TVP3026_XCOLKEYGREENMIN, TVP3026_XCOLKEYGREENMAX, TVP3026_XCOLKEYBLUEMIN, TVP3026_XCOLKEYBLUEMAX,
0258   TVP3026_XCOLKEYCTRL,
0259   TVP3026_XMEMPLLCTRL, TVP3026_XSENSETEST, TVP3026_XCURCTRL };
0260 
0261 #define POS3026_XLATCHCTRL  0
0262 #define POS3026_XTRUECOLORCTRL  1
0263 #define POS3026_XMUXCTRL    2
0264 #define POS3026_XCLKCTRL    3
0265 #define POS3026_XGENCTRL    5
0266 #define POS3026_XMISCCTRL   6
0267 #define POS3026_XMEMPLLCTRL 18
0268 #define POS3026_XCURCTRL    20
0269 
0270 static const unsigned char MGADACbpp32[] =
0271 { TVP3026_XLATCHCTRL_2_1, TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_8888,
0272   0x00, TVP3026_XCLKCTRL_DIV1 | TVP3026_XCLKCTRL_SRC_PLL,
0273   0x00,
0274   TVP3026_XGENCTRL_HSYNC_POS | TVP3026_XGENCTRL_VSYNC_POS | TVP3026_XGENCTRL_LITTLE_ENDIAN | TVP3026_XGENCTRL_BLACK_0IRE | TVP3026_XGENCTRL_NO_SYNC_ON_GREEN | TVP3026_XGENCTRL_OVERSCAN_DIS,
0275   TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_HIGH,
0276   0x00,
0277   0x1E,
0278   0xFF, 0xFF, 0xFF, 0xFF,
0279   0xFF, 0xFF, 0xFF, 0xFF,
0280   TVP3026_XCOLKEYCTRL_ZOOM1,
0281   0x00, 0x00, TVP3026_XCURCTRL_DIS };
0282 
0283 static int Ti3026_calcclock(const struct matrox_fb_info *minfo,
0284                 unsigned int freq, unsigned int fmax, int *in,
0285                 int *feed, int *post)
0286 {
0287     unsigned int fvco;
0288     unsigned int lin, lfeed, lpost;
0289 
0290     DBG(__func__)
0291 
0292     fvco = PLL_calcclock(minfo, freq, fmax, &lin, &lfeed, &lpost);
0293     fvco >>= (*post = lpost);
0294     *in = 64 - lin;
0295     *feed = 64 - lfeed;
0296     return fvco;
0297 }
0298 
0299 static int Ti3026_setpclk(struct matrox_fb_info *minfo, int clk)
0300 {
0301     unsigned int f_pll;
0302     unsigned int pixfeed, pixin, pixpost;
0303     struct matrox_hw_state *hw = &minfo->hw;
0304 
0305     DBG(__func__)
0306 
0307     f_pll = Ti3026_calcclock(minfo, clk, minfo->max_pixel_clock, &pixin, &pixfeed, &pixpost);
0308 
0309     hw->DACclk[0] = pixin | 0xC0;
0310     hw->DACclk[1] = pixfeed;
0311     hw->DACclk[2] = pixpost | 0xB0;
0312 
0313     {
0314         unsigned int loopfeed, loopin, looppost, loopdiv, z;
0315         unsigned int Bpp;
0316 
0317         Bpp = minfo->curr.final_bppShift;
0318 
0319         if (minfo->fbcon.var.bits_per_pixel == 24) {
0320             loopfeed = 3;       /* set lm to any possible value */
0321             loopin = 3 * 32 / Bpp;
0322         } else {
0323             loopfeed = 4;
0324             loopin = 4 * 32 / Bpp;
0325         }
0326         z = (110000 * loopin) / (f_pll * loopfeed);
0327         loopdiv = 0; /* div 2 */
0328         if (z < 2)
0329             looppost = 0;
0330         else if (z < 4)
0331             looppost = 1;
0332         else if (z < 8)
0333             looppost = 2;
0334         else {
0335             looppost = 3;
0336             loopdiv = z/16;
0337         }
0338         if (minfo->fbcon.var.bits_per_pixel == 24) {
0339             hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
0340             hw->DACclk[4] = (65 - loopfeed) | 0x80;
0341             if (minfo->accel.ramdac_rev > 0x20) {
0342                 if (isInterleave(minfo))
0343                     hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3;
0344                 else {
0345                     hw->DACclk[4] &= ~0xC0;
0346                     hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3;
0347                 }
0348             } else {
0349                 if (isInterleave(minfo))
0350                     ;   /* default... */
0351                 else {
0352                     hw->DACclk[4] ^= 0xC0;  /* change from 0x80 to 0x40 */
0353                     hw->DACreg[POS3026_XLATCHCTRL] = TVP3026A_XLATCHCTRL_4_3;
0354                 }
0355             }
0356             hw->DACclk[5] = looppost | 0xF8;
0357             if (minfo->devflags.mga_24bpp_fix)
0358                 hw->DACclk[5] ^= 0x40;
0359         } else {
0360             hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
0361             hw->DACclk[4] = 65 - loopfeed;
0362             hw->DACclk[5] = looppost | 0xF0;
0363         }
0364         hw->DACreg[POS3026_XMEMPLLCTRL] = loopdiv | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL;
0365     }
0366     return 0;
0367 }
0368 
0369 static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m)
0370 {
0371     u_int8_t muxctrl = isInterleave(minfo) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT;
0372     struct matrox_hw_state *hw = &minfo->hw;
0373 
0374     DBG(__func__)
0375 
0376     memcpy(hw->DACreg, MGADACbpp32, sizeof(MGADACbpp32));
0377     switch (minfo->fbcon.var.bits_per_pixel) {
0378         case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1;   /* or _8_1, they are same */
0379             hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
0380             hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_4BIT;
0381             hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV8;
0382             hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
0383             break;
0384         case 8: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_8_1;    /* or _4_1, they are same */
0385             hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
0386             hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_8BIT;
0387             hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4;
0388             hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
0389             break;
0390         case 16:
0391             /* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used every time) */
0392             hw->DACreg[POS3026_XTRUECOLORCTRL] = (minfo->fbcon.var.green.length == 5) ? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565);
0393             hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT;
0394             hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2;
0395             break;
0396         case 24:
0397             /* XLATCHCTRL is: for (A) use _4_3 (?_8_3 is same? TBD), for (B) it is set in setpclk */
0398             hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_888;
0399             hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT;
0400             hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4;
0401             break;
0402         case 32:
0403             /* XLATCHCTRL should be _2_1 / _1_1... Why is not? (_2_1 is used every time) */
0404             hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT;
0405             break;
0406         default:
0407             return 1;   /* TODO: failed */
0408     }
0409     if (matroxfb_vgaHWinit(minfo, m)) return 1;
0410 
0411     /* set SYNC */
0412     hw->MiscOutReg = 0xCB;
0413     if (m->sync & FB_SYNC_HOR_HIGH_ACT)
0414         hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_HSYNC_NEG;
0415     if (m->sync & FB_SYNC_VERT_HIGH_ACT)
0416         hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_VSYNC_NEG;
0417     if (m->sync & FB_SYNC_ON_GREEN)
0418         hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_SYNC_ON_GREEN;
0419 
0420     /* set DELAY */
0421     if (minfo->video.len < 0x400000)
0422         hw->CRTCEXT[3] |= 0x08;
0423     else if (minfo->video.len > 0x400000)
0424         hw->CRTCEXT[3] |= 0x10;
0425 
0426     /* set HWCURSOR */
0427     if (m->interlaced) {
0428         hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_INTERLACED;
0429     }
0430     if (m->HTotal >= 1536)
0431         hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_BLANK4096;
0432 
0433     /* set interleaving */
0434     hw->MXoptionReg &= ~0x00001000;
0435     if (isInterleave(minfo)) hw->MXoptionReg |= 0x00001000;
0436 
0437     /* set DAC */
0438     Ti3026_setpclk(minfo, m->pixclock);
0439     return 0;
0440 }
0441 
0442 static void ti3026_setMCLK(struct matrox_fb_info *minfo, int fout)
0443 {
0444     unsigned int f_pll;
0445     unsigned int pclk_m, pclk_n, pclk_p;
0446     unsigned int mclk_m, mclk_n, mclk_p;
0447     unsigned int rfhcnt, mclk_ctl;
0448     int tmout;
0449 
0450     DBG(__func__)
0451 
0452     f_pll = Ti3026_calcclock(minfo, fout, minfo->max_pixel_clock, &mclk_n, &mclk_m, &mclk_p);
0453 
0454     /* save pclk */
0455     outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
0456     pclk_n = inTi3026(minfo, TVP3026_XPIXPLLDATA);
0457     outTi3026(minfo, TVP3026_XPLLADDR, 0xFD);
0458     pclk_m = inTi3026(minfo, TVP3026_XPIXPLLDATA);
0459     outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
0460     pclk_p = inTi3026(minfo, TVP3026_XPIXPLLDATA);
0461 
0462     /* stop pclk */
0463     outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
0464     outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
0465 
0466     /* set pclk to new mclk */
0467     outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
0468     outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_n | 0xC0);
0469     outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_m);
0470     outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_p | 0xB0);
0471 
0472     /* wait for PLL to lock */
0473     for (tmout = 500000; tmout; tmout--) {
0474         if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
0475             break;
0476         udelay(10);
0477     }
0478     if (!tmout)
0479         printk(KERN_ERR "matroxfb: Temporary pixel PLL not locked after 5 secs\n");
0480 
0481     /* output pclk on mclk pin */
0482     mclk_ctl = inTi3026(minfo, TVP3026_XMEMPLLCTRL);
0483     outTi3026(minfo, TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7);
0484     outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4);
0485 
0486     /* stop MCLK */
0487     outTi3026(minfo, TVP3026_XPLLADDR, 0xFB);
0488     outTi3026(minfo, TVP3026_XMEMPLLDATA, 0x00);
0489 
0490     /* set mclk to new freq */
0491     outTi3026(minfo, TVP3026_XPLLADDR, 0xF3);
0492     outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_n | 0xC0);
0493     outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_m);
0494     outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_p | 0xB0);
0495 
0496     /* wait for PLL to lock */
0497     for (tmout = 500000; tmout; tmout--) {
0498         if (inTi3026(minfo, TVP3026_XMEMPLLDATA) & 0x40)
0499             break;
0500         udelay(10);
0501     }
0502     if (!tmout)
0503         printk(KERN_ERR "matroxfb: Memory PLL not locked after 5 secs\n");
0504 
0505     f_pll = f_pll * 333 / (10000 << mclk_p);
0506     if (isMilleniumII(minfo)) {
0507         rfhcnt = (f_pll - 128) / 256;
0508         if (rfhcnt > 15)
0509             rfhcnt = 15;
0510     } else {
0511         rfhcnt = (f_pll - 64) / 128;
0512         if (rfhcnt > 15)
0513             rfhcnt = 0;
0514     }
0515     minfo->hw.MXoptionReg = (minfo->hw.MXoptionReg & ~0x000F0000) | (rfhcnt << 16);
0516     pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
0517 
0518     /* output MCLK to MCLK pin */
0519     outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
0520     outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl       ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4);
0521 
0522     /* stop PCLK */
0523     outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
0524     outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
0525 
0526     /* restore pclk */
0527     outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
0528     outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_n);
0529     outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_m);
0530     outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_p);
0531 
0532     /* wait for PLL to lock */
0533     for (tmout = 500000; tmout; tmout--) {
0534         if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
0535             break;
0536         udelay(10);
0537     }
0538     if (!tmout)
0539         printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
0540 }
0541 
0542 static void ti3026_ramdac_init(struct matrox_fb_info *minfo)
0543 {
0544     DBG(__func__)
0545 
0546     minfo->features.pll.vco_freq_min = 110000;
0547     minfo->features.pll.ref_freq     = 114545;
0548     minfo->features.pll.feed_div_min = 2;
0549     minfo->features.pll.feed_div_max = 24;
0550     minfo->features.pll.in_div_min   = 2;
0551     minfo->features.pll.in_div_max   = 63;
0552     minfo->features.pll.post_shift_max = 3;
0553     if (minfo->devflags.noinit)
0554         return;
0555     ti3026_setMCLK(minfo, 60000);
0556 }
0557 
0558 static void Ti3026_restore(struct matrox_fb_info *minfo)
0559 {
0560     int i;
0561     unsigned char progdac[6];
0562     struct matrox_hw_state *hw = &minfo->hw;
0563     CRITFLAGS
0564 
0565     DBG(__func__)
0566 
0567 #ifdef DEBUG
0568     dprintk(KERN_INFO "EXTVGA regs: ");
0569     for (i = 0; i < 6; i++)
0570         dprintk("%02X:", hw->CRTCEXT[i]);
0571     dprintk("\n");
0572 #endif
0573 
0574     CRITBEGIN
0575 
0576     pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
0577 
0578     CRITEND
0579 
0580     matroxfb_vgaHWrestore(minfo);
0581 
0582     CRITBEGIN
0583 
0584     minfo->crtc1.panpos = -1;
0585     for (i = 0; i < 6; i++)
0586         mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
0587 
0588     for (i = 0; i < 21; i++) {
0589         outTi3026(minfo, DACseq[i], hw->DACreg[i]);
0590     }
0591 
0592     outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
0593     progdac[0] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
0594     progdac[3] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
0595     outTi3026(minfo, TVP3026_XPLLADDR, 0x15);
0596     progdac[1] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
0597     progdac[4] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
0598     outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
0599     progdac[2] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
0600     progdac[5] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
0601 
0602     CRITEND
0603     if (memcmp(hw->DACclk, progdac, 6)) {
0604         /* agrhh... setting up PLL is very slow on Millennium... */
0605         /* Mystique PLL is locked in few ms, but Millennium PLL lock takes about 0.15 s... */
0606         /* Maybe even we should call schedule() ? */
0607 
0608         CRITBEGIN
0609         outTi3026(minfo, TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]);
0610         outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
0611         outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0);
0612         outTi3026(minfo, TVP3026_XPIXPLLDATA, 0);
0613 
0614         outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
0615         for (i = 0; i < 3; i++)
0616             outTi3026(minfo, TVP3026_XPIXPLLDATA, hw->DACclk[i]);
0617         /* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */
0618         if (hw->MiscOutReg & 0x08) {
0619             int tmout;
0620             outTi3026(minfo, TVP3026_XPLLADDR, 0x3F);
0621             for (tmout = 500000; tmout; --tmout) {
0622                 if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
0623                     break;
0624                 udelay(10);
0625             }
0626 
0627             CRITEND
0628 
0629             if (!tmout)
0630                 printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
0631             else
0632                 dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout);
0633             CRITBEGIN
0634         }
0635         outTi3026(minfo, TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]);
0636         outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
0637         for (i = 3; i < 6; i++)
0638             outTi3026(minfo, TVP3026_XLOOPPLLDATA, hw->DACclk[i]);
0639         CRITEND
0640         if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) {
0641             int tmout;
0642 
0643             CRITBEGIN
0644             outTi3026(minfo, TVP3026_XPLLADDR, 0x3F);
0645             for (tmout = 500000; tmout; --tmout) {
0646                 if (inTi3026(minfo, TVP3026_XLOOPPLLDATA) & 0x40)
0647                     break;
0648                 udelay(10);
0649             }
0650             CRITEND
0651             if (!tmout)
0652                 printk(KERN_ERR "matroxfb: Loop PLL not locked after 5 secs\n");
0653             else
0654                 dprintk(KERN_INFO "LoopPLL: %d\n", 500000-tmout);
0655         }
0656     }
0657 
0658 #ifdef DEBUG
0659     dprintk(KERN_DEBUG "3026DACregs ");
0660     for (i = 0; i < 21; i++) {
0661         dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]);
0662         if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
0663     }
0664     dprintk(KERN_DEBUG "DACclk ");
0665     for (i = 0; i < 6; i++)
0666         dprintk("C%02X=%02X ", i, hw->DACclk[i]);
0667     dprintk("\n");
0668 #endif
0669 }
0670 
0671 static void Ti3026_reset(struct matrox_fb_info *minfo)
0672 {
0673     DBG(__func__)
0674 
0675     ti3026_ramdac_init(minfo);
0676 }
0677 
0678 static struct matrox_altout ti3026_output = {
0679     .name    = "Primary output",
0680 };
0681 
0682 static int Ti3026_preinit(struct matrox_fb_info *minfo)
0683 {
0684     static const int vxres_mill2[] = { 512,        640, 768,  800,  832,  960,
0685                       1024, 1152, 1280,      1600, 1664, 1920,
0686                       2048, 0};
0687     static const int vxres_mill1[] = {             640, 768,  800,        960,
0688                       1024, 1152, 1280,      1600,       1920,
0689                       2048, 0};
0690     struct matrox_hw_state *hw = &minfo->hw;
0691 
0692     DBG(__func__)
0693 
0694     minfo->millenium = 1;
0695     minfo->milleniumII = (minfo->pcidev->device != PCI_DEVICE_ID_MATROX_MIL);
0696     minfo->capable.cfb4 = 1;
0697     minfo->capable.text = 1; /* isMilleniumII(minfo); */
0698     minfo->capable.vxres = isMilleniumII(minfo) ? vxres_mill2 : vxres_mill1;
0699 
0700     minfo->outputs[0].data = minfo;
0701     minfo->outputs[0].output = &ti3026_output;
0702     minfo->outputs[0].src = minfo->outputs[0].default_src;
0703     minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
0704 
0705     if (minfo->devflags.noinit)
0706         return 0;
0707     /* preserve VGA I/O, BIOS and PPC */
0708     hw->MXoptionReg &= 0xC0000100;
0709     hw->MXoptionReg |= 0x002C0000;
0710     if (minfo->devflags.novga)
0711         hw->MXoptionReg &= ~0x00000100;
0712     if (minfo->devflags.nobios)
0713         hw->MXoptionReg &= ~0x40000000;
0714     if (minfo->devflags.nopciretry)
0715         hw->MXoptionReg |=  0x20000000;
0716     pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
0717 
0718     minfo->accel.ramdac_rev = inTi3026(minfo, TVP3026_XSILICONREV);
0719 
0720     outTi3026(minfo, TVP3026_XCLKCTRL, TVP3026_XCLKCTRL_SRC_CLK0VGA | TVP3026_XCLKCTRL_CLKSTOPPED);
0721     outTi3026(minfo, TVP3026_XTRUECOLORCTRL, TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR);
0722     outTi3026(minfo, TVP3026_XMUXCTRL, TVP3026_XMUXCTRL_VGA);
0723 
0724     outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
0725     outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0x00);
0726     outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
0727 
0728     mga_outb(M_MISC_REG, 0x67);
0729 
0730     outTi3026(minfo, TVP3026_XMEMPLLCTRL, TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
0731 
0732     mga_outl(M_RESET, 1);
0733     udelay(250);
0734     mga_outl(M_RESET, 0);
0735     udelay(250);
0736     mga_outl(M_MACCESS, 0x00008000);
0737     udelay(10);
0738     return 0;
0739 }
0740 
0741 struct matrox_switch matrox_millennium = {
0742     .preinit    = Ti3026_preinit,
0743     .reset      = Ti3026_reset,
0744     .init       = Ti3026_init,
0745     .restore    = Ti3026_restore
0746 };
0747 EXPORT_SYMBOL(matrox_millennium);
0748 #endif
0749 MODULE_LICENSE("GPL");