PageRenderTime 42ms CodeModel.GetById 12ms app.highlight 25ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/video/matrox/matroxfb_Ti3026.c

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t
C | 745 lines | 564 code | 77 blank | 104 comment | 70 complexity | c31f6fffe5abfe01b69172a258eb1284 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  1/*
  2 *
  3 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
  4 *
  5 * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
  6 *
  7 * Portions Copyright (c) 2001 Matrox Graphics Inc.
  8 *
  9 * Version: 1.65 2002/08/14
 10 *
 11 * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
 12 *
 13 * Contributors: "menion?" <menion@mindless.com>
 14 *                     Betatesting, fixes, ideas
 15 *
 16 *               "Kurt Garloff" <garloff@suse.de>
 17 *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
 18 *
 19 *               "Tom Rini" <trini@kernel.crashing.org>
 20 *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
 21 *
 22 *               "Bibek Sahu" <scorpio@dodds.net>
 23 *                     Access device through readb|w|l and write b|w|l
 24 *                     Extensive debugging stuff
 25 *
 26 *               "Daniel Haun" <haund@usa.net>
 27 *                     Testing, hardware cursor fixes
 28 *
 29 *               "Scott Wood" <sawst46+@pitt.edu>
 30 *                     Fixes
 31 *
 32 *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
 33 *                     Betatesting
 34 *
 35 *               "Kelly French" <targon@hazmat.com>
 36 *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
 37 *                     Betatesting, bug reporting
 38 *
 39 *               "Pablo Bianucci" <pbian@pccp.com.ar>
 40 *                     Fixes, ideas, betatesting
 41 *
 42 *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
 43 *                     Fixes, enhandcements, ideas, betatesting
 44 *
 45 *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
 46 *                     PPC betatesting, PPC support, backward compatibility
 47 *
 48 *               "Paul Womar" <Paul@pwomar.demon.co.uk>
 49 *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
 50 *                     PPC betatesting
 51 *
 52 *               "Thomas Pornin" <pornin@bolet.ens.fr>
 53 *                     Alpha betatesting
 54 *
 55 *               "Pieter van Leuven" <pvl@iae.nl>
 56 *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
 57 *                     G100 testing
 58 *
 59 *               "H. Peter Arvin" <hpa@transmeta.com>
 60 *                     Ideas
 61 *
 62 *               "Cort Dougan" <cort@cs.nmt.edu>
 63 *                     CHRP fixes and PReP cleanup
 64 *
 65 *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
 66 *                     G400 support
 67 *
 68 * (following author is not in any relation with this code, but his code
 69 *  is included in this driver)
 70 *
 71 * Based on framebuffer driver for VBE 2.0 compliant graphic boards
 72 *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
 73 *
 74 * (following author is not in any relation with this code, but his ideas
 75 *  were used when writing this driver)
 76 *
 77 *		 FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
 78 *
 79 */
 80
 81
 82#include "matroxfb_Ti3026.h"
 83#include "matroxfb_misc.h"
 84#include "matroxfb_accel.h"
 85#include <linux/matroxfb.h>
 86
 87#ifdef CONFIG_FB_MATROX_MILLENIUM
 88#define outTi3026 matroxfb_DAC_out
 89#define inTi3026 matroxfb_DAC_in
 90
 91#define TVP3026_INDEX		0x00
 92#define TVP3026_PALWRADD	0x00
 93#define TVP3026_PALDATA		0x01
 94#define TVP3026_PIXRDMSK	0x02
 95#define TVP3026_PALRDADD	0x03
 96#define TVP3026_CURCOLWRADD	0x04
 97#define     TVP3026_CLOVERSCAN		0x00
 98#define     TVP3026_CLCOLOR0		0x01
 99#define     TVP3026_CLCOLOR1		0x02
100#define     TVP3026_CLCOLOR2		0x03
101#define TVP3026_CURCOLDATA	0x05
102#define TVP3026_CURCOLRDADD	0x07
103#define TVP3026_CURCTRL		0x09
104#define TVP3026_X_DATAREG	0x0A
105#define TVP3026_CURRAMDATA	0x0B
106#define TVP3026_CURPOSXL	0x0C
107#define TVP3026_CURPOSXH	0x0D
108#define TVP3026_CURPOSYL	0x0E
109#define TVP3026_CURPOSYH	0x0F
110
111#define TVP3026_XSILICONREV	0x01
112#define TVP3026_XCURCTRL	0x06
113#define     TVP3026_XCURCTRL_DIS	0x00	/* transparent, transparent, transparent, transparent */
114#define     TVP3026_XCURCTRL_3COLOR	0x01	/* transparent, 0, 1, 2 */
115#define     TVP3026_XCURCTRL_XGA	0x02	/* 0, 1, transparent, complement */
116#define     TVP3026_XCURCTRL_XWIN	0x03	/* transparent, transparent, 0, 1 */
117#define     TVP3026_XCURCTRL_BLANK2048	0x00
118#define     TVP3026_XCURCTRL_BLANK4096	0x10
119#define     TVP3026_XCURCTRL_INTERLACED	0x20
120#define     TVP3026_XCURCTRL_ODD	0x00 /* ext.signal ODD/\EVEN */
121#define     TVP3026_XCURCTRL_EVEN	0x40 /* ext.signal EVEN/\ODD */
122#define     TVP3026_XCURCTRL_INDIRECT	0x00
123#define     TVP3026_XCURCTRL_DIRECT	0x80
124#define TVP3026_XLATCHCTRL	0x0F
125#define     TVP3026_XLATCHCTRL_1_1	0x06
126#define     TVP3026_XLATCHCTRL_2_1	0x07
127#define     TVP3026_XLATCHCTRL_4_1	0x06
128#define     TVP3026_XLATCHCTRL_8_1	0x06
129#define     TVP3026_XLATCHCTRL_16_1	0x06
130#define     TVP3026A_XLATCHCTRL_4_3	0x06	/* ??? do not understand... but it works... !!! */
131#define     TVP3026A_XLATCHCTRL_8_3	0x07
132#define     TVP3026B_XLATCHCTRL_4_3	0x08
133#define     TVP3026B_XLATCHCTRL_8_3	0x06	/* ??? do not understand... but it works... !!! */
134#define TVP3026_XTRUECOLORCTRL	0x18
135#define     TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_ACCEL	0x00
136#define     TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_TVP	0x20
137#define     TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR		0x80
138#define     TVP3026_XTRUECOLORCTRL_TRUECOLOR		0x40 /* paletized */
139#define     TVP3026_XTRUECOLORCTRL_DIRECTCOLOR		0x00
140#define     TVP3026_XTRUECOLORCTRL_24_ALTERNATE		0x08 /* 5:4/5:2 instead of 4:3/8:3 */
141#define     TVP3026_XTRUECOLORCTRL_RGB_888		0x16 /* 4:3/8:3 (or 5:4/5:2) */
142#define	    TVP3026_XTRUECOLORCTRL_BGR_888		0x17
143#define     TVP3026_XTRUECOLORCTRL_ORGB_8888		0x06
144#define     TVP3026_XTRUECOLORCTRL_BGRO_8888		0x07
145#define     TVP3026_XTRUECOLORCTRL_RGB_565		0x05
146#define     TVP3026_XTRUECOLORCTRL_ORGB_1555		0x04
147#define     TVP3026_XTRUECOLORCTRL_RGB_664		0x03
148#define     TVP3026_XTRUECOLORCTRL_RGBO_4444		0x01
149#define TVP3026_XMUXCTRL	0x19
150#define     TVP3026_XMUXCTRL_MEMORY_8BIT			0x01 /* - */
151#define     TVP3026_XMUXCTRL_MEMORY_16BIT			0x02 /* - */
152#define     TVP3026_XMUXCTRL_MEMORY_32BIT			0x03 /* 2MB RAM, 512K * 4 */
153#define     TVP3026_XMUXCTRL_MEMORY_64BIT			0x04 /* >2MB RAM, 512K * 8 & more */
154#define     TVP3026_XMUXCTRL_PIXEL_4BIT				0x40 /* L0,H0,L1,H1... */
155#define     TVP3026_XMUXCTRL_PIXEL_4BIT_SWAPPED			0x60 /* H0,L0,H1,L1... */
156#define     TVP3026_XMUXCTRL_PIXEL_8BIT				0x48
157#define     TVP3026_XMUXCTRL_PIXEL_16BIT			0x50
158#define     TVP3026_XMUXCTRL_PIXEL_32BIT			0x58
159#define     TVP3026_XMUXCTRL_VGA				0x98 /* VGA MEMORY, 8BIT PIXEL */
160#define TVP3026_XCLKCTRL	0x1A
161#define     TVP3026_XCLKCTRL_DIV1	0x00
162#define     TVP3026_XCLKCTRL_DIV2	0x10
163#define     TVP3026_XCLKCTRL_DIV4	0x20
164#define     TVP3026_XCLKCTRL_DIV8	0x30
165#define     TVP3026_XCLKCTRL_DIV16	0x40
166#define     TVP3026_XCLKCTRL_DIV32	0x50
167#define     TVP3026_XCLKCTRL_DIV64	0x60
168#define     TVP3026_XCLKCTRL_CLKSTOPPED	0x70
169#define     TVP3026_XCLKCTRL_SRC_CLK0	0x00
170#define     TVP3026_XCLKCTRL_SRC_CLK1   0x01
171#define     TVP3026_XCLKCTRL_SRC_CLK2	0x02	/* CLK2 is TTL source*/
172#define     TVP3026_XCLKCTRL_SRC_NCLK2	0x03	/* not CLK2 is TTL source */
173#define     TVP3026_XCLKCTRL_SRC_ECLK2	0x04	/* CLK2 and not CLK2 is ECL source */
174#define     TVP3026_XCLKCTRL_SRC_PLL	0x05
175#define     TVP3026_XCLKCTRL_SRC_DIS	0x06	/* disable & poweroff internal clock */
176#define     TVP3026_XCLKCTRL_SRC_CLK0VGA 0x07
177#define TVP3026_XPALETTEPAGE	0x1C
178#define TVP3026_XGENCTRL	0x1D
179#define     TVP3026_XGENCTRL_HSYNC_POS	0x00
180#define     TVP3026_XGENCTRL_HSYNC_NEG	0x01
181#define     TVP3026_XGENCTRL_VSYNC_POS	0x00
182#define     TVP3026_XGENCTRL_VSYNC_NEG	0x02
183#define     TVP3026_XGENCTRL_LITTLE_ENDIAN 0x00
184#define     TVP3026_XGENCTRL_BIG_ENDIAN    0x08
185#define     TVP3026_XGENCTRL_BLACK_0IRE		0x00
186#define     TVP3026_XGENCTRL_BLACK_75IRE	0x10
187#define     TVP3026_XGENCTRL_NO_SYNC_ON_GREEN	0x00
188#define     TVP3026_XGENCTRL_SYNC_ON_GREEN	0x20
189#define     TVP3026_XGENCTRL_OVERSCAN_DIS	0x00
190#define     TVP3026_XGENCTRL_OVERSCAN_EN	0x40
191#define TVP3026_XMISCCTRL	0x1E
192#define     TVP3026_XMISCCTRL_DAC_PUP	0x00
193#define     TVP3026_XMISCCTRL_DAC_PDOWN	0x01
194#define     TVP3026_XMISCCTRL_DAC_EXT	0x00 /* or 8, bit 3 is ignored */
195#define     TVP3026_XMISCCTRL_DAC_6BIT	0x04
196#define     TVP3026_XMISCCTRL_DAC_8BIT	0x0C
197#define     TVP3026_XMISCCTRL_PSEL_DIS	0x00
198#define     TVP3026_XMISCCTRL_PSEL_EN	0x10
199#define     TVP3026_XMISCCTRL_PSEL_LOW	0x00 /* PSEL high selects directcolor */
200#define     TVP3026_XMISCCTRL_PSEL_HIGH 0x20 /* PSEL high selects truecolor or pseudocolor */
201#define TVP3026_XGENIOCTRL	0x2A
202#define TVP3026_XGENIODATA	0x2B
203#define TVP3026_XPLLADDR	0x2C
204#define     TVP3026_XPLLADDR_X(LOOP,MCLK,PIX) (((LOOP)<<4) | ((MCLK)<<2) | (PIX))
205#define     TVP3026_XPLLDATA_N		0x00
206#define     TVP3026_XPLLDATA_M		0x01
207#define     TVP3026_XPLLDATA_P		0x02
208#define     TVP3026_XPLLDATA_STAT	0x03
209#define TVP3026_XPIXPLLDATA	0x2D
210#define TVP3026_XMEMPLLDATA	0x2E
211#define TVP3026_XLOOPPLLDATA	0x2F
212#define TVP3026_XCOLKEYOVRMIN	0x30
213#define TVP3026_XCOLKEYOVRMAX	0x31
214#define TVP3026_XCOLKEYREDMIN	0x32
215#define TVP3026_XCOLKEYREDMAX	0x33
216#define TVP3026_XCOLKEYGREENMIN	0x34
217#define TVP3026_XCOLKEYGREENMAX	0x35
218#define TVP3026_XCOLKEYBLUEMIN	0x36
219#define TVP3026_XCOLKEYBLUEMAX	0x37
220#define TVP3026_XCOLKEYCTRL	0x38
221#define     TVP3026_XCOLKEYCTRL_OVR_EN	0x01
222#define     TVP3026_XCOLKEYCTRL_RED_EN	0x02
223#define     TVP3026_XCOLKEYCTRL_GREEN_EN 0x04
224#define     TVP3026_XCOLKEYCTRL_BLUE_EN	0x08
225#define     TVP3026_XCOLKEYCTRL_NEGATE	0x10
226#define     TVP3026_XCOLKEYCTRL_ZOOM1	0x00
227#define     TVP3026_XCOLKEYCTRL_ZOOM2	0x20
228#define     TVP3026_XCOLKEYCTRL_ZOOM4	0x40
229#define     TVP3026_XCOLKEYCTRL_ZOOM8	0x60
230#define     TVP3026_XCOLKEYCTRL_ZOOM16	0x80
231#define     TVP3026_XCOLKEYCTRL_ZOOM32	0xA0
232#define TVP3026_XMEMPLLCTRL	0x39
233#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 */
234#define     TVP3026_XMEMPLLCTRL_STROBEMKC4	0x08
235#define     TVP3026_XMEMPLLCTRL_MCLK_DOTCLOCK	0x00	/* MKC4 */
236#define     TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL	0x10	/* MKC4 */
237#define     TVP3026_XMEMPLLCTRL_RCLK_PIXPLL	0x00
238#define     TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL	0x20
239#define     TVP3026_XMEMPLLCTRL_RCLK_DOTDIVN	0x40	/* dot clock divided by loop pclk N prescaler */
240#define TVP3026_XSENSETEST	0x3A
241#define TVP3026_XTESTMODEDATA	0x3B
242#define TVP3026_XCRCREML	0x3C
243#define TVP3026_XCRCREMH	0x3D
244#define TVP3026_XCRCBITSEL	0x3E
245#define TVP3026_XID		0x3F
246
247static const unsigned char DACseq[] =
248{ TVP3026_XLATCHCTRL, TVP3026_XTRUECOLORCTRL,
249  TVP3026_XMUXCTRL, TVP3026_XCLKCTRL,
250  TVP3026_XPALETTEPAGE,
251  TVP3026_XGENCTRL,
252  TVP3026_XMISCCTRL,
253  TVP3026_XGENIOCTRL,
254  TVP3026_XGENIODATA,
255  TVP3026_XCOLKEYOVRMIN, TVP3026_XCOLKEYOVRMAX, TVP3026_XCOLKEYREDMIN, TVP3026_XCOLKEYREDMAX,
256  TVP3026_XCOLKEYGREENMIN, TVP3026_XCOLKEYGREENMAX, TVP3026_XCOLKEYBLUEMIN, TVP3026_XCOLKEYBLUEMAX,
257  TVP3026_XCOLKEYCTRL,
258  TVP3026_XMEMPLLCTRL, TVP3026_XSENSETEST, TVP3026_XCURCTRL };
259
260#define POS3026_XLATCHCTRL	0
261#define POS3026_XTRUECOLORCTRL	1
262#define POS3026_XMUXCTRL	2
263#define POS3026_XCLKCTRL	3
264#define POS3026_XGENCTRL	5
265#define POS3026_XMISCCTRL	6
266#define POS3026_XMEMPLLCTRL	18
267#define POS3026_XCURCTRL	20
268
269static const unsigned char MGADACbpp32[] =
270{ TVP3026_XLATCHCTRL_2_1, TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_8888,
271  0x00, TVP3026_XCLKCTRL_DIV1 | TVP3026_XCLKCTRL_SRC_PLL,
272  0x00,
273  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,
274  TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_HIGH,
275  0x00,
276  0x1E,
277  0xFF, 0xFF, 0xFF, 0xFF,
278  0xFF, 0xFF, 0xFF, 0xFF,
279  TVP3026_XCOLKEYCTRL_ZOOM1,
280  0x00, 0x00, TVP3026_XCURCTRL_DIS };
281
282static int Ti3026_calcclock(const struct matrox_fb_info *minfo,
283			    unsigned int freq, unsigned int fmax, int *in,
284			    int *feed, int *post)
285{
286	unsigned int fvco;
287	unsigned int lin, lfeed, lpost;
288
289	DBG(__func__)
290
291	fvco = PLL_calcclock(minfo, freq, fmax, &lin, &lfeed, &lpost);
292	fvco >>= (*post = lpost);
293	*in = 64 - lin;
294	*feed = 64 - lfeed;
295	return fvco;
296}
297
298static int Ti3026_setpclk(struct matrox_fb_info *minfo, int clk)
299{
300	unsigned int f_pll;
301	unsigned int pixfeed, pixin, pixpost;
302	struct matrox_hw_state *hw = &minfo->hw;
303
304	DBG(__func__)
305
306	f_pll = Ti3026_calcclock(minfo, clk, minfo->max_pixel_clock, &pixin, &pixfeed, &pixpost);
307
308	hw->DACclk[0] = pixin | 0xC0;
309	hw->DACclk[1] = pixfeed;
310	hw->DACclk[2] = pixpost | 0xB0;
311
312	{
313		unsigned int loopfeed, loopin, looppost, loopdiv, z;
314		unsigned int Bpp;
315
316		Bpp = minfo->curr.final_bppShift;
317
318		if (minfo->fbcon.var.bits_per_pixel == 24) {
319			loopfeed = 3;		/* set lm to any possible value */
320			loopin = 3 * 32 / Bpp;
321		} else {
322			loopfeed = 4;
323			loopin = 4 * 32 / Bpp;
324		}
325		z = (110000 * loopin) / (f_pll * loopfeed);
326		loopdiv = 0; /* div 2 */
327		if (z < 2)
328			looppost = 0;
329		else if (z < 4)
330			looppost = 1;
331		else if (z < 8)
332			looppost = 2;
333		else {
334			looppost = 3;
335			loopdiv = z/16;
336		}
337		if (minfo->fbcon.var.bits_per_pixel == 24) {
338			hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
339			hw->DACclk[4] = (65 - loopfeed) | 0x80;
340			if (minfo->accel.ramdac_rev > 0x20) {
341				if (isInterleave(minfo))
342					hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3;
343				else {
344					hw->DACclk[4] &= ~0xC0;
345					hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3;
346				}
347			} else {
348				if (isInterleave(minfo))
349					;	/* default... */
350				else {
351					hw->DACclk[4] ^= 0xC0;	/* change from 0x80 to 0x40 */
352					hw->DACreg[POS3026_XLATCHCTRL] = TVP3026A_XLATCHCTRL_4_3;
353				}
354			}
355			hw->DACclk[5] = looppost | 0xF8;
356			if (minfo->devflags.mga_24bpp_fix)
357				hw->DACclk[5] ^= 0x40;
358		} else {
359			hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
360			hw->DACclk[4] = 65 - loopfeed;
361			hw->DACclk[5] = looppost | 0xF0;
362		}
363		hw->DACreg[POS3026_XMEMPLLCTRL] = loopdiv | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL;
364	}
365	return 0;
366}
367
368static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m)
369{
370	u_int8_t muxctrl = isInterleave(minfo) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT;
371	struct matrox_hw_state *hw = &minfo->hw;
372
373	DBG(__func__)
374
375	memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
376	switch (minfo->fbcon.var.bits_per_pixel) {
377		case 4:	hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1;	/* or _8_1, they are same */
378			hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
379			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_4BIT;
380			hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV8;
381			hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
382			break;
383		case 8: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_8_1;	/* or _4_1, they are same */
384			hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
385			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_8BIT;
386			hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4;
387			hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
388			break;
389		case 16:
390			/* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used every time) */
391			hw->DACreg[POS3026_XTRUECOLORCTRL] = (minfo->fbcon.var.green.length == 5) ? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565);
392			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT;
393			hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2;
394			break;
395		case 24:
396			/* XLATCHCTRL is: for (A) use _4_3 (?_8_3 is same? TBD), for (B) it is set in setpclk */
397			hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_888;
398			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT;
399			hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4;
400			break;
401		case 32:
402			/* XLATCHCTRL should be _2_1 / _1_1... Why is not? (_2_1 is used every time) */
403			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT;
404			break;
405		default:
406			return 1;	/* TODO: failed */
407	}
408	if (matroxfb_vgaHWinit(minfo, m)) return 1;
409
410	/* set SYNC */
411	hw->MiscOutReg = 0xCB;
412	if (m->sync & FB_SYNC_HOR_HIGH_ACT)
413		hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_HSYNC_NEG;
414	if (m->sync & FB_SYNC_VERT_HIGH_ACT)
415		hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_VSYNC_NEG;
416	if (m->sync & FB_SYNC_ON_GREEN)
417		hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_SYNC_ON_GREEN;
418
419	/* set DELAY */
420	if (minfo->video.len < 0x400000)
421		hw->CRTCEXT[3] |= 0x08;
422	else if (minfo->video.len > 0x400000)
423		hw->CRTCEXT[3] |= 0x10;
424
425	/* set HWCURSOR */
426	if (m->interlaced) {
427		hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_INTERLACED;
428	}
429	if (m->HTotal >= 1536)
430		hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_BLANK4096;
431
432	/* set interleaving */
433	hw->MXoptionReg &= ~0x00001000;
434	if (isInterleave(minfo)) hw->MXoptionReg |= 0x00001000;
435
436	/* set DAC */
437	Ti3026_setpclk(minfo, m->pixclock);
438	return 0;
439}
440
441static void ti3026_setMCLK(struct matrox_fb_info *minfo, int fout)
442{
443	unsigned int f_pll;
444	unsigned int pclk_m, pclk_n, pclk_p;
445	unsigned int mclk_m, mclk_n, mclk_p;
446	unsigned int rfhcnt, mclk_ctl;
447	int tmout;
448
449	DBG(__func__)
450
451	f_pll = Ti3026_calcclock(minfo, fout, minfo->max_pixel_clock, &mclk_n, &mclk_m, &mclk_p);
452
453	/* save pclk */
454	outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
455	pclk_n = inTi3026(minfo, TVP3026_XPIXPLLDATA);
456	outTi3026(minfo, TVP3026_XPLLADDR, 0xFD);
457	pclk_m = inTi3026(minfo, TVP3026_XPIXPLLDATA);
458	outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
459	pclk_p = inTi3026(minfo, TVP3026_XPIXPLLDATA);
460
461	/* stop pclk */
462	outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
463	outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
464
465	/* set pclk to new mclk */
466	outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
467	outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_n | 0xC0);
468	outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_m);
469	outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_p | 0xB0);
470
471	/* wait for PLL to lock */
472	for (tmout = 500000; tmout; tmout--) {
473		if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
474			break;
475		udelay(10);
476	};
477	if (!tmout)
478		printk(KERN_ERR "matroxfb: Temporary pixel PLL not locked after 5 secs\n");
479
480	/* output pclk on mclk pin */
481	mclk_ctl = inTi3026(minfo, TVP3026_XMEMPLLCTRL);
482	outTi3026(minfo, TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7);
483	outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4);
484
485	/* stop MCLK */
486	outTi3026(minfo, TVP3026_XPLLADDR, 0xFB);
487	outTi3026(minfo, TVP3026_XMEMPLLDATA, 0x00);
488
489	/* set mclk to new freq */
490	outTi3026(minfo, TVP3026_XPLLADDR, 0xF3);
491	outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_n | 0xC0);
492	outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_m);
493	outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_p | 0xB0);
494
495	/* wait for PLL to lock */
496	for (tmout = 500000; tmout; tmout--) {
497		if (inTi3026(minfo, TVP3026_XMEMPLLDATA) & 0x40)
498			break;
499		udelay(10);
500	}
501	if (!tmout)
502		printk(KERN_ERR "matroxfb: Memory PLL not locked after 5 secs\n");
503
504	f_pll = f_pll * 333 / (10000 << mclk_p);
505	if (isMilleniumII(minfo)) {
506		rfhcnt = (f_pll - 128) / 256;
507		if (rfhcnt > 15)
508			rfhcnt = 15;
509	} else {
510		rfhcnt = (f_pll - 64) / 128;
511		if (rfhcnt > 15)
512			rfhcnt = 0;
513	}
514	minfo->hw.MXoptionReg = (minfo->hw.MXoptionReg & ~0x000F0000) | (rfhcnt << 16);
515	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
516
517	/* output MCLK to MCLK pin */
518	outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
519	outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl       ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4);
520
521	/* stop PCLK */
522	outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
523	outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
524
525	/* restore pclk */
526	outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
527	outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_n);
528	outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_m);
529	outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_p);
530
531	/* wait for PLL to lock */
532	for (tmout = 500000; tmout; tmout--) {
533		if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
534			break;
535		udelay(10);
536	}
537	if (!tmout)
538		printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
539}
540
541static void ti3026_ramdac_init(struct matrox_fb_info *minfo)
542{
543	DBG(__func__)
544
545	minfo->features.pll.vco_freq_min = 110000;
546	minfo->features.pll.ref_freq	 = 114545;
547	minfo->features.pll.feed_div_min = 2;
548	minfo->features.pll.feed_div_max = 24;
549	minfo->features.pll.in_div_min	 = 2;
550	minfo->features.pll.in_div_max	 = 63;
551	minfo->features.pll.post_shift_max = 3;
552	if (minfo->devflags.noinit)
553		return;
554	ti3026_setMCLK(minfo, 60000);
555}
556
557static void Ti3026_restore(struct matrox_fb_info *minfo)
558{
559	int i;
560	unsigned char progdac[6];
561	struct matrox_hw_state *hw = &minfo->hw;
562	CRITFLAGS
563
564	DBG(__func__)
565
566#ifdef DEBUG
567	dprintk(KERN_INFO "EXTVGA regs: ");
568	for (i = 0; i < 6; i++)
569		dprintk("%02X:", hw->CRTCEXT[i]);
570	dprintk("\n");
571#endif
572
573	CRITBEGIN
574
575	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
576
577	CRITEND
578
579	matroxfb_vgaHWrestore(minfo);
580
581	CRITBEGIN
582
583	minfo->crtc1.panpos = -1;
584	for (i = 0; i < 6; i++)
585		mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
586
587	for (i = 0; i < 21; i++) {
588		outTi3026(minfo, DACseq[i], hw->DACreg[i]);
589	}
590
591	outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
592	progdac[0] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
593	progdac[3] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
594	outTi3026(minfo, TVP3026_XPLLADDR, 0x15);
595	progdac[1] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
596	progdac[4] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
597	outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
598	progdac[2] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
599	progdac[5] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
600
601	CRITEND
602	if (memcmp(hw->DACclk, progdac, 6)) {
603		/* agrhh... setting up PLL is very slow on Millennium... */
604		/* Mystique PLL is locked in few ms, but Millennium PLL lock takes about 0.15 s... */
605		/* Maybe even we should call schedule() ? */
606
607		CRITBEGIN
608		outTi3026(minfo, TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]);
609		outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
610		outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0);
611		outTi3026(minfo, TVP3026_XPIXPLLDATA, 0);
612
613		outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
614		for (i = 0; i < 3; i++)
615			outTi3026(minfo, TVP3026_XPIXPLLDATA, hw->DACclk[i]);
616		/* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */
617		if (hw->MiscOutReg & 0x08) {
618			int tmout;
619			outTi3026(minfo, TVP3026_XPLLADDR, 0x3F);
620			for (tmout = 500000; tmout; --tmout) {
621				if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
622					break;
623				udelay(10);
624			}
625
626			CRITEND
627
628			if (!tmout)
629				printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
630			else
631				dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout);
632			CRITBEGIN
633		}
634		outTi3026(minfo, TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]);
635		outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
636		for (i = 3; i < 6; i++)
637			outTi3026(minfo, TVP3026_XLOOPPLLDATA, hw->DACclk[i]);
638		CRITEND
639		if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) {
640			int tmout;
641
642			CRITBEGIN
643			outTi3026(minfo, TVP3026_XPLLADDR, 0x3F);
644			for (tmout = 500000; tmout; --tmout) {
645				if (inTi3026(minfo, TVP3026_XLOOPPLLDATA) & 0x40)
646					break;
647				udelay(10);
648			}
649			CRITEND
650			if (!tmout)
651				printk(KERN_ERR "matroxfb: Loop PLL not locked after 5 secs\n");
652			else
653				dprintk(KERN_INFO "LoopPLL: %d\n", 500000-tmout);
654		}
655	}
656
657#ifdef DEBUG
658	dprintk(KERN_DEBUG "3026DACregs ");
659	for (i = 0; i < 21; i++) {
660		dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]);
661		if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
662	}
663	dprintk(KERN_DEBUG "DACclk ");
664	for (i = 0; i < 6; i++)
665		dprintk("C%02X=%02X ", i, hw->DACclk[i]);
666	dprintk("\n");
667#endif
668}
669
670static void Ti3026_reset(struct matrox_fb_info *minfo)
671{
672	DBG(__func__)
673
674	ti3026_ramdac_init(minfo);
675}
676
677static struct matrox_altout ti3026_output = {
678	.name	 = "Primary output",
679};
680
681static int Ti3026_preinit(struct matrox_fb_info *minfo)
682{
683	static const int vxres_mill2[] = { 512,        640, 768,  800,  832,  960,
684					  1024, 1152, 1280,      1600, 1664, 1920,
685					  2048, 0};
686	static const int vxres_mill1[] = {             640, 768,  800,        960,
687					  1024, 1152, 1280,      1600,       1920,
688					  2048, 0};
689	struct matrox_hw_state *hw = &minfo->hw;
690
691	DBG(__func__)
692
693	minfo->millenium = 1;
694	minfo->milleniumII = (minfo->pcidev->device != PCI_DEVICE_ID_MATROX_MIL);
695	minfo->capable.cfb4 = 1;
696	minfo->capable.text = 1; /* isMilleniumII(minfo); */
697	minfo->capable.vxres = isMilleniumII(minfo) ? vxres_mill2 : vxres_mill1;
698
699	minfo->outputs[0].data = minfo;
700	minfo->outputs[0].output = &ti3026_output;
701	minfo->outputs[0].src = minfo->outputs[0].default_src;
702	minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
703
704	if (minfo->devflags.noinit)
705		return 0;
706	/* preserve VGA I/O, BIOS and PPC */
707	hw->MXoptionReg &= 0xC0000100;
708	hw->MXoptionReg |= 0x002C0000;
709	if (minfo->devflags.novga)
710		hw->MXoptionReg &= ~0x00000100;
711	if (minfo->devflags.nobios)
712		hw->MXoptionReg &= ~0x40000000;
713	if (minfo->devflags.nopciretry)
714		hw->MXoptionReg |=  0x20000000;
715	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
716
717	minfo->accel.ramdac_rev = inTi3026(minfo, TVP3026_XSILICONREV);
718
719	outTi3026(minfo, TVP3026_XCLKCTRL, TVP3026_XCLKCTRL_SRC_CLK0VGA | TVP3026_XCLKCTRL_CLKSTOPPED);
720	outTi3026(minfo, TVP3026_XTRUECOLORCTRL, TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR);
721	outTi3026(minfo, TVP3026_XMUXCTRL, TVP3026_XMUXCTRL_VGA);
722
723	outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
724	outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0x00);
725	outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
726
727	mga_outb(M_MISC_REG, 0x67);
728
729	outTi3026(minfo, TVP3026_XMEMPLLCTRL, TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
730
731	mga_outl(M_RESET, 1);
732	udelay(250);
733	mga_outl(M_RESET, 0);
734	udelay(250);
735	mga_outl(M_MACCESS, 0x00008000);
736	udelay(10);
737	return 0;
738}
739
740struct matrox_switch matrox_millennium = {
741	Ti3026_preinit, Ti3026_reset, Ti3026_init, Ti3026_restore
742};
743EXPORT_SYMBOL(matrox_millennium);
744#endif
745MODULE_LICENSE("GPL");