18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Portions Copyright (c) 2001 Matrox Graphics Inc. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Version: 1.65 2002/08/14 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org> 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Contributors: "menion?" <menion@mindless.com> 158c2ecf20Sopenharmony_ci * Betatesting, fixes, ideas 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * "Kurt Garloff" <garloff@suse.de> 188c2ecf20Sopenharmony_ci * Betatesting, fixes, ideas, videomodes, videomodes timmings 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * "Tom Rini" <trini@kernel.crashing.org> 218c2ecf20Sopenharmony_ci * MTRR stuff, PPC cleanups, betatesting, fixes, ideas 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * "Bibek Sahu" <scorpio@dodds.net> 248c2ecf20Sopenharmony_ci * Access device through readb|w|l and write b|w|l 258c2ecf20Sopenharmony_ci * Extensive debugging stuff 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * "Daniel Haun" <haund@usa.net> 288c2ecf20Sopenharmony_ci * Testing, hardware cursor fixes 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * "Scott Wood" <sawst46+@pitt.edu> 318c2ecf20Sopenharmony_ci * Fixes 328c2ecf20Sopenharmony_ci * 338c2ecf20Sopenharmony_ci * "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de> 348c2ecf20Sopenharmony_ci * Betatesting 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * "Kelly French" <targon@hazmat.com> 378c2ecf20Sopenharmony_ci * "Fernando Herrera" <fherrera@eurielec.etsit.upm.es> 388c2ecf20Sopenharmony_ci * Betatesting, bug reporting 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * "Pablo Bianucci" <pbian@pccp.com.ar> 418c2ecf20Sopenharmony_ci * Fixes, ideas, betatesting 428c2ecf20Sopenharmony_ci * 438c2ecf20Sopenharmony_ci * "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es> 448c2ecf20Sopenharmony_ci * Fixes, enhandcements, ideas, betatesting 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci * "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp> 478c2ecf20Sopenharmony_ci * PPC betatesting, PPC support, backward compatibility 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci * "Paul Womar" <Paul@pwomar.demon.co.uk> 508c2ecf20Sopenharmony_ci * "Owen Waller" <O.Waller@ee.qub.ac.uk> 518c2ecf20Sopenharmony_ci * PPC betatesting 528c2ecf20Sopenharmony_ci * 538c2ecf20Sopenharmony_ci * "Thomas Pornin" <pornin@bolet.ens.fr> 548c2ecf20Sopenharmony_ci * Alpha betatesting 558c2ecf20Sopenharmony_ci * 568c2ecf20Sopenharmony_ci * "Pieter van Leuven" <pvl@iae.nl> 578c2ecf20Sopenharmony_ci * "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de> 588c2ecf20Sopenharmony_ci * G100 testing 598c2ecf20Sopenharmony_ci * 608c2ecf20Sopenharmony_ci * "H. Peter Arvin" <hpa@transmeta.com> 618c2ecf20Sopenharmony_ci * Ideas 628c2ecf20Sopenharmony_ci * 638c2ecf20Sopenharmony_ci * "Cort Dougan" <cort@cs.nmt.edu> 648c2ecf20Sopenharmony_ci * CHRP fixes and PReP cleanup 658c2ecf20Sopenharmony_ci * 668c2ecf20Sopenharmony_ci * "Mark Vojkovich" <mvojkovi@ucsd.edu> 678c2ecf20Sopenharmony_ci * G400 support 688c2ecf20Sopenharmony_ci * 698c2ecf20Sopenharmony_ci * (following author is not in any relation with this code, but his code 708c2ecf20Sopenharmony_ci * is included in this driver) 718c2ecf20Sopenharmony_ci * 728c2ecf20Sopenharmony_ci * Based on framebuffer driver for VBE 2.0 compliant graphic boards 738c2ecf20Sopenharmony_ci * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> 748c2ecf20Sopenharmony_ci * 758c2ecf20Sopenharmony_ci * (following author is not in any relation with this code, but his ideas 768c2ecf20Sopenharmony_ci * were used when writing this driver) 778c2ecf20Sopenharmony_ci * 788c2ecf20Sopenharmony_ci * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk> 798c2ecf20Sopenharmony_ci * 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#include "matroxfb_Ti3026.h" 848c2ecf20Sopenharmony_ci#include "matroxfb_misc.h" 858c2ecf20Sopenharmony_ci#include "matroxfb_accel.h" 868c2ecf20Sopenharmony_ci#include <linux/matroxfb.h> 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_MATROX_MILLENIUM 898c2ecf20Sopenharmony_ci#define outTi3026 matroxfb_DAC_out 908c2ecf20Sopenharmony_ci#define inTi3026 matroxfb_DAC_in 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci#define TVP3026_INDEX 0x00 938c2ecf20Sopenharmony_ci#define TVP3026_PALWRADD 0x00 948c2ecf20Sopenharmony_ci#define TVP3026_PALDATA 0x01 958c2ecf20Sopenharmony_ci#define TVP3026_PIXRDMSK 0x02 968c2ecf20Sopenharmony_ci#define TVP3026_PALRDADD 0x03 978c2ecf20Sopenharmony_ci#define TVP3026_CURCOLWRADD 0x04 988c2ecf20Sopenharmony_ci#define TVP3026_CLOVERSCAN 0x00 998c2ecf20Sopenharmony_ci#define TVP3026_CLCOLOR0 0x01 1008c2ecf20Sopenharmony_ci#define TVP3026_CLCOLOR1 0x02 1018c2ecf20Sopenharmony_ci#define TVP3026_CLCOLOR2 0x03 1028c2ecf20Sopenharmony_ci#define TVP3026_CURCOLDATA 0x05 1038c2ecf20Sopenharmony_ci#define TVP3026_CURCOLRDADD 0x07 1048c2ecf20Sopenharmony_ci#define TVP3026_CURCTRL 0x09 1058c2ecf20Sopenharmony_ci#define TVP3026_X_DATAREG 0x0A 1068c2ecf20Sopenharmony_ci#define TVP3026_CURRAMDATA 0x0B 1078c2ecf20Sopenharmony_ci#define TVP3026_CURPOSXL 0x0C 1088c2ecf20Sopenharmony_ci#define TVP3026_CURPOSXH 0x0D 1098c2ecf20Sopenharmony_ci#define TVP3026_CURPOSYL 0x0E 1108c2ecf20Sopenharmony_ci#define TVP3026_CURPOSYH 0x0F 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci#define TVP3026_XSILICONREV 0x01 1138c2ecf20Sopenharmony_ci#define TVP3026_XCURCTRL 0x06 1148c2ecf20Sopenharmony_ci#define TVP3026_XCURCTRL_DIS 0x00 /* transparent, transparent, transparent, transparent */ 1158c2ecf20Sopenharmony_ci#define TVP3026_XCURCTRL_3COLOR 0x01 /* transparent, 0, 1, 2 */ 1168c2ecf20Sopenharmony_ci#define TVP3026_XCURCTRL_XGA 0x02 /* 0, 1, transparent, complement */ 1178c2ecf20Sopenharmony_ci#define TVP3026_XCURCTRL_XWIN 0x03 /* transparent, transparent, 0, 1 */ 1188c2ecf20Sopenharmony_ci#define TVP3026_XCURCTRL_BLANK2048 0x00 1198c2ecf20Sopenharmony_ci#define TVP3026_XCURCTRL_BLANK4096 0x10 1208c2ecf20Sopenharmony_ci#define TVP3026_XCURCTRL_INTERLACED 0x20 1218c2ecf20Sopenharmony_ci#define TVP3026_XCURCTRL_ODD 0x00 /* ext.signal ODD/\EVEN */ 1228c2ecf20Sopenharmony_ci#define TVP3026_XCURCTRL_EVEN 0x40 /* ext.signal EVEN/\ODD */ 1238c2ecf20Sopenharmony_ci#define TVP3026_XCURCTRL_INDIRECT 0x00 1248c2ecf20Sopenharmony_ci#define TVP3026_XCURCTRL_DIRECT 0x80 1258c2ecf20Sopenharmony_ci#define TVP3026_XLATCHCTRL 0x0F 1268c2ecf20Sopenharmony_ci#define TVP3026_XLATCHCTRL_1_1 0x06 1278c2ecf20Sopenharmony_ci#define TVP3026_XLATCHCTRL_2_1 0x07 1288c2ecf20Sopenharmony_ci#define TVP3026_XLATCHCTRL_4_1 0x06 1298c2ecf20Sopenharmony_ci#define TVP3026_XLATCHCTRL_8_1 0x06 1308c2ecf20Sopenharmony_ci#define TVP3026_XLATCHCTRL_16_1 0x06 1318c2ecf20Sopenharmony_ci#define TVP3026A_XLATCHCTRL_4_3 0x06 /* ??? do not understand... but it works... !!! */ 1328c2ecf20Sopenharmony_ci#define TVP3026A_XLATCHCTRL_8_3 0x07 1338c2ecf20Sopenharmony_ci#define TVP3026B_XLATCHCTRL_4_3 0x08 1348c2ecf20Sopenharmony_ci#define TVP3026B_XLATCHCTRL_8_3 0x06 /* ??? do not understand... but it works... !!! */ 1358c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL 0x18 1368c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_ACCEL 0x00 1378c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_TVP 0x20 1388c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR 0x80 1398c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_TRUECOLOR 0x40 /* paletized */ 1408c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_DIRECTCOLOR 0x00 1418c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_24_ALTERNATE 0x08 /* 5:4/5:2 instead of 4:3/8:3 */ 1428c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_RGB_888 0x16 /* 4:3/8:3 (or 5:4/5:2) */ 1438c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_BGR_888 0x17 1448c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_ORGB_8888 0x06 1458c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_BGRO_8888 0x07 1468c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_RGB_565 0x05 1478c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_ORGB_1555 0x04 1488c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_RGB_664 0x03 1498c2ecf20Sopenharmony_ci#define TVP3026_XTRUECOLORCTRL_RGBO_4444 0x01 1508c2ecf20Sopenharmony_ci#define TVP3026_XMUXCTRL 0x19 1518c2ecf20Sopenharmony_ci#define TVP3026_XMUXCTRL_MEMORY_8BIT 0x01 /* - */ 1528c2ecf20Sopenharmony_ci#define TVP3026_XMUXCTRL_MEMORY_16BIT 0x02 /* - */ 1538c2ecf20Sopenharmony_ci#define TVP3026_XMUXCTRL_MEMORY_32BIT 0x03 /* 2MB RAM, 512K * 4 */ 1548c2ecf20Sopenharmony_ci#define TVP3026_XMUXCTRL_MEMORY_64BIT 0x04 /* >2MB RAM, 512K * 8 & more */ 1558c2ecf20Sopenharmony_ci#define TVP3026_XMUXCTRL_PIXEL_4BIT 0x40 /* L0,H0,L1,H1... */ 1568c2ecf20Sopenharmony_ci#define TVP3026_XMUXCTRL_PIXEL_4BIT_SWAPPED 0x60 /* H0,L0,H1,L1... */ 1578c2ecf20Sopenharmony_ci#define TVP3026_XMUXCTRL_PIXEL_8BIT 0x48 1588c2ecf20Sopenharmony_ci#define TVP3026_XMUXCTRL_PIXEL_16BIT 0x50 1598c2ecf20Sopenharmony_ci#define TVP3026_XMUXCTRL_PIXEL_32BIT 0x58 1608c2ecf20Sopenharmony_ci#define TVP3026_XMUXCTRL_VGA 0x98 /* VGA MEMORY, 8BIT PIXEL */ 1618c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL 0x1A 1628c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV1 0x00 1638c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV2 0x10 1648c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV4 0x20 1658c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV8 0x30 1668c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV16 0x40 1678c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV32 0x50 1688c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_DIV64 0x60 1698c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_CLKSTOPPED 0x70 1708c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_CLK0 0x00 1718c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_CLK1 0x01 1728c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_CLK2 0x02 /* CLK2 is TTL source*/ 1738c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_NCLK2 0x03 /* not CLK2 is TTL source */ 1748c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_ECLK2 0x04 /* CLK2 and not CLK2 is ECL source */ 1758c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_PLL 0x05 1768c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_DIS 0x06 /* disable & poweroff internal clock */ 1778c2ecf20Sopenharmony_ci#define TVP3026_XCLKCTRL_SRC_CLK0VGA 0x07 1788c2ecf20Sopenharmony_ci#define TVP3026_XPALETTEPAGE 0x1C 1798c2ecf20Sopenharmony_ci#define TVP3026_XGENCTRL 0x1D 1808c2ecf20Sopenharmony_ci#define TVP3026_XGENCTRL_HSYNC_POS 0x00 1818c2ecf20Sopenharmony_ci#define TVP3026_XGENCTRL_HSYNC_NEG 0x01 1828c2ecf20Sopenharmony_ci#define TVP3026_XGENCTRL_VSYNC_POS 0x00 1838c2ecf20Sopenharmony_ci#define TVP3026_XGENCTRL_VSYNC_NEG 0x02 1848c2ecf20Sopenharmony_ci#define TVP3026_XGENCTRL_LITTLE_ENDIAN 0x00 1858c2ecf20Sopenharmony_ci#define TVP3026_XGENCTRL_BIG_ENDIAN 0x08 1868c2ecf20Sopenharmony_ci#define TVP3026_XGENCTRL_BLACK_0IRE 0x00 1878c2ecf20Sopenharmony_ci#define TVP3026_XGENCTRL_BLACK_75IRE 0x10 1888c2ecf20Sopenharmony_ci#define TVP3026_XGENCTRL_NO_SYNC_ON_GREEN 0x00 1898c2ecf20Sopenharmony_ci#define TVP3026_XGENCTRL_SYNC_ON_GREEN 0x20 1908c2ecf20Sopenharmony_ci#define TVP3026_XGENCTRL_OVERSCAN_DIS 0x00 1918c2ecf20Sopenharmony_ci#define TVP3026_XGENCTRL_OVERSCAN_EN 0x40 1928c2ecf20Sopenharmony_ci#define TVP3026_XMISCCTRL 0x1E 1938c2ecf20Sopenharmony_ci#define TVP3026_XMISCCTRL_DAC_PUP 0x00 1948c2ecf20Sopenharmony_ci#define TVP3026_XMISCCTRL_DAC_PDOWN 0x01 1958c2ecf20Sopenharmony_ci#define TVP3026_XMISCCTRL_DAC_EXT 0x00 /* or 8, bit 3 is ignored */ 1968c2ecf20Sopenharmony_ci#define TVP3026_XMISCCTRL_DAC_6BIT 0x04 1978c2ecf20Sopenharmony_ci#define TVP3026_XMISCCTRL_DAC_8BIT 0x0C 1988c2ecf20Sopenharmony_ci#define TVP3026_XMISCCTRL_PSEL_DIS 0x00 1998c2ecf20Sopenharmony_ci#define TVP3026_XMISCCTRL_PSEL_EN 0x10 2008c2ecf20Sopenharmony_ci#define TVP3026_XMISCCTRL_PSEL_LOW 0x00 /* PSEL high selects directcolor */ 2018c2ecf20Sopenharmony_ci#define TVP3026_XMISCCTRL_PSEL_HIGH 0x20 /* PSEL high selects truecolor or pseudocolor */ 2028c2ecf20Sopenharmony_ci#define TVP3026_XGENIOCTRL 0x2A 2038c2ecf20Sopenharmony_ci#define TVP3026_XGENIODATA 0x2B 2048c2ecf20Sopenharmony_ci#define TVP3026_XPLLADDR 0x2C 2058c2ecf20Sopenharmony_ci#define TVP3026_XPLLADDR_X(LOOP,MCLK,PIX) (((LOOP)<<4) | ((MCLK)<<2) | (PIX)) 2068c2ecf20Sopenharmony_ci#define TVP3026_XPLLDATA_N 0x00 2078c2ecf20Sopenharmony_ci#define TVP3026_XPLLDATA_M 0x01 2088c2ecf20Sopenharmony_ci#define TVP3026_XPLLDATA_P 0x02 2098c2ecf20Sopenharmony_ci#define TVP3026_XPLLDATA_STAT 0x03 2108c2ecf20Sopenharmony_ci#define TVP3026_XPIXPLLDATA 0x2D 2118c2ecf20Sopenharmony_ci#define TVP3026_XMEMPLLDATA 0x2E 2128c2ecf20Sopenharmony_ci#define TVP3026_XLOOPPLLDATA 0x2F 2138c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYOVRMIN 0x30 2148c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYOVRMAX 0x31 2158c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYREDMIN 0x32 2168c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYREDMAX 0x33 2178c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYGREENMIN 0x34 2188c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYGREENMAX 0x35 2198c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYBLUEMIN 0x36 2208c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYBLUEMAX 0x37 2218c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYCTRL 0x38 2228c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_OVR_EN 0x01 2238c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_RED_EN 0x02 2248c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_GREEN_EN 0x04 2258c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_BLUE_EN 0x08 2268c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_NEGATE 0x10 2278c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_ZOOM1 0x00 2288c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_ZOOM2 0x20 2298c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_ZOOM4 0x40 2308c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_ZOOM8 0x60 2318c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_ZOOM16 0x80 2328c2ecf20Sopenharmony_ci#define TVP3026_XCOLKEYCTRL_ZOOM32 0xA0 2338c2ecf20Sopenharmony_ci#define TVP3026_XMEMPLLCTRL 0x39 2348c2ecf20Sopenharmony_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 */ 2358c2ecf20Sopenharmony_ci#define TVP3026_XMEMPLLCTRL_STROBEMKC4 0x08 2368c2ecf20Sopenharmony_ci#define TVP3026_XMEMPLLCTRL_MCLK_DOTCLOCK 0x00 /* MKC4 */ 2378c2ecf20Sopenharmony_ci#define TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL 0x10 /* MKC4 */ 2388c2ecf20Sopenharmony_ci#define TVP3026_XMEMPLLCTRL_RCLK_PIXPLL 0x00 2398c2ecf20Sopenharmony_ci#define TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL 0x20 2408c2ecf20Sopenharmony_ci#define TVP3026_XMEMPLLCTRL_RCLK_DOTDIVN 0x40 /* dot clock divided by loop pclk N prescaler */ 2418c2ecf20Sopenharmony_ci#define TVP3026_XSENSETEST 0x3A 2428c2ecf20Sopenharmony_ci#define TVP3026_XTESTMODEDATA 0x3B 2438c2ecf20Sopenharmony_ci#define TVP3026_XCRCREML 0x3C 2448c2ecf20Sopenharmony_ci#define TVP3026_XCRCREMH 0x3D 2458c2ecf20Sopenharmony_ci#define TVP3026_XCRCBITSEL 0x3E 2468c2ecf20Sopenharmony_ci#define TVP3026_XID 0x3F 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_cistatic const unsigned char DACseq[] = 2498c2ecf20Sopenharmony_ci{ TVP3026_XLATCHCTRL, TVP3026_XTRUECOLORCTRL, 2508c2ecf20Sopenharmony_ci TVP3026_XMUXCTRL, TVP3026_XCLKCTRL, 2518c2ecf20Sopenharmony_ci TVP3026_XPALETTEPAGE, 2528c2ecf20Sopenharmony_ci TVP3026_XGENCTRL, 2538c2ecf20Sopenharmony_ci TVP3026_XMISCCTRL, 2548c2ecf20Sopenharmony_ci TVP3026_XGENIOCTRL, 2558c2ecf20Sopenharmony_ci TVP3026_XGENIODATA, 2568c2ecf20Sopenharmony_ci TVP3026_XCOLKEYOVRMIN, TVP3026_XCOLKEYOVRMAX, TVP3026_XCOLKEYREDMIN, TVP3026_XCOLKEYREDMAX, 2578c2ecf20Sopenharmony_ci TVP3026_XCOLKEYGREENMIN, TVP3026_XCOLKEYGREENMAX, TVP3026_XCOLKEYBLUEMIN, TVP3026_XCOLKEYBLUEMAX, 2588c2ecf20Sopenharmony_ci TVP3026_XCOLKEYCTRL, 2598c2ecf20Sopenharmony_ci TVP3026_XMEMPLLCTRL, TVP3026_XSENSETEST, TVP3026_XCURCTRL }; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci#define POS3026_XLATCHCTRL 0 2628c2ecf20Sopenharmony_ci#define POS3026_XTRUECOLORCTRL 1 2638c2ecf20Sopenharmony_ci#define POS3026_XMUXCTRL 2 2648c2ecf20Sopenharmony_ci#define POS3026_XCLKCTRL 3 2658c2ecf20Sopenharmony_ci#define POS3026_XGENCTRL 5 2668c2ecf20Sopenharmony_ci#define POS3026_XMISCCTRL 6 2678c2ecf20Sopenharmony_ci#define POS3026_XMEMPLLCTRL 18 2688c2ecf20Sopenharmony_ci#define POS3026_XCURCTRL 20 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic const unsigned char MGADACbpp32[] = 2718c2ecf20Sopenharmony_ci{ TVP3026_XLATCHCTRL_2_1, TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_8888, 2728c2ecf20Sopenharmony_ci 0x00, TVP3026_XCLKCTRL_DIV1 | TVP3026_XCLKCTRL_SRC_PLL, 2738c2ecf20Sopenharmony_ci 0x00, 2748c2ecf20Sopenharmony_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, 2758c2ecf20Sopenharmony_ci TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_HIGH, 2768c2ecf20Sopenharmony_ci 0x00, 2778c2ecf20Sopenharmony_ci 0x1E, 2788c2ecf20Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 2798c2ecf20Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 2808c2ecf20Sopenharmony_ci TVP3026_XCOLKEYCTRL_ZOOM1, 2818c2ecf20Sopenharmony_ci 0x00, 0x00, TVP3026_XCURCTRL_DIS }; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic int Ti3026_calcclock(const struct matrox_fb_info *minfo, 2848c2ecf20Sopenharmony_ci unsigned int freq, unsigned int fmax, int *in, 2858c2ecf20Sopenharmony_ci int *feed, int *post) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci unsigned int fvco; 2888c2ecf20Sopenharmony_ci unsigned int lin, lfeed, lpost; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci DBG(__func__) 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci fvco = PLL_calcclock(minfo, freq, fmax, &lin, &lfeed, &lpost); 2938c2ecf20Sopenharmony_ci fvco >>= (*post = lpost); 2948c2ecf20Sopenharmony_ci *in = 64 - lin; 2958c2ecf20Sopenharmony_ci *feed = 64 - lfeed; 2968c2ecf20Sopenharmony_ci return fvco; 2978c2ecf20Sopenharmony_ci} 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_cistatic int Ti3026_setpclk(struct matrox_fb_info *minfo, int clk) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci unsigned int f_pll; 3028c2ecf20Sopenharmony_ci unsigned int pixfeed, pixin, pixpost; 3038c2ecf20Sopenharmony_ci struct matrox_hw_state *hw = &minfo->hw; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci DBG(__func__) 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci f_pll = Ti3026_calcclock(minfo, clk, minfo->max_pixel_clock, &pixin, &pixfeed, &pixpost); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci hw->DACclk[0] = pixin | 0xC0; 3108c2ecf20Sopenharmony_ci hw->DACclk[1] = pixfeed; 3118c2ecf20Sopenharmony_ci hw->DACclk[2] = pixpost | 0xB0; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci { 3148c2ecf20Sopenharmony_ci unsigned int loopfeed, loopin, looppost, loopdiv, z; 3158c2ecf20Sopenharmony_ci unsigned int Bpp; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci Bpp = minfo->curr.final_bppShift; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci if (minfo->fbcon.var.bits_per_pixel == 24) { 3208c2ecf20Sopenharmony_ci loopfeed = 3; /* set lm to any possible value */ 3218c2ecf20Sopenharmony_ci loopin = 3 * 32 / Bpp; 3228c2ecf20Sopenharmony_ci } else { 3238c2ecf20Sopenharmony_ci loopfeed = 4; 3248c2ecf20Sopenharmony_ci loopin = 4 * 32 / Bpp; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci z = (110000 * loopin) / (f_pll * loopfeed); 3278c2ecf20Sopenharmony_ci loopdiv = 0; /* div 2 */ 3288c2ecf20Sopenharmony_ci if (z < 2) 3298c2ecf20Sopenharmony_ci looppost = 0; 3308c2ecf20Sopenharmony_ci else if (z < 4) 3318c2ecf20Sopenharmony_ci looppost = 1; 3328c2ecf20Sopenharmony_ci else if (z < 8) 3338c2ecf20Sopenharmony_ci looppost = 2; 3348c2ecf20Sopenharmony_ci else { 3358c2ecf20Sopenharmony_ci looppost = 3; 3368c2ecf20Sopenharmony_ci loopdiv = z/16; 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci if (minfo->fbcon.var.bits_per_pixel == 24) { 3398c2ecf20Sopenharmony_ci hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0; 3408c2ecf20Sopenharmony_ci hw->DACclk[4] = (65 - loopfeed) | 0x80; 3418c2ecf20Sopenharmony_ci if (minfo->accel.ramdac_rev > 0x20) { 3428c2ecf20Sopenharmony_ci if (isInterleave(minfo)) 3438c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3; 3448c2ecf20Sopenharmony_ci else { 3458c2ecf20Sopenharmony_ci hw->DACclk[4] &= ~0xC0; 3468c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3; 3478c2ecf20Sopenharmony_ci } 3488c2ecf20Sopenharmony_ci } else { 3498c2ecf20Sopenharmony_ci if (isInterleave(minfo)) 3508c2ecf20Sopenharmony_ci ; /* default... */ 3518c2ecf20Sopenharmony_ci else { 3528c2ecf20Sopenharmony_ci hw->DACclk[4] ^= 0xC0; /* change from 0x80 to 0x40 */ 3538c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XLATCHCTRL] = TVP3026A_XLATCHCTRL_4_3; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci hw->DACclk[5] = looppost | 0xF8; 3578c2ecf20Sopenharmony_ci if (minfo->devflags.mga_24bpp_fix) 3588c2ecf20Sopenharmony_ci hw->DACclk[5] ^= 0x40; 3598c2ecf20Sopenharmony_ci } else { 3608c2ecf20Sopenharmony_ci hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0; 3618c2ecf20Sopenharmony_ci hw->DACclk[4] = 65 - loopfeed; 3628c2ecf20Sopenharmony_ci hw->DACclk[5] = looppost | 0xF0; 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XMEMPLLCTRL] = loopdiv | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL; 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci return 0; 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_cistatic int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci u_int8_t muxctrl = isInterleave(minfo) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT; 3728c2ecf20Sopenharmony_ci struct matrox_hw_state *hw = &minfo->hw; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci DBG(__func__) 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci memcpy(hw->DACreg, MGADACbpp32, sizeof(MGADACbpp32)); 3778c2ecf20Sopenharmony_ci switch (minfo->fbcon.var.bits_per_pixel) { 3788c2ecf20Sopenharmony_ci case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */ 3798c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR; 3808c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_4BIT; 3818c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV8; 3828c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW; 3838c2ecf20Sopenharmony_ci break; 3848c2ecf20Sopenharmony_ci case 8: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_8_1; /* or _4_1, they are same */ 3858c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR; 3868c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_8BIT; 3878c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4; 3888c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW; 3898c2ecf20Sopenharmony_ci break; 3908c2ecf20Sopenharmony_ci case 16: 3918c2ecf20Sopenharmony_ci /* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used every time) */ 3928c2ecf20Sopenharmony_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); 3938c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT; 3948c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2; 3958c2ecf20Sopenharmony_ci break; 3968c2ecf20Sopenharmony_ci case 24: 3978c2ecf20Sopenharmony_ci /* XLATCHCTRL is: for (A) use _4_3 (?_8_3 is same? TBD), for (B) it is set in setpclk */ 3988c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_888; 3998c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT; 4008c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4; 4018c2ecf20Sopenharmony_ci break; 4028c2ecf20Sopenharmony_ci case 32: 4038c2ecf20Sopenharmony_ci /* XLATCHCTRL should be _2_1 / _1_1... Why is not? (_2_1 is used every time) */ 4048c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT; 4058c2ecf20Sopenharmony_ci break; 4068c2ecf20Sopenharmony_ci default: 4078c2ecf20Sopenharmony_ci return 1; /* TODO: failed */ 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci if (matroxfb_vgaHWinit(minfo, m)) return 1; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci /* set SYNC */ 4128c2ecf20Sopenharmony_ci hw->MiscOutReg = 0xCB; 4138c2ecf20Sopenharmony_ci if (m->sync & FB_SYNC_HOR_HIGH_ACT) 4148c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_HSYNC_NEG; 4158c2ecf20Sopenharmony_ci if (m->sync & FB_SYNC_VERT_HIGH_ACT) 4168c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_VSYNC_NEG; 4178c2ecf20Sopenharmony_ci if (m->sync & FB_SYNC_ON_GREEN) 4188c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_SYNC_ON_GREEN; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci /* set DELAY */ 4218c2ecf20Sopenharmony_ci if (minfo->video.len < 0x400000) 4228c2ecf20Sopenharmony_ci hw->CRTCEXT[3] |= 0x08; 4238c2ecf20Sopenharmony_ci else if (minfo->video.len > 0x400000) 4248c2ecf20Sopenharmony_ci hw->CRTCEXT[3] |= 0x10; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci /* set HWCURSOR */ 4278c2ecf20Sopenharmony_ci if (m->interlaced) { 4288c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_INTERLACED; 4298c2ecf20Sopenharmony_ci } 4308c2ecf20Sopenharmony_ci if (m->HTotal >= 1536) 4318c2ecf20Sopenharmony_ci hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_BLANK4096; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci /* set interleaving */ 4348c2ecf20Sopenharmony_ci hw->MXoptionReg &= ~0x00001000; 4358c2ecf20Sopenharmony_ci if (isInterleave(minfo)) hw->MXoptionReg |= 0x00001000; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci /* set DAC */ 4388c2ecf20Sopenharmony_ci Ti3026_setpclk(minfo, m->pixclock); 4398c2ecf20Sopenharmony_ci return 0; 4408c2ecf20Sopenharmony_ci} 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_cistatic void ti3026_setMCLK(struct matrox_fb_info *minfo, int fout) 4438c2ecf20Sopenharmony_ci{ 4448c2ecf20Sopenharmony_ci unsigned int f_pll; 4458c2ecf20Sopenharmony_ci unsigned int pclk_m, pclk_n, pclk_p; 4468c2ecf20Sopenharmony_ci unsigned int mclk_m, mclk_n, mclk_p; 4478c2ecf20Sopenharmony_ci unsigned int rfhcnt, mclk_ctl; 4488c2ecf20Sopenharmony_ci int tmout; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci DBG(__func__) 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci f_pll = Ti3026_calcclock(minfo, fout, minfo->max_pixel_clock, &mclk_n, &mclk_m, &mclk_p); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci /* save pclk */ 4558c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFC); 4568c2ecf20Sopenharmony_ci pclk_n = inTi3026(minfo, TVP3026_XPIXPLLDATA); 4578c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFD); 4588c2ecf20Sopenharmony_ci pclk_m = inTi3026(minfo, TVP3026_XPIXPLLDATA); 4598c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFE); 4608c2ecf20Sopenharmony_ci pclk_p = inTi3026(minfo, TVP3026_XPIXPLLDATA); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci /* stop pclk */ 4638c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFE); 4648c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci /* set pclk to new mclk */ 4678c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFC); 4688c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_n | 0xC0); 4698c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_m); 4708c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_p | 0xB0); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci /* wait for PLL to lock */ 4738c2ecf20Sopenharmony_ci for (tmout = 500000; tmout; tmout--) { 4748c2ecf20Sopenharmony_ci if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40) 4758c2ecf20Sopenharmony_ci break; 4768c2ecf20Sopenharmony_ci udelay(10); 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci if (!tmout) 4798c2ecf20Sopenharmony_ci printk(KERN_ERR "matroxfb: Temporary pixel PLL not locked after 5 secs\n"); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci /* output pclk on mclk pin */ 4828c2ecf20Sopenharmony_ci mclk_ctl = inTi3026(minfo, TVP3026_XMEMPLLCTRL); 4838c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7); 4848c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4); 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci /* stop MCLK */ 4878c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFB); 4888c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLDATA, 0x00); 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci /* set mclk to new freq */ 4918c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xF3); 4928c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_n | 0xC0); 4938c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_m); 4948c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_p | 0xB0); 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci /* wait for PLL to lock */ 4978c2ecf20Sopenharmony_ci for (tmout = 500000; tmout; tmout--) { 4988c2ecf20Sopenharmony_ci if (inTi3026(minfo, TVP3026_XMEMPLLDATA) & 0x40) 4998c2ecf20Sopenharmony_ci break; 5008c2ecf20Sopenharmony_ci udelay(10); 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci if (!tmout) 5038c2ecf20Sopenharmony_ci printk(KERN_ERR "matroxfb: Memory PLL not locked after 5 secs\n"); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci f_pll = f_pll * 333 / (10000 << mclk_p); 5068c2ecf20Sopenharmony_ci if (isMilleniumII(minfo)) { 5078c2ecf20Sopenharmony_ci rfhcnt = (f_pll - 128) / 256; 5088c2ecf20Sopenharmony_ci if (rfhcnt > 15) 5098c2ecf20Sopenharmony_ci rfhcnt = 15; 5108c2ecf20Sopenharmony_ci } else { 5118c2ecf20Sopenharmony_ci rfhcnt = (f_pll - 64) / 128; 5128c2ecf20Sopenharmony_ci if (rfhcnt > 15) 5138c2ecf20Sopenharmony_ci rfhcnt = 0; 5148c2ecf20Sopenharmony_ci } 5158c2ecf20Sopenharmony_ci minfo->hw.MXoptionReg = (minfo->hw.MXoptionReg & ~0x000F0000) | (rfhcnt << 16); 5168c2ecf20Sopenharmony_ci pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg); 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci /* output MCLK to MCLK pin */ 5198c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL); 5208c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4); 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci /* stop PCLK */ 5238c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFE); 5248c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00); 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci /* restore pclk */ 5278c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0xFC); 5288c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_n); 5298c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_m); 5308c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_p); 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci /* wait for PLL to lock */ 5338c2ecf20Sopenharmony_ci for (tmout = 500000; tmout; tmout--) { 5348c2ecf20Sopenharmony_ci if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40) 5358c2ecf20Sopenharmony_ci break; 5368c2ecf20Sopenharmony_ci udelay(10); 5378c2ecf20Sopenharmony_ci } 5388c2ecf20Sopenharmony_ci if (!tmout) 5398c2ecf20Sopenharmony_ci printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n"); 5408c2ecf20Sopenharmony_ci} 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_cistatic void ti3026_ramdac_init(struct matrox_fb_info *minfo) 5438c2ecf20Sopenharmony_ci{ 5448c2ecf20Sopenharmony_ci DBG(__func__) 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci minfo->features.pll.vco_freq_min = 110000; 5478c2ecf20Sopenharmony_ci minfo->features.pll.ref_freq = 114545; 5488c2ecf20Sopenharmony_ci minfo->features.pll.feed_div_min = 2; 5498c2ecf20Sopenharmony_ci minfo->features.pll.feed_div_max = 24; 5508c2ecf20Sopenharmony_ci minfo->features.pll.in_div_min = 2; 5518c2ecf20Sopenharmony_ci minfo->features.pll.in_div_max = 63; 5528c2ecf20Sopenharmony_ci minfo->features.pll.post_shift_max = 3; 5538c2ecf20Sopenharmony_ci if (minfo->devflags.noinit) 5548c2ecf20Sopenharmony_ci return; 5558c2ecf20Sopenharmony_ci ti3026_setMCLK(minfo, 60000); 5568c2ecf20Sopenharmony_ci} 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_cistatic void Ti3026_restore(struct matrox_fb_info *minfo) 5598c2ecf20Sopenharmony_ci{ 5608c2ecf20Sopenharmony_ci int i; 5618c2ecf20Sopenharmony_ci unsigned char progdac[6]; 5628c2ecf20Sopenharmony_ci struct matrox_hw_state *hw = &minfo->hw; 5638c2ecf20Sopenharmony_ci CRITFLAGS 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci DBG(__func__) 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci#ifdef DEBUG 5688c2ecf20Sopenharmony_ci dprintk(KERN_INFO "EXTVGA regs: "); 5698c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) 5708c2ecf20Sopenharmony_ci dprintk("%02X:", hw->CRTCEXT[i]); 5718c2ecf20Sopenharmony_ci dprintk("\n"); 5728c2ecf20Sopenharmony_ci#endif 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci CRITBEGIN 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci CRITEND 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci matroxfb_vgaHWrestore(minfo); 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci CRITBEGIN 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci minfo->crtc1.panpos = -1; 5858c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) 5868c2ecf20Sopenharmony_ci mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci for (i = 0; i < 21; i++) { 5898c2ecf20Sopenharmony_ci outTi3026(minfo, DACseq[i], hw->DACreg[i]); 5908c2ecf20Sopenharmony_ci } 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x00); 5938c2ecf20Sopenharmony_ci progdac[0] = inTi3026(minfo, TVP3026_XPIXPLLDATA); 5948c2ecf20Sopenharmony_ci progdac[3] = inTi3026(minfo, TVP3026_XLOOPPLLDATA); 5958c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x15); 5968c2ecf20Sopenharmony_ci progdac[1] = inTi3026(minfo, TVP3026_XPIXPLLDATA); 5978c2ecf20Sopenharmony_ci progdac[4] = inTi3026(minfo, TVP3026_XLOOPPLLDATA); 5988c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x2A); 5998c2ecf20Sopenharmony_ci progdac[2] = inTi3026(minfo, TVP3026_XPIXPLLDATA); 6008c2ecf20Sopenharmony_ci progdac[5] = inTi3026(minfo, TVP3026_XLOOPPLLDATA); 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci CRITEND 6038c2ecf20Sopenharmony_ci if (memcmp(hw->DACclk, progdac, 6)) { 6048c2ecf20Sopenharmony_ci /* agrhh... setting up PLL is very slow on Millennium... */ 6058c2ecf20Sopenharmony_ci /* Mystique PLL is locked in few ms, but Millennium PLL lock takes about 0.15 s... */ 6068c2ecf20Sopenharmony_ci /* Maybe even we should call schedule() ? */ 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci CRITBEGIN 6098c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]); 6108c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x2A); 6118c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0); 6128c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, 0); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x00); 6158c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 6168c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, hw->DACclk[i]); 6178c2ecf20Sopenharmony_ci /* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */ 6188c2ecf20Sopenharmony_ci if (hw->MiscOutReg & 0x08) { 6198c2ecf20Sopenharmony_ci int tmout; 6208c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x3F); 6218c2ecf20Sopenharmony_ci for (tmout = 500000; tmout; --tmout) { 6228c2ecf20Sopenharmony_ci if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40) 6238c2ecf20Sopenharmony_ci break; 6248c2ecf20Sopenharmony_ci udelay(10); 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci CRITEND 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci if (!tmout) 6308c2ecf20Sopenharmony_ci printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n"); 6318c2ecf20Sopenharmony_ci else 6328c2ecf20Sopenharmony_ci dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout); 6338c2ecf20Sopenharmony_ci CRITBEGIN 6348c2ecf20Sopenharmony_ci } 6358c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]); 6368c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x00); 6378c2ecf20Sopenharmony_ci for (i = 3; i < 6; i++) 6388c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XLOOPPLLDATA, hw->DACclk[i]); 6398c2ecf20Sopenharmony_ci CRITEND 6408c2ecf20Sopenharmony_ci if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) { 6418c2ecf20Sopenharmony_ci int tmout; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci CRITBEGIN 6448c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x3F); 6458c2ecf20Sopenharmony_ci for (tmout = 500000; tmout; --tmout) { 6468c2ecf20Sopenharmony_ci if (inTi3026(minfo, TVP3026_XLOOPPLLDATA) & 0x40) 6478c2ecf20Sopenharmony_ci break; 6488c2ecf20Sopenharmony_ci udelay(10); 6498c2ecf20Sopenharmony_ci } 6508c2ecf20Sopenharmony_ci CRITEND 6518c2ecf20Sopenharmony_ci if (!tmout) 6528c2ecf20Sopenharmony_ci printk(KERN_ERR "matroxfb: Loop PLL not locked after 5 secs\n"); 6538c2ecf20Sopenharmony_ci else 6548c2ecf20Sopenharmony_ci dprintk(KERN_INFO "LoopPLL: %d\n", 500000-tmout); 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci } 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci#ifdef DEBUG 6598c2ecf20Sopenharmony_ci dprintk(KERN_DEBUG "3026DACregs "); 6608c2ecf20Sopenharmony_ci for (i = 0; i < 21; i++) { 6618c2ecf20Sopenharmony_ci dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]); 6628c2ecf20Sopenharmony_ci if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... "); 6638c2ecf20Sopenharmony_ci } 6648c2ecf20Sopenharmony_ci dprintk(KERN_DEBUG "DACclk "); 6658c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) 6668c2ecf20Sopenharmony_ci dprintk("C%02X=%02X ", i, hw->DACclk[i]); 6678c2ecf20Sopenharmony_ci dprintk("\n"); 6688c2ecf20Sopenharmony_ci#endif 6698c2ecf20Sopenharmony_ci} 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_cistatic void Ti3026_reset(struct matrox_fb_info *minfo) 6728c2ecf20Sopenharmony_ci{ 6738c2ecf20Sopenharmony_ci DBG(__func__) 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci ti3026_ramdac_init(minfo); 6768c2ecf20Sopenharmony_ci} 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_cistatic struct matrox_altout ti3026_output = { 6798c2ecf20Sopenharmony_ci .name = "Primary output", 6808c2ecf20Sopenharmony_ci}; 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_cistatic int Ti3026_preinit(struct matrox_fb_info *minfo) 6838c2ecf20Sopenharmony_ci{ 6848c2ecf20Sopenharmony_ci static const int vxres_mill2[] = { 512, 640, 768, 800, 832, 960, 6858c2ecf20Sopenharmony_ci 1024, 1152, 1280, 1600, 1664, 1920, 6868c2ecf20Sopenharmony_ci 2048, 0}; 6878c2ecf20Sopenharmony_ci static const int vxres_mill1[] = { 640, 768, 800, 960, 6888c2ecf20Sopenharmony_ci 1024, 1152, 1280, 1600, 1920, 6898c2ecf20Sopenharmony_ci 2048, 0}; 6908c2ecf20Sopenharmony_ci struct matrox_hw_state *hw = &minfo->hw; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci DBG(__func__) 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci minfo->millenium = 1; 6958c2ecf20Sopenharmony_ci minfo->milleniumII = (minfo->pcidev->device != PCI_DEVICE_ID_MATROX_MIL); 6968c2ecf20Sopenharmony_ci minfo->capable.cfb4 = 1; 6978c2ecf20Sopenharmony_ci minfo->capable.text = 1; /* isMilleniumII(minfo); */ 6988c2ecf20Sopenharmony_ci minfo->capable.vxres = isMilleniumII(minfo) ? vxres_mill2 : vxres_mill1; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci minfo->outputs[0].data = minfo; 7018c2ecf20Sopenharmony_ci minfo->outputs[0].output = &ti3026_output; 7028c2ecf20Sopenharmony_ci minfo->outputs[0].src = minfo->outputs[0].default_src; 7038c2ecf20Sopenharmony_ci minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci if (minfo->devflags.noinit) 7068c2ecf20Sopenharmony_ci return 0; 7078c2ecf20Sopenharmony_ci /* preserve VGA I/O, BIOS and PPC */ 7088c2ecf20Sopenharmony_ci hw->MXoptionReg &= 0xC0000100; 7098c2ecf20Sopenharmony_ci hw->MXoptionReg |= 0x002C0000; 7108c2ecf20Sopenharmony_ci if (minfo->devflags.novga) 7118c2ecf20Sopenharmony_ci hw->MXoptionReg &= ~0x00000100; 7128c2ecf20Sopenharmony_ci if (minfo->devflags.nobios) 7138c2ecf20Sopenharmony_ci hw->MXoptionReg &= ~0x40000000; 7148c2ecf20Sopenharmony_ci if (minfo->devflags.nopciretry) 7158c2ecf20Sopenharmony_ci hw->MXoptionReg |= 0x20000000; 7168c2ecf20Sopenharmony_ci pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg); 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci minfo->accel.ramdac_rev = inTi3026(minfo, TVP3026_XSILICONREV); 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XCLKCTRL, TVP3026_XCLKCTRL_SRC_CLK0VGA | TVP3026_XCLKCTRL_CLKSTOPPED); 7218c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XTRUECOLORCTRL, TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR); 7228c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XMUXCTRL, TVP3026_XMUXCTRL_VGA); 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPLLADDR, 0x2A); 7258c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0x00); 7268c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00); 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci mga_outb(M_MISC_REG, 0x67); 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci outTi3026(minfo, TVP3026_XMEMPLLCTRL, TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL); 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci mga_outl(M_RESET, 1); 7338c2ecf20Sopenharmony_ci udelay(250); 7348c2ecf20Sopenharmony_ci mga_outl(M_RESET, 0); 7358c2ecf20Sopenharmony_ci udelay(250); 7368c2ecf20Sopenharmony_ci mga_outl(M_MACCESS, 0x00008000); 7378c2ecf20Sopenharmony_ci udelay(10); 7388c2ecf20Sopenharmony_ci return 0; 7398c2ecf20Sopenharmony_ci} 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_cistruct matrox_switch matrox_millennium = { 7428c2ecf20Sopenharmony_ci .preinit = Ti3026_preinit, 7438c2ecf20Sopenharmony_ci .reset = Ti3026_reset, 7448c2ecf20Sopenharmony_ci .init = Ti3026_init, 7458c2ecf20Sopenharmony_ci .restore = Ti3026_restore 7468c2ecf20Sopenharmony_ci}; 7478c2ecf20Sopenharmony_ciEXPORT_SYMBOL(matrox_millennium); 7488c2ecf20Sopenharmony_ci#endif 7498c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 750