162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Portions Copyright (c) 2001 Matrox Graphics Inc. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Version: 1.65 2002/08/14 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org> 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Contributors: "menion?" <menion@mindless.com> 1562306a36Sopenharmony_ci * Betatesting, fixes, ideas 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * "Kurt Garloff" <garloff@suse.de> 1862306a36Sopenharmony_ci * Betatesting, fixes, ideas, videomodes, videomodes timmings 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * "Tom Rini" <trini@kernel.crashing.org> 2162306a36Sopenharmony_ci * MTRR stuff, PPC cleanups, betatesting, fixes, ideas 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * "Bibek Sahu" <scorpio@dodds.net> 2462306a36Sopenharmony_ci * Access device through readb|w|l and write b|w|l 2562306a36Sopenharmony_ci * Extensive debugging stuff 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * "Daniel Haun" <haund@usa.net> 2862306a36Sopenharmony_ci * Testing, hardware cursor fixes 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * "Scott Wood" <sawst46+@pitt.edu> 3162306a36Sopenharmony_ci * Fixes 3262306a36Sopenharmony_ci * 3362306a36Sopenharmony_ci * "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de> 3462306a36Sopenharmony_ci * Betatesting 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * "Kelly French" <targon@hazmat.com> 3762306a36Sopenharmony_ci * "Fernando Herrera" <fherrera@eurielec.etsit.upm.es> 3862306a36Sopenharmony_ci * Betatesting, bug reporting 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci * "Pablo Bianucci" <pbian@pccp.com.ar> 4162306a36Sopenharmony_ci * Fixes, ideas, betatesting 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es> 4462306a36Sopenharmony_ci * Fixes, enhandcements, ideas, betatesting 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp> 4762306a36Sopenharmony_ci * PPC betatesting, PPC support, backward compatibility 4862306a36Sopenharmony_ci * 4962306a36Sopenharmony_ci * "Paul Womar" <Paul@pwomar.demon.co.uk> 5062306a36Sopenharmony_ci * "Owen Waller" <O.Waller@ee.qub.ac.uk> 5162306a36Sopenharmony_ci * PPC betatesting 5262306a36Sopenharmony_ci * 5362306a36Sopenharmony_ci * "Thomas Pornin" <pornin@bolet.ens.fr> 5462306a36Sopenharmony_ci * Alpha betatesting 5562306a36Sopenharmony_ci * 5662306a36Sopenharmony_ci * "Pieter van Leuven" <pvl@iae.nl> 5762306a36Sopenharmony_ci * "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de> 5862306a36Sopenharmony_ci * G100 testing 5962306a36Sopenharmony_ci * 6062306a36Sopenharmony_ci * "H. Peter Arvin" <hpa@transmeta.com> 6162306a36Sopenharmony_ci * Ideas 6262306a36Sopenharmony_ci * 6362306a36Sopenharmony_ci * "Cort Dougan" <cort@cs.nmt.edu> 6462306a36Sopenharmony_ci * CHRP fixes and PReP cleanup 6562306a36Sopenharmony_ci * 6662306a36Sopenharmony_ci * "Mark Vojkovich" <mvojkovi@ucsd.edu> 6762306a36Sopenharmony_ci * G400 support 6862306a36Sopenharmony_ci * 6962306a36Sopenharmony_ci * (following author is not in any relation with this code, but his code 7062306a36Sopenharmony_ci * is included in this driver) 7162306a36Sopenharmony_ci * 7262306a36Sopenharmony_ci * Based on framebuffer driver for VBE 2.0 compliant graphic boards 7362306a36Sopenharmony_ci * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> 7462306a36Sopenharmony_ci * 7562306a36Sopenharmony_ci * (following author is not in any relation with this code, but his ideas 7662306a36Sopenharmony_ci * were used when writing this driver) 7762306a36Sopenharmony_ci * 7862306a36Sopenharmony_ci * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk> 7962306a36Sopenharmony_ci * 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci#include "matroxfb_Ti3026.h" 8462306a36Sopenharmony_ci#include "matroxfb_misc.h" 8562306a36Sopenharmony_ci#include "matroxfb_accel.h" 8662306a36Sopenharmony_ci#include <linux/matroxfb.h> 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#ifdef CONFIG_FB_MATROX_MILLENIUM 8962306a36Sopenharmony_ci#define outTi3026 matroxfb_DAC_out 9062306a36Sopenharmony_ci#define inTi3026 matroxfb_DAC_in 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#define TVP3026_INDEX 0x00 9362306a36Sopenharmony_ci#define TVP3026_PALWRADD 0x00 9462306a36Sopenharmony_ci#define TVP3026_PALDATA 0x01 9562306a36Sopenharmony_ci#define TVP3026_PIXRDMSK 0x02 9662306a36Sopenharmony_ci#define TVP3026_PALRDADD 0x03 9762306a36Sopenharmony_ci#define TVP3026_CURCOLWRADD 0x04 9862306a36Sopenharmony_ci#define TVP3026_CLOVERSCAN 0x00 9962306a36Sopenharmony_ci#define TVP3026_CLCOLOR0 0x01 10062306a36Sopenharmony_ci#define TVP3026_CLCOLOR1 0x02 10162306a36Sopenharmony_ci#define TVP3026_CLCOLOR2 0x03 10262306a36Sopenharmony_ci#define TVP3026_CURCOLDATA 0x05 10362306a36Sopenharmony_ci#define TVP3026_CURCOLRDADD 0x07 10462306a36Sopenharmony_ci#define TVP3026_CURCTRL 0x09 10562306a36Sopenharmony_ci#define TVP3026_X_DATAREG 0x0A 10662306a36Sopenharmony_ci#define TVP3026_CURRAMDATA 0x0B 10762306a36Sopenharmony_ci#define TVP3026_CURPOSXL 0x0C 10862306a36Sopenharmony_ci#define TVP3026_CURPOSXH 0x0D 10962306a36Sopenharmony_ci#define TVP3026_CURPOSYL 0x0E 11062306a36Sopenharmony_ci#define TVP3026_CURPOSYH 0x0F 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#define TVP3026_XSILICONREV 0x01 11362306a36Sopenharmony_ci#define TVP3026_XCURCTRL 0x06 11462306a36Sopenharmony_ci#define TVP3026_XCURCTRL_DIS 0x00 /* transparent, transparent, transparent, transparent */ 11562306a36Sopenharmony_ci#define TVP3026_XCURCTRL_3COLOR 0x01 /* transparent, 0, 1, 2 */ 11662306a36Sopenharmony_ci#define TVP3026_XCURCTRL_XGA 0x02 /* 0, 1, transparent, complement */ 11762306a36Sopenharmony_ci#define TVP3026_XCURCTRL_XWIN 0x03 /* transparent, transparent, 0, 1 */ 11862306a36Sopenharmony_ci#define TVP3026_XCURCTRL_BLANK2048 0x00 11962306a36Sopenharmony_ci#define TVP3026_XCURCTRL_BLANK4096 0x10 12062306a36Sopenharmony_ci#define TVP3026_XCURCTRL_INTERLACED 0x20 12162306a36Sopenharmony_ci#define TVP3026_XCURCTRL_ODD 0x00 /* ext.signal ODD/\EVEN */ 12262306a36Sopenharmony_ci#define TVP3026_XCURCTRL_EVEN 0x40 /* ext.signal EVEN/\ODD */ 12362306a36Sopenharmony_ci#define TVP3026_XCURCTRL_INDIRECT 0x00 12462306a36Sopenharmony_ci#define TVP3026_XCURCTRL_DIRECT 0x80 12562306a36Sopenharmony_ci#define TVP3026_XLATCHCTRL 0x0F 12662306a36Sopenharmony_ci#define TVP3026_XLATCHCTRL_1_1 0x06 12762306a36Sopenharmony_ci#define TVP3026_XLATCHCTRL_2_1 0x07 12862306a36Sopenharmony_ci#define TVP3026_XLATCHCTRL_4_1 0x06 12962306a36Sopenharmony_ci#define TVP3026_XLATCHCTRL_8_1 0x06 13062306a36Sopenharmony_ci#define TVP3026_XLATCHCTRL_16_1 0x06 13162306a36Sopenharmony_ci#define TVP3026A_XLATCHCTRL_4_3 0x06 /* ??? do not understand... but it works... !!! */ 13262306a36Sopenharmony_ci#define TVP3026A_XLATCHCTRL_8_3 0x07 13362306a36Sopenharmony_ci#define TVP3026B_XLATCHCTRL_4_3 0x08 13462306a36Sopenharmony_ci#define TVP3026B_XLATCHCTRL_8_3 0x06 /* ??? do not understand... but it works... !!! */ 13562306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL 0x18 13662306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_ACCEL 0x00 13762306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_TVP 0x20 13862306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR 0x80 13962306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_TRUECOLOR 0x40 /* paletized */ 14062306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_DIRECTCOLOR 0x00 14162306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_24_ALTERNATE 0x08 /* 5:4/5:2 instead of 4:3/8:3 */ 14262306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_RGB_888 0x16 /* 4:3/8:3 (or 5:4/5:2) */ 14362306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_BGR_888 0x17 14462306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_ORGB_8888 0x06 14562306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_BGRO_8888 0x07 14662306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_RGB_565 0x05 14762306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_ORGB_1555 0x04 14862306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_RGB_664 0x03 14962306a36Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_RGBO_4444 0x01 15062306a36Sopenharmony_ci#define TVP3026_XMUXCTRL 0x19 15162306a36Sopenharmony_ci#define TVP3026_XMUXCTRL_MEMORY_8BIT 0x01 /* - */ 15262306a36Sopenharmony_ci#define TVP3026_XMUXCTRL_MEMORY_16BIT 0x02 /* - */ 15362306a36Sopenharmony_ci#define TVP3026_XMUXCTRL_MEMORY_32BIT 0x03 /* 2MB RAM, 512K * 4 */ 15462306a36Sopenharmony_ci#define TVP3026_XMUXCTRL_MEMORY_64BIT 0x04 /* >2MB RAM, 512K * 8 & more */ 15562306a36Sopenharmony_ci#define TVP3026_XMUXCTRL_PIXEL_4BIT 0x40 /* L0,H0,L1,H1... */ 15662306a36Sopenharmony_ci#define TVP3026_XMUXCTRL_PIXEL_4BIT_SWAPPED 0x60 /* H0,L0,H1,L1... */ 15762306a36Sopenharmony_ci#define TVP3026_XMUXCTRL_PIXEL_8BIT 0x48 15862306a36Sopenharmony_ci#define TVP3026_XMUXCTRL_PIXEL_16BIT 0x50 15962306a36Sopenharmony_ci#define TVP3026_XMUXCTRL_PIXEL_32BIT 0x58 16062306a36Sopenharmony_ci#define TVP3026_XMUXCTRL_VGA 0x98 /* VGA MEMORY, 8BIT PIXEL */ 16162306a36Sopenharmony_ci#define TVP3026_XCLKCTRL 0x1A 16262306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV1 0x00 16362306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV2 0x10 16462306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV4 0x20 16562306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV8 0x30 16662306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV16 0x40 16762306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV32 0x50 16862306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV64 0x60 16962306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_CLKSTOPPED 0x70 17062306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_CLK0 0x00 17162306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_CLK1 0x01 17262306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_CLK2 0x02 /* CLK2 is TTL source*/ 17362306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_NCLK2 0x03 /* not CLK2 is TTL source */ 17462306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_ECLK2 0x04 /* CLK2 and not CLK2 is ECL source */ 17562306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_PLL 0x05 17662306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_DIS 0x06 /* disable & poweroff internal clock */ 17762306a36Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_CLK0VGA 0x07 17862306a36Sopenharmony_ci#define TVP3026_XPALETTEPAGE 0x1C 17962306a36Sopenharmony_ci#define TVP3026_XGENCTRL 0x1D 18062306a36Sopenharmony_ci#define TVP3026_XGENCTRL_HSYNC_POS 0x00 18162306a36Sopenharmony_ci#define TVP3026_XGENCTRL_HSYNC_NEG 0x01 18262306a36Sopenharmony_ci#define TVP3026_XGENCTRL_VSYNC_POS 0x00 18362306a36Sopenharmony_ci#define TVP3026_XGENCTRL_VSYNC_NEG 0x02 18462306a36Sopenharmony_ci#define TVP3026_XGENCTRL_LITTLE_ENDIAN 0x00 18562306a36Sopenharmony_ci#define TVP3026_XGENCTRL_BIG_ENDIAN 0x08 18662306a36Sopenharmony_ci#define TVP3026_XGENCTRL_BLACK_0IRE 0x00 18762306a36Sopenharmony_ci#define TVP3026_XGENCTRL_BLACK_75IRE 0x10 18862306a36Sopenharmony_ci#define TVP3026_XGENCTRL_NO_SYNC_ON_GREEN 0x00 18962306a36Sopenharmony_ci#define TVP3026_XGENCTRL_SYNC_ON_GREEN 0x20 19062306a36Sopenharmony_ci#define TVP3026_XGENCTRL_OVERSCAN_DIS 0x00 19162306a36Sopenharmony_ci#define TVP3026_XGENCTRL_OVERSCAN_EN 0x40 19262306a36Sopenharmony_ci#define TVP3026_XMISCCTRL 0x1E 19362306a36Sopenharmony_ci#define TVP3026_XMISCCTRL_DAC_PUP 0x00 19462306a36Sopenharmony_ci#define TVP3026_XMISCCTRL_DAC_PDOWN 0x01 19562306a36Sopenharmony_ci#define TVP3026_XMISCCTRL_DAC_EXT 0x00 /* or 8, bit 3 is ignored */ 19662306a36Sopenharmony_ci#define TVP3026_XMISCCTRL_DAC_6BIT 0x04 19762306a36Sopenharmony_ci#define TVP3026_XMISCCTRL_DAC_8BIT 0x0C 19862306a36Sopenharmony_ci#define TVP3026_XMISCCTRL_PSEL_DIS 0x00 19962306a36Sopenharmony_ci#define TVP3026_XMISCCTRL_PSEL_EN 0x10 20062306a36Sopenharmony_ci#define TVP3026_XMISCCTRL_PSEL_LOW 0x00 /* PSEL high selects directcolor */ 20162306a36Sopenharmony_ci#define TVP3026_XMISCCTRL_PSEL_HIGH 0x20 /* PSEL high selects truecolor or pseudocolor */ 20262306a36Sopenharmony_ci#define TVP3026_XGENIOCTRL 0x2A 20362306a36Sopenharmony_ci#define TVP3026_XGENIODATA 0x2B 20462306a36Sopenharmony_ci#define TVP3026_XPLLADDR 0x2C 20562306a36Sopenharmony_ci#define TVP3026_XPLLADDR_X(LOOP,MCLK,PIX) (((LOOP)<<4) | ((MCLK)<<2) | (PIX)) 20662306a36Sopenharmony_ci#define TVP3026_XPLLDATA_N 0x00 20762306a36Sopenharmony_ci#define TVP3026_XPLLDATA_M 0x01 20862306a36Sopenharmony_ci#define TVP3026_XPLLDATA_P 0x02 20962306a36Sopenharmony_ci#define TVP3026_XPLLDATA_STAT 0x03 21062306a36Sopenharmony_ci#define TVP3026_XPIXPLLDATA 0x2D 21162306a36Sopenharmony_ci#define TVP3026_XMEMPLLDATA 0x2E 21262306a36Sopenharmony_ci#define TVP3026_XLOOPPLLDATA 0x2F 21362306a36Sopenharmony_ci#define TVP3026_XCOLKEYOVRMIN 0x30 21462306a36Sopenharmony_ci#define TVP3026_XCOLKEYOVRMAX 0x31 21562306a36Sopenharmony_ci#define TVP3026_XCOLKEYREDMIN 0x32 21662306a36Sopenharmony_ci#define TVP3026_XCOLKEYREDMAX 0x33 21762306a36Sopenharmony_ci#define TVP3026_XCOLKEYGREENMIN 0x34 21862306a36Sopenharmony_ci#define TVP3026_XCOLKEYGREENMAX 0x35 21962306a36Sopenharmony_ci#define TVP3026_XCOLKEYBLUEMIN 0x36 22062306a36Sopenharmony_ci#define TVP3026_XCOLKEYBLUEMAX 0x37 22162306a36Sopenharmony_ci#define TVP3026_XCOLKEYCTRL 0x38 22262306a36Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_OVR_EN 0x01 22362306a36Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_RED_EN 0x02 22462306a36Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_GREEN_EN 0x04 22562306a36Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_BLUE_EN 0x08 22662306a36Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_NEGATE 0x10 22762306a36Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_ZOOM1 0x00 22862306a36Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_ZOOM2 0x20 22962306a36Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_ZOOM4 0x40 23062306a36Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_ZOOM8 0x60 23162306a36Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_ZOOM16 0x80 23262306a36Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_ZOOM32 0xA0 23362306a36Sopenharmony_ci#define TVP3026_XMEMPLLCTRL 0x39 23462306a36Sopenharmony_ci#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 */ 23562306a36Sopenharmony_ci#define TVP3026_XMEMPLLCTRL_STROBEMKC4 0x08 23662306a36Sopenharmony_ci#define TVP3026_XMEMPLLCTRL_MCLK_DOTCLOCK 0x00 /* MKC4 */ 23762306a36Sopenharmony_ci#define TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL 0x10 /* MKC4 */ 23862306a36Sopenharmony_ci#define TVP3026_XMEMPLLCTRL_RCLK_PIXPLL 0x00 23962306a36Sopenharmony_ci#define TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL 0x20 24062306a36Sopenharmony_ci#define TVP3026_XMEMPLLCTRL_RCLK_DOTDIVN 0x40 /* dot clock divided by loop pclk N prescaler */ 24162306a36Sopenharmony_ci#define TVP3026_XSENSETEST 0x3A 24262306a36Sopenharmony_ci#define TVP3026_XTESTMODEDATA 0x3B 24362306a36Sopenharmony_ci#define TVP3026_XCRCREML 0x3C 24462306a36Sopenharmony_ci#define TVP3026_XCRCREMH 0x3D 24562306a36Sopenharmony_ci#define TVP3026_XCRCBITSEL 0x3E 24662306a36Sopenharmony_ci#define TVP3026_XID 0x3F 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic const unsigned char DACseq[] = 24962306a36Sopenharmony_ci{ TVP3026_XLATCHCTRL, TVP3026_XTRUECOLORCTRL, 25062306a36Sopenharmony_ci TVP3026_XMUXCTRL, TVP3026_XCLKCTRL, 25162306a36Sopenharmony_ci TVP3026_XPALETTEPAGE, 25262306a36Sopenharmony_ci TVP3026_XGENCTRL, 25362306a36Sopenharmony_ci TVP3026_XMISCCTRL, 25462306a36Sopenharmony_ci TVP3026_XGENIOCTRL, 25562306a36Sopenharmony_ci TVP3026_XGENIODATA, 25662306a36Sopenharmony_ci TVP3026_XCOLKEYOVRMIN, TVP3026_XCOLKEYOVRMAX, TVP3026_XCOLKEYREDMIN, TVP3026_XCOLKEYREDMAX, 25762306a36Sopenharmony_ci TVP3026_XCOLKEYGREENMIN, TVP3026_XCOLKEYGREENMAX, TVP3026_XCOLKEYBLUEMIN, TVP3026_XCOLKEYBLUEMAX, 25862306a36Sopenharmony_ci TVP3026_XCOLKEYCTRL, 25962306a36Sopenharmony_ci TVP3026_XMEMPLLCTRL, TVP3026_XSENSETEST, TVP3026_XCURCTRL }; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci#define POS3026_XLATCHCTRL 0 26262306a36Sopenharmony_ci#define POS3026_XTRUECOLORCTRL 1 26362306a36Sopenharmony_ci#define POS3026_XMUXCTRL 2 26462306a36Sopenharmony_ci#define POS3026_XCLKCTRL 3 26562306a36Sopenharmony_ci#define POS3026_XGENCTRL 5 26662306a36Sopenharmony_ci#define POS3026_XMISCCTRL 6 26762306a36Sopenharmony_ci#define POS3026_XMEMPLLCTRL 18 26862306a36Sopenharmony_ci#define POS3026_XCURCTRL 20 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic const unsigned char MGADACbpp32[] = 27162306a36Sopenharmony_ci{ TVP3026_XLATCHCTRL_2_1, TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_8888, 27262306a36Sopenharmony_ci 0x00, TVP3026_XCLKCTRL_DIV1 | TVP3026_XCLKCTRL_SRC_PLL, 27362306a36Sopenharmony_ci 0x00, 27462306a36Sopenharmony_ci 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, 27562306a36Sopenharmony_ci TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_HIGH, 27662306a36Sopenharmony_ci 0x00, 27762306a36Sopenharmony_ci 0x1E, 27862306a36Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 27962306a36Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 28062306a36Sopenharmony_ci TVP3026_XCOLKEYCTRL_ZOOM1, 28162306a36Sopenharmony_ci 0x00, 0x00, TVP3026_XCURCTRL_DIS }; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic int Ti3026_calcclock(const struct matrox_fb_info *minfo, 28462306a36Sopenharmony_ci unsigned int freq, unsigned int fmax, int *in, 28562306a36Sopenharmony_ci int *feed, int *post) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci unsigned int fvco; 28862306a36Sopenharmony_ci unsigned int lin, lfeed, lpost; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci DBG(__func__) 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci fvco = PLL_calcclock(minfo, freq, fmax, &lin, &lfeed, &lpost); 29362306a36Sopenharmony_ci fvco >>= (*post = lpost); 29462306a36Sopenharmony_ci *in = 64 - lin; 29562306a36Sopenharmony_ci *feed = 64 - lfeed; 29662306a36Sopenharmony_ci return fvco; 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistatic int Ti3026_setpclk(struct matrox_fb_info *minfo, int clk) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci unsigned int f_pll; 30262306a36Sopenharmony_ci unsigned int pixfeed, pixin, pixpost; 30362306a36Sopenharmony_ci struct matrox_hw_state *hw = &minfo->hw; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci DBG(__func__) 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci f_pll = Ti3026_calcclock(minfo, clk, minfo->max_pixel_clock, &pixin, &pixfeed, &pixpost); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci hw->DACclk[0] = pixin | 0xC0; 31062306a36Sopenharmony_ci hw->DACclk[1] = pixfeed; 31162306a36Sopenharmony_ci hw->DACclk[2] = pixpost | 0xB0; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci { 31462306a36Sopenharmony_ci unsigned int loopfeed, loopin, looppost, loopdiv, z; 31562306a36Sopenharmony_ci unsigned int Bpp; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci Bpp = minfo->curr.final_bppShift; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci if (minfo->fbcon.var.bits_per_pixel == 24) { 32062306a36Sopenharmony_ci loopfeed = 3; /* set lm to any possible value */ 32162306a36Sopenharmony_ci loopin = 3 * 32 / Bpp; 32262306a36Sopenharmony_ci } else { 32362306a36Sopenharmony_ci loopfeed = 4; 32462306a36Sopenharmony_ci loopin = 4 * 32 / Bpp; 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci z = (110000 * loopin) / (f_pll * loopfeed); 32762306a36Sopenharmony_ci loopdiv = 0; /* div 2 */ 32862306a36Sopenharmony_ci if (z < 2) 32962306a36Sopenharmony_ci looppost = 0; 33062306a36Sopenharmony_ci else if (z < 4) 33162306a36Sopenharmony_ci looppost = 1; 33262306a36Sopenharmony_ci else if (z < 8) 33362306a36Sopenharmony_ci looppost = 2; 33462306a36Sopenharmony_ci else { 33562306a36Sopenharmony_ci looppost = 3; 33662306a36Sopenharmony_ci loopdiv = z/16; 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci if (minfo->fbcon.var.bits_per_pixel == 24) { 33962306a36Sopenharmony_ci hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0; 34062306a36Sopenharmony_ci hw->DACclk[4] = (65 - loopfeed) | 0x80; 34162306a36Sopenharmony_ci if (minfo->accel.ramdac_rev > 0x20) { 34262306a36Sopenharmony_ci if (isInterleave(minfo)) 34362306a36Sopenharmony_ci hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3; 34462306a36Sopenharmony_ci else { 34562306a36Sopenharmony_ci hw->DACclk[4] &= ~0xC0; 34662306a36Sopenharmony_ci hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci } else { 34962306a36Sopenharmony_ci if (isInterleave(minfo)) 35062306a36Sopenharmony_ci ; /* default... */ 35162306a36Sopenharmony_ci else { 35262306a36Sopenharmony_ci hw->DACclk[4] ^= 0xC0; /* change from 0x80 to 0x40 */ 35362306a36Sopenharmony_ci hw->DACreg[POS3026_XLATCHCTRL] = TVP3026A_XLATCHCTRL_4_3; 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci hw->DACclk[5] = looppost | 0xF8; 35762306a36Sopenharmony_ci if (minfo->devflags.mga_24bpp_fix) 35862306a36Sopenharmony_ci hw->DACclk[5] ^= 0x40; 35962306a36Sopenharmony_ci } else { 36062306a36Sopenharmony_ci hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0; 36162306a36Sopenharmony_ci hw->DACclk[4] = 65 - loopfeed; 36262306a36Sopenharmony_ci hw->DACclk[5] = looppost | 0xF0; 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci hw->DACreg[POS3026_XMEMPLLCTRL] = loopdiv | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci return 0; 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci u_int8_t muxctrl = isInterleave(minfo) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT; 37262306a36Sopenharmony_ci struct matrox_hw_state *hw = &minfo->hw; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci DBG(__func__) 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci memcpy(hw->DACreg, MGADACbpp32, sizeof(MGADACbpp32)); 37762306a36Sopenharmony_ci switch (minfo->fbcon.var.bits_per_pixel) { 37862306a36Sopenharmony_ci case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */ 37962306a36Sopenharmony_ci hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR; 38062306a36Sopenharmony_ci hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_4BIT; 38162306a36Sopenharmony_ci hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV8; 38262306a36Sopenharmony_ci hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW; 38362306a36Sopenharmony_ci break; 38462306a36Sopenharmony_ci case 8: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_8_1; /* or _4_1, they are same */ 38562306a36Sopenharmony_ci hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR; 38662306a36Sopenharmony_ci hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_8BIT; 38762306a36Sopenharmony_ci hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4; 38862306a36Sopenharmony_ci hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW; 38962306a36Sopenharmony_ci break; 39062306a36Sopenharmony_ci case 16: 39162306a36Sopenharmony_ci /* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used every time) */ 39262306a36Sopenharmony_ci hw->DACreg[POS3026_XTRUECOLORCTRL] = (minfo->fbcon.var.green.length == 5) ? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565); 39362306a36Sopenharmony_ci hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT; 39462306a36Sopenharmony_ci hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2; 39562306a36Sopenharmony_ci break; 39662306a36Sopenharmony_ci case 24: 39762306a36Sopenharmony_ci /* XLATCHCTRL is: for (A) use _4_3 (?_8_3 is same? TBD), for (B) it is set in setpclk */ 39862306a36Sopenharmony_ci hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_888; 39962306a36Sopenharmony_ci hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT; 40062306a36Sopenharmony_ci hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4; 40162306a36Sopenharmony_ci break; 40262306a36Sopenharmony_ci case 32: 40362306a36Sopenharmony_ci /* XLATCHCTRL should be _2_1 / _1_1... Why is not? (_2_1 is used every time) */ 40462306a36Sopenharmony_ci hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT; 40562306a36Sopenharmony_ci break; 40662306a36Sopenharmony_ci default: 40762306a36Sopenharmony_ci return 1; /* TODO: failed */ 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci if (matroxfb_vgaHWinit(minfo, m)) return 1; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci /* set SYNC */ 41262306a36Sopenharmony_ci hw->MiscOutReg = 0xCB; 41362306a36Sopenharmony_ci if (m->sync & FB_SYNC_HOR_HIGH_ACT) 41462306a36Sopenharmony_ci hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_HSYNC_NEG; 41562306a36Sopenharmony_ci if (m->sync & FB_SYNC_VERT_HIGH_ACT) 41662306a36Sopenharmony_ci hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_VSYNC_NEG; 41762306a36Sopenharmony_ci if (m->sync & FB_SYNC_ON_GREEN) 41862306a36Sopenharmony_ci hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_SYNC_ON_GREEN; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci /* set DELAY */ 42162306a36Sopenharmony_ci if (minfo->video.len < 0x400000) 42262306a36Sopenharmony_ci hw->CRTCEXT[3] |= 0x08; 42362306a36Sopenharmony_ci else if (minfo->video.len > 0x400000) 42462306a36Sopenharmony_ci hw->CRTCEXT[3] |= 0x10; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci /* set HWCURSOR */ 42762306a36Sopenharmony_ci if (m->interlaced) { 42862306a36Sopenharmony_ci hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_INTERLACED; 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci if (m->HTotal >= 1536) 43162306a36Sopenharmony_ci hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_BLANK4096; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci /* set interleaving */ 43462306a36Sopenharmony_ci hw->MXoptionReg &= ~0x00001000; 43562306a36Sopenharmony_ci if (isInterleave(minfo)) hw->MXoptionReg |= 0x00001000; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci /* set DAC */ 43862306a36Sopenharmony_ci Ti3026_setpclk(minfo, m->pixclock); 43962306a36Sopenharmony_ci return 0; 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic void ti3026_setMCLK(struct matrox_fb_info *minfo, int fout) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci unsigned int f_pll; 44562306a36Sopenharmony_ci unsigned int pclk_m, pclk_n, pclk_p; 44662306a36Sopenharmony_ci unsigned int mclk_m, mclk_n, mclk_p; 44762306a36Sopenharmony_ci unsigned int rfhcnt, mclk_ctl; 44862306a36Sopenharmony_ci int tmout; 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci DBG(__func__) 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci f_pll = Ti3026_calcclock(minfo, fout, minfo->max_pixel_clock, &mclk_n, &mclk_m, &mclk_p); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci /* save pclk */ 45562306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFC); 45662306a36Sopenharmony_ci pclk_n = inTi3026(minfo, TVP3026_XPIXPLLDATA); 45762306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFD); 45862306a36Sopenharmony_ci pclk_m = inTi3026(minfo, TVP3026_XPIXPLLDATA); 45962306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFE); 46062306a36Sopenharmony_ci pclk_p = inTi3026(minfo, TVP3026_XPIXPLLDATA); 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci /* stop pclk */ 46362306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFE); 46462306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci /* set pclk to new mclk */ 46762306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFC); 46862306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_n | 0xC0); 46962306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_m); 47062306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_p | 0xB0); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci /* wait for PLL to lock */ 47362306a36Sopenharmony_ci for (tmout = 500000; tmout; tmout--) { 47462306a36Sopenharmony_ci if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40) 47562306a36Sopenharmony_ci break; 47662306a36Sopenharmony_ci udelay(10); 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci if (!tmout) 47962306a36Sopenharmony_ci printk(KERN_ERR "matroxfb: Temporary pixel PLL not locked after 5 secs\n"); 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci /* output pclk on mclk pin */ 48262306a36Sopenharmony_ci mclk_ctl = inTi3026(minfo, TVP3026_XMEMPLLCTRL); 48362306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7); 48462306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4); 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci /* stop MCLK */ 48762306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFB); 48862306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLDATA, 0x00); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci /* set mclk to new freq */ 49162306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xF3); 49262306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_n | 0xC0); 49362306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_m); 49462306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_p | 0xB0); 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci /* wait for PLL to lock */ 49762306a36Sopenharmony_ci for (tmout = 500000; tmout; tmout--) { 49862306a36Sopenharmony_ci if (inTi3026(minfo, TVP3026_XMEMPLLDATA) & 0x40) 49962306a36Sopenharmony_ci break; 50062306a36Sopenharmony_ci udelay(10); 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci if (!tmout) 50362306a36Sopenharmony_ci printk(KERN_ERR "matroxfb: Memory PLL not locked after 5 secs\n"); 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci f_pll = f_pll * 333 / (10000 << mclk_p); 50662306a36Sopenharmony_ci if (isMilleniumII(minfo)) { 50762306a36Sopenharmony_ci rfhcnt = (f_pll - 128) / 256; 50862306a36Sopenharmony_ci if (rfhcnt > 15) 50962306a36Sopenharmony_ci rfhcnt = 15; 51062306a36Sopenharmony_ci } else { 51162306a36Sopenharmony_ci rfhcnt = (f_pll - 64) / 128; 51262306a36Sopenharmony_ci if (rfhcnt > 15) 51362306a36Sopenharmony_ci rfhcnt = 0; 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ci minfo->hw.MXoptionReg = (minfo->hw.MXoptionReg & ~0x000F0000) | (rfhcnt << 16); 51662306a36Sopenharmony_ci pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci /* output MCLK to MCLK pin */ 51962306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL); 52062306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4); 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci /* stop PCLK */ 52362306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFE); 52462306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00); 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci /* restore pclk */ 52762306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFC); 52862306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_n); 52962306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_m); 53062306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_p); 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci /* wait for PLL to lock */ 53362306a36Sopenharmony_ci for (tmout = 500000; tmout; tmout--) { 53462306a36Sopenharmony_ci if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40) 53562306a36Sopenharmony_ci break; 53662306a36Sopenharmony_ci udelay(10); 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci if (!tmout) 53962306a36Sopenharmony_ci printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n"); 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic void ti3026_ramdac_init(struct matrox_fb_info *minfo) 54362306a36Sopenharmony_ci{ 54462306a36Sopenharmony_ci DBG(__func__) 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci minfo->features.pll.vco_freq_min = 110000; 54762306a36Sopenharmony_ci minfo->features.pll.ref_freq = 114545; 54862306a36Sopenharmony_ci minfo->features.pll.feed_div_min = 2; 54962306a36Sopenharmony_ci minfo->features.pll.feed_div_max = 24; 55062306a36Sopenharmony_ci minfo->features.pll.in_div_min = 2; 55162306a36Sopenharmony_ci minfo->features.pll.in_div_max = 63; 55262306a36Sopenharmony_ci minfo->features.pll.post_shift_max = 3; 55362306a36Sopenharmony_ci if (minfo->devflags.noinit) 55462306a36Sopenharmony_ci return; 55562306a36Sopenharmony_ci ti3026_setMCLK(minfo, 60000); 55662306a36Sopenharmony_ci} 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_cistatic void Ti3026_restore(struct matrox_fb_info *minfo) 55962306a36Sopenharmony_ci{ 56062306a36Sopenharmony_ci int i; 56162306a36Sopenharmony_ci unsigned char progdac[6]; 56262306a36Sopenharmony_ci struct matrox_hw_state *hw = &minfo->hw; 56362306a36Sopenharmony_ci CRITFLAGS 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci DBG(__func__) 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci#ifdef DEBUG 56862306a36Sopenharmony_ci dprintk(KERN_INFO "EXTVGA regs: "); 56962306a36Sopenharmony_ci for (i = 0; i < 6; i++) 57062306a36Sopenharmony_ci dprintk("%02X:", hw->CRTCEXT[i]); 57162306a36Sopenharmony_ci dprintk("\n"); 57262306a36Sopenharmony_ci#endif 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci CRITBEGIN 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg); 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci CRITEND 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci matroxfb_vgaHWrestore(minfo); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci CRITBEGIN 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci minfo->crtc1.panpos = -1; 58562306a36Sopenharmony_ci for (i = 0; i < 6; i++) 58662306a36Sopenharmony_ci mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci for (i = 0; i < 21; i++) { 58962306a36Sopenharmony_ci outTi3026(minfo, DACseq[i], hw->DACreg[i]); 59062306a36Sopenharmony_ci } 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x00); 59362306a36Sopenharmony_ci progdac[0] = inTi3026(minfo, TVP3026_XPIXPLLDATA); 59462306a36Sopenharmony_ci progdac[3] = inTi3026(minfo, TVP3026_XLOOPPLLDATA); 59562306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x15); 59662306a36Sopenharmony_ci progdac[1] = inTi3026(minfo, TVP3026_XPIXPLLDATA); 59762306a36Sopenharmony_ci progdac[4] = inTi3026(minfo, TVP3026_XLOOPPLLDATA); 59862306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x2A); 59962306a36Sopenharmony_ci progdac[2] = inTi3026(minfo, TVP3026_XPIXPLLDATA); 60062306a36Sopenharmony_ci progdac[5] = inTi3026(minfo, TVP3026_XLOOPPLLDATA); 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci CRITEND 60362306a36Sopenharmony_ci if (memcmp(hw->DACclk, progdac, 6)) { 60462306a36Sopenharmony_ci /* agrhh... setting up PLL is very slow on Millennium... */ 60562306a36Sopenharmony_ci /* Mystique PLL is locked in few ms, but Millennium PLL lock takes about 0.15 s... */ 60662306a36Sopenharmony_ci /* Maybe even we should call schedule() ? */ 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci CRITBEGIN 60962306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]); 61062306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x2A); 61162306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0); 61262306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, 0); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x00); 61562306a36Sopenharmony_ci for (i = 0; i < 3; i++) 61662306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, hw->DACclk[i]); 61762306a36Sopenharmony_ci /* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */ 61862306a36Sopenharmony_ci if (hw->MiscOutReg & 0x08) { 61962306a36Sopenharmony_ci int tmout; 62062306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x3F); 62162306a36Sopenharmony_ci for (tmout = 500000; tmout; --tmout) { 62262306a36Sopenharmony_ci if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40) 62362306a36Sopenharmony_ci break; 62462306a36Sopenharmony_ci udelay(10); 62562306a36Sopenharmony_ci } 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci CRITEND 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci if (!tmout) 63062306a36Sopenharmony_ci printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n"); 63162306a36Sopenharmony_ci else 63262306a36Sopenharmony_ci dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout); 63362306a36Sopenharmony_ci CRITBEGIN 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]); 63662306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x00); 63762306a36Sopenharmony_ci for (i = 3; i < 6; i++) 63862306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XLOOPPLLDATA, hw->DACclk[i]); 63962306a36Sopenharmony_ci CRITEND 64062306a36Sopenharmony_ci if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) { 64162306a36Sopenharmony_ci int tmout; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci CRITBEGIN 64462306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x3F); 64562306a36Sopenharmony_ci for (tmout = 500000; tmout; --tmout) { 64662306a36Sopenharmony_ci if (inTi3026(minfo, TVP3026_XLOOPPLLDATA) & 0x40) 64762306a36Sopenharmony_ci break; 64862306a36Sopenharmony_ci udelay(10); 64962306a36Sopenharmony_ci } 65062306a36Sopenharmony_ci CRITEND 65162306a36Sopenharmony_ci if (!tmout) 65262306a36Sopenharmony_ci printk(KERN_ERR "matroxfb: Loop PLL not locked after 5 secs\n"); 65362306a36Sopenharmony_ci else 65462306a36Sopenharmony_ci dprintk(KERN_INFO "LoopPLL: %d\n", 500000-tmout); 65562306a36Sopenharmony_ci } 65662306a36Sopenharmony_ci } 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci#ifdef DEBUG 65962306a36Sopenharmony_ci dprintk(KERN_DEBUG "3026DACregs "); 66062306a36Sopenharmony_ci for (i = 0; i < 21; i++) { 66162306a36Sopenharmony_ci dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]); 66262306a36Sopenharmony_ci if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... "); 66362306a36Sopenharmony_ci } 66462306a36Sopenharmony_ci dprintk(KERN_DEBUG "DACclk "); 66562306a36Sopenharmony_ci for (i = 0; i < 6; i++) 66662306a36Sopenharmony_ci dprintk("C%02X=%02X ", i, hw->DACclk[i]); 66762306a36Sopenharmony_ci dprintk("\n"); 66862306a36Sopenharmony_ci#endif 66962306a36Sopenharmony_ci} 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_cistatic void Ti3026_reset(struct matrox_fb_info *minfo) 67262306a36Sopenharmony_ci{ 67362306a36Sopenharmony_ci DBG(__func__) 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci ti3026_ramdac_init(minfo); 67662306a36Sopenharmony_ci} 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_cistatic struct matrox_altout ti3026_output = { 67962306a36Sopenharmony_ci .name = "Primary output", 68062306a36Sopenharmony_ci}; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_cistatic int Ti3026_preinit(struct matrox_fb_info *minfo) 68362306a36Sopenharmony_ci{ 68462306a36Sopenharmony_ci static const int vxres_mill2[] = { 512, 640, 768, 800, 832, 960, 68562306a36Sopenharmony_ci 1024, 1152, 1280, 1600, 1664, 1920, 68662306a36Sopenharmony_ci 2048, 0}; 68762306a36Sopenharmony_ci static const int vxres_mill1[] = { 640, 768, 800, 960, 68862306a36Sopenharmony_ci 1024, 1152, 1280, 1600, 1920, 68962306a36Sopenharmony_ci 2048, 0}; 69062306a36Sopenharmony_ci struct matrox_hw_state *hw = &minfo->hw; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci DBG(__func__) 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci minfo->millenium = 1; 69562306a36Sopenharmony_ci minfo->milleniumII = (minfo->pcidev->device != PCI_DEVICE_ID_MATROX_MIL); 69662306a36Sopenharmony_ci minfo->capable.cfb4 = 1; 69762306a36Sopenharmony_ci minfo->capable.text = 1; /* isMilleniumII(minfo); */ 69862306a36Sopenharmony_ci minfo->capable.vxres = isMilleniumII(minfo) ? vxres_mill2 : vxres_mill1; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci minfo->outputs[0].data = minfo; 70162306a36Sopenharmony_ci minfo->outputs[0].output = &ti3026_output; 70262306a36Sopenharmony_ci minfo->outputs[0].src = minfo->outputs[0].default_src; 70362306a36Sopenharmony_ci minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci if (minfo->devflags.noinit) 70662306a36Sopenharmony_ci return 0; 70762306a36Sopenharmony_ci /* preserve VGA I/O, BIOS and PPC */ 70862306a36Sopenharmony_ci hw->MXoptionReg &= 0xC0000100; 70962306a36Sopenharmony_ci hw->MXoptionReg |= 0x002C0000; 71062306a36Sopenharmony_ci if (minfo->devflags.novga) 71162306a36Sopenharmony_ci hw->MXoptionReg &= ~0x00000100; 71262306a36Sopenharmony_ci if (minfo->devflags.nobios) 71362306a36Sopenharmony_ci hw->MXoptionReg &= ~0x40000000; 71462306a36Sopenharmony_ci if (minfo->devflags.nopciretry) 71562306a36Sopenharmony_ci hw->MXoptionReg |= 0x20000000; 71662306a36Sopenharmony_ci pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg); 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci minfo->accel.ramdac_rev = inTi3026(minfo, TVP3026_XSILICONREV); 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XCLKCTRL, TVP3026_XCLKCTRL_SRC_CLK0VGA | TVP3026_XCLKCTRL_CLKSTOPPED); 72162306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XTRUECOLORCTRL, TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR); 72262306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XMUXCTRL, TVP3026_XMUXCTRL_VGA); 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x2A); 72562306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0x00); 72662306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci mga_outb(M_MISC_REG, 0x67); 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLCTRL, TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL); 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci mga_outl(M_RESET, 1); 73362306a36Sopenharmony_ci udelay(250); 73462306a36Sopenharmony_ci mga_outl(M_RESET, 0); 73562306a36Sopenharmony_ci udelay(250); 73662306a36Sopenharmony_ci mga_outl(M_MACCESS, 0x00008000); 73762306a36Sopenharmony_ci udelay(10); 73862306a36Sopenharmony_ci return 0; 73962306a36Sopenharmony_ci} 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_cistruct matrox_switch matrox_millennium = { 74262306a36Sopenharmony_ci .preinit = Ti3026_preinit, 74362306a36Sopenharmony_ci .reset = Ti3026_reset, 74462306a36Sopenharmony_ci .init = Ti3026_init, 74562306a36Sopenharmony_ci .restore = Ti3026_restore 74662306a36Sopenharmony_ci}; 74762306a36Sopenharmony_ciEXPORT_SYMBOL(matrox_millennium); 74862306a36Sopenharmony_ci#endif 74962306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 750