diff options
author | 2005-04-16 15:20:36 -0700 | |
---|---|---|
committer | 2005-04-16 15:20:36 -0700 | |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/video/sis | |
download | linux-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.tar.gz linux-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.tar.bz2 linux-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.zip |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/video/sis')
-rw-r--r-- | drivers/video/sis/300vtbl.h | 1965 | ||||
-rw-r--r-- | drivers/video/sis/310vtbl.h | 2754 | ||||
-rw-r--r-- | drivers/video/sis/Makefile | 7 | ||||
-rw-r--r-- | drivers/video/sis/init.c | 5318 | ||||
-rw-r--r-- | drivers/video/sis/init.h | 2472 | ||||
-rw-r--r-- | drivers/video/sis/init301.c | 12239 | ||||
-rw-r--r-- | drivers/video/sis/init301.h | 410 | ||||
-rw-r--r-- | drivers/video/sis/initdef.h | 671 | ||||
-rw-r--r-- | drivers/video/sis/oem300.h | 859 | ||||
-rw-r--r-- | drivers/video/sis/oem310.h | 449 | ||||
-rw-r--r-- | drivers/video/sis/osdef.h | 131 | ||||
-rw-r--r-- | drivers/video/sis/sis.h | 573 | ||||
-rw-r--r-- | drivers/video/sis/sis_accel.c | 678 | ||||
-rw-r--r-- | drivers/video/sis/sis_accel.h | 409 | ||||
-rw-r--r-- | drivers/video/sis/sis_main.c | 6027 | ||||
-rw-r--r-- | drivers/video/sis/sis_main.h | 955 | ||||
-rw-r--r-- | drivers/video/sis/vgatypes.h | 242 | ||||
-rw-r--r-- | drivers/video/sis/vstruct.h | 676 |
18 files changed, 36835 insertions, 0 deletions
diff --git a/drivers/video/sis/300vtbl.h b/drivers/video/sis/300vtbl.h new file mode 100644 index 000000000000..b6d5c71b2563 --- /dev/null +++ b/drivers/video/sis/300vtbl.h @@ -0,0 +1,1965 @@ +/* $XFree86$ */ +/* $XdotOrg$ */ +/* + * Register settings for SiS 300 series + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the named License, + * * or any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program; if not, write to the Free Software + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Otherwise, the following license terms apply: + * + * * Redistribution and use in source and binary forms, with or without + * * modification, are permitted provided that the following conditions + * * are met: + * * 1) Redistributions of source code must retain the above copyright + * * notice, this list of conditions and the following disclaimer. + * * 2) Redistributions in binary form must reproduce the above copyright + * * notice, this list of conditions and the following disclaimer in the + * * documentation and/or other materials provided with the distribution. + * * 3) The name of the author may not be used to endorse or promote products + * * derived from this software without specific prior written permission. + * * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + */ + +static const SiS_StStruct SiS300_SModeIDTable[] = +{ + {0x01,0x9208,0x01,0x00,0x00,0x00,0x00,0x00, 0}, + {0x01,0x1210,0x14,0x01,0x01,0x00,0x00,0x00, 0}, + {0x01,0x1010,0x17,0x02,0x02,0x00,0x00,0x00, 0}, + {0x03,0x8208,0x03,0x00,0x00,0x00,0x00,0x00, 0}, + {0x03,0x0210,0x16,0x01,0x01,0x00,0x00,0x00, 0}, + {0x03,0x0010,0x18,0x02,0x02,0x00,0x00,0x00, 0}, + {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x00, 0}, + {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x00, 0}, + {0x07,0x0000,0x07,0x03,0x03,0x00,0x00,0x00, 0}, + {0x07,0x0000,0x19,0x02,0x02,0x00,0x00,0x00, 0}, + {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x00, 0}, + {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x00, 0}, + {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x00, 0}, + {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x00, 0}, + {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x00, 0}, + {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x00, 0}, + {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x00, 0}, + {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x00, 0}, + {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x00, 0}, + {0xff, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +static const SiS_ExtStruct SiS300_EModeIDTable[] = +{ + {0x6a,0x2212,0x0102,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00,-1}, /* 800x600x? */ + {0x2e,0x0a1b,0x0101,SIS_RI_640x480, 0x00,0x00,0x00,0x00,0x08,-1}, + {0x2f,0x021b,0x0100,SIS_RI_640x400, 0x00,0x00,0x00,0x00,0x10,-1}, /* 640x400x8 */ + {0x30,0x2a1b,0x0103,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00,-1}, + {0x31,0x4a1b,0x0000,SIS_RI_720x480, 0x00,0x00,0x00,0x00,0x11,-1}, /* 720x480x8 */ + {0x32,0x6a1b,0x0000,SIS_RI_720x576, 0x00,0x00,0x00,0x00,0x12,-1}, /* 720x576x8 */ + {0x33,0x4a1d,0x0000,SIS_RI_720x480, 0x00,0x00,0x00,0x00,0x11,-1}, /* 720x480x16 */ + {0x34,0x6a1d,0x0000,SIS_RI_720x576, 0x00,0x00,0x00,0x00,0x12,-1}, /* 720x576x16 */ + {0x35,0x4a1f,0x0000,SIS_RI_720x480, 0x00,0x00,0x00,0x00,0x11,-1}, /* 720x480x32 */ + {0x36,0x6a1f,0x0000,SIS_RI_720x576, 0x00,0x00,0x00,0x00,0x12,-1}, /* 720x576x32 */ + {0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1}, /* 1024x768x? */ + {0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1}, /* 1024x768x8 */ + {0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1}, /* 1280x1024x8 */ + {0x3c,0x063b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1}, + {0x3d,0x067d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1}, + {0x40,0x921c,0x010d,SIS_RI_320x200, 0x00,0x00,0x00,0x00,0x23,-1}, /* 320x200x15 */ + {0x41,0x921d,0x010e,SIS_RI_320x200, 0x00,0x00,0x00,0x00,0x23,-1}, /* 320x200x16 */ + {0x43,0x0a1c,0x0110,SIS_RI_640x480, 0x00,0x00,0x00,0x00,0x08,-1}, + {0x44,0x0a1d,0x0111,SIS_RI_640x480, 0x00,0x00,0x00,0x00,0x08,-1}, + {0x46,0x2a1c,0x0113,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00,-1}, /* 800x600x15 */ + {0x47,0x2a1d,0x0114,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00,-1}, /* 800x600x16 */ + {0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1}, + {0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1}, + {0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1}, + {0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1}, + {0x50,0x921b,0x0132,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x24,-1}, /* 320x240x8 */ + {0x51,0xb21b,0x0133,SIS_RI_400x300, 0x00,0x00,0x00,0x00,0x25,-1}, /* 400x300x8 */ + {0x52,0x921b,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x26,-1}, /* 512x384x8 */ + {0x56,0x921d,0x0135,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x24,-1}, /* 320x240x16 */ + {0x57,0xb21d,0x0136,SIS_RI_400x300, 0x00,0x00,0x00,0x00,0x25,-1}, /* 400x300x16 */ + {0x58,0x921d,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x26,-1}, /* 512x384x16 */ + {0x59,0x921b,0x0138,SIS_RI_320x200, 0x00,0x00,0x00,0x00,0x23,-1}, /* 320x200x8 */ + {0x5c,0x921f,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x26,-1}, /* 512x384x32 */ + {0x5d,0x021d,0x0139,SIS_RI_640x400, 0x00,0x00,0x00,0x00,0x10,-1}, /* 640x400x16 */ + {0x5e,0x021f,0x0000,SIS_RI_640x400, 0x00,0x00,0x00,0x00,0x10,-1}, /* 640x400x32 */ + {0x62,0x0a3f,0x013a,SIS_RI_640x480, 0x00,0x00,0x00,0x00,0x08,-1}, + {0x63,0x2a3f,0x013b,SIS_RI_800x600, 0x00,0x00,0x00,0x00,0x00,-1}, /* 800x600x32 */ + {0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1}, + {0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1}, + {0x66,0x06ff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1}, + {0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1}, + {0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1}, + {0x6b,0x07ff,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1}, + {0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1}, /* 2048x1536x8 - not in BIOS! */ + {0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1}, /* 2048x1536x16 - not in BIOS! */ + {0x70,0x6a1b,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x00,0x2d,-1}, /* 800x480x8 */ + {0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1}, /* 1024x576x8 */ + {0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1}, /* 1024x576x16 */ + {0x75,0x0e3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1}, /* 1280x720x16 */ + {0x76,0x6a1f,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x00,0x2d,-1}, /* 800x480x32 */ + {0x77,0x4a3f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1}, /* 1024x576x32 */ + {0x78,0x0eff,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1}, /* 1280x720x32 */ + {0x79,0x0e3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1}, /* 1280x720x8 */ + {0x7a,0x6a1d,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x00,0x2d,-1}, /* 800x480x16 */ + {0x7c,0x0a3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1}, /* 1280x960x8 */ + {0x7d,0x0a7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1}, /* 1280x960x16 */ + {0x7e,0x0aff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1}, /* 1280x960x32 */ + {0x20,0x4a1b,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1}, /* 1024x600 */ + {0x21,0x4a3d,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1}, + {0x22,0x4a7f,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1}, + {0x23,0x4a1b,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1}, /* 1152x768 */ + {0x24,0x4a3d,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1}, + {0x25,0x4a7f,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1}, + {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1}, /* 1152x864 */ + {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1}, + {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1}, + {0x39,0x6a1b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x39,-1}, /* 848x480 */ + {0x3b,0x6a3d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x39,-1}, + {0x3e,0x6a7f,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x39,-1}, + {0x3f,0x6a1b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x3b,-1}, /* 856x480 */ + {0x42,0x6a3d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x3b,-1}, + {0x45,0x6a7f,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x3b,-1}, + {0x48,0x6a3b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1360x768 */ + {0x4b,0x6a7d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3d,-1}, + {0x4e,0x6aff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3d,-1}, + {0x4f,0x921f,0x0000,SIS_RI_320x200, 0x00,0x00,0x00,0x00,0x23,-1}, /* 320x200x32 */ + {0x53,0x921f,0x0000,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x24,-1}, /* 320x240x32 */ + {0x54,0xb21f,0x0000,SIS_RI_400x300, 0x00,0x00,0x00,0x00,0x25,-1}, /* 400x300x32 */ + {0x55,0x2e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3e,-1}, /* 1280x768 */ + {0x5a,0x2e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3e,-1}, + {0x5b,0x2eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3e,-1}, + {0x5f,0x6a1b,0x0000,SIS_RI_768x576, 0x00,0x00,0x00,0x00,0x3f,-1}, /* 768x576x8 */ + {0x60,0x6a1d,0x0000,SIS_RI_768x576, 0x00,0x00,0x00,0x00,0x3f,-1}, /* 768x576x16 */ + {0x61,0x6a1f,0x0000,SIS_RI_768x576, 0x00,0x00,0x00,0x00,0x3f,-1}, /* 768x576x32 */ + {0x67,0x6e3b,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x40,-1}, /* 1360x1024x8 (BARCO) */ + {0x6f,0x6e7d,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x40,-1}, /* 1360x1024x16 (BARCO) */ + {0x72,0x6eff,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x40,-1}, /* 1360x1024x32 (BARCO) */ + {0xff,0x0000,0xffff,0, 0x00,0x00,0x00,0x00,0x00} +}; + +static const SiS_Ext2Struct SiS300_RefIndex[] = +{ + {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0}, /* 00 */ + {0x0467,0x0e,0x44,0x05,0x05,0x6a, 800, 600, 0}, /* 01 */ + {0x0067,0x0f,0x07,0x48,0x05,0x6a, 800, 600, 0}, /* 02 - CRT1CRTC was 0x4f */ + {0x0067,0x10,0x06,0x8b,0x05,0x6a, 800, 600, 0}, /* 03 */ + {0x0147,0x11,0x08,0x00,0x05,0x6a, 800, 600, 0}, /* 04 */ + {0x0147,0x12,0x0c,0x00,0x05,0x6a, 800, 600, 0}, /* 05 */ + {0x0047,0x11,0x4e,0x00,0x05,0x6a, 800, 600, 0}, /* 06 - CRT1CRTC was 0x51 */ + {0x0047,0x11,0x13,0x00,0x05,0x6a, 800, 600, 0}, /* 07 */ + {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0}, /* 08 */ + {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0}, /* 09 */ + {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0}, /* 0a */ + {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0}, /* 0b */ + {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0}, /* 0c */ + {0xc047,0x0a,0x08,0x00,0x04,0x2e, 640, 480, 0}, /* 0d */ + {0xc047,0x0b,0x0a,0x00,0x04,0x2e, 640, 480, 0}, /* 0e */ + {0xc047,0x0c,0x10,0x00,0x04,0x2e, 640, 480, 0}, /* 0f */ + {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0}, /* 10 */ + {0xc06f,0x31,0x01,0x06,0x13,0x31, 720, 480, 0}, /* 11 */ + {0x006f,0x32,0x03,0x06,0x14,0x32, 720, 576, 0}, /* 12 */ + {0x0187,0x15,0x05,0x00,0x06,0x37,1024, 768, 0}, /* 13 */ + {0xc877,0x16,0x09,0x06,0x06,0x37,1024, 768, 0}, /* 14 */ + {0xc067,0x17,0x0b,0x49,0x06,0x37,1024, 768, 0}, /* 15 - CRT1CRTC was 0x97 */ + {0x0267,0x18,0x0d,0x00,0x06,0x37,1024, 768, 0}, /* 16 */ + {0x0047,0x19,0x11,0x8c,0x06,0x37,1024, 768, 0}, /* 17 - CRT1CRTC was 0x59 */ + {0x0047,0x1a,0x52,0x00,0x06,0x37,1024, 768, 0}, /* 18 */ + {0x0007,0x1b,0x16,0x00,0x06,0x37,1024, 768, 0}, /* 19 - CRT1CRTC was 0x5b */ + {0x0387,0x1c,0x4d,0x00,0x07,0x3a,1280,1024, 0}, /* 1a - CRT1CRTC was 0x5c */ + {0x0077,0x1d,0x14,0x07,0x07,0x3a,1280,1024, 0}, /* 1b */ + {0x0047,0x1e,0x17,0x00,0x07,0x3a,1280,1024, 0}, /* 1c */ + {0x0007,0x1f,0x98,0x00,0x07,0x3a,1280,1024, 0}, /* 1d */ + {0x0007,0x20,0x59,0x00,0x00,0x3c,1600,1200, 0}, /* 1e - CRT1CRTC was 0x60 */ + {0x0007,0x21,0x5a,0x00,0x00,0x3c,1600,1200, 0}, /* 1f */ + {0x0007,0x22,0x1b,0x00,0x00,0x3c,1600,1200, 0}, /* 20 */ + {0x0007,0x23,0x1d,0x00,0x00,0x3c,1600,1200, 0}, /* 21 - CRT1CRTC was 0x63 */ + {0x0007,0x24,0x1e,0x00,0x00,0x3c,1600,1200, 0}, /* 22 */ + {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0}, /* 23 */ + {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0}, /* 24 */ + {0x0077,0x02,0x04,0x05,0x05,0x51, 400, 300, 0}, /* 25 */ + {0xc877,0x03,0x09,0x06,0x06,0x52, 512, 384, 0}, /* 26 */ /* was c077 */ + {0x8207,0x25,0x1f,0x00,0x00,0x68,1920,1440, 0}, /* 27 */ + {0x0007,0x26,0x20,0x00,0x00,0x6c,2048,1536, 0}, /* 28 */ + {0x0067,0x27,0x14,0x08,0x0a,0x6e,1280, 960, 0}, /* 29 - 1280x960-60 */ + {0x0027,0x45,0x3c,0x08,0x0a,0x6e,1280, 960, 0}, /* 2a - 1280x960-85 */ + {0xc077,0x33,0x09,0x06,0x00,0x20,1024, 600, 0}, /* 2b */ + {0xc077,0x34,0x0b,0x06,0x00,0x23,1152, 768, 0}, /* 2c */ /* VCLK 0x09 */ + {0x0077,0x35,0x27,0x08,0x18,0x70, 800, 480, 0}, /* 2d */ + {0x0047,0x36,0x37,0x08,0x18,0x70, 800, 480, 0}, /* 2e */ + {0x0047,0x37,0x08,0x08,0x18,0x70, 800, 480, 0}, /* 2f */ + {0x0077,0x38,0x09,0x09,0x19,0x71,1024, 576, 0}, /* 30 */ + {0x0047,0x39,0x38,0x09,0x19,0x71,1024, 576, 0}, /* 31 */ + {0x0047,0x3a,0x11,0x09,0x19,0x71,1024, 576, 0}, /* 32 */ + {0x0077,0x3b,0x39,0x0a,0x0c,0x75,1280, 720, 0}, /* 33 */ + {0x0047,0x3c,0x3a,0x0a,0x0c,0x75,1280, 720, 0}, /* 34 */ + {0x0007,0x3d,0x3b,0x0a,0x0c,0x75,1280, 720, 0}, /* 35 */ + {0x0067,0x49,0x35,0x06,0x1a,0x29,1152, 864, 0}, /* 36 1152x864-60Hz */ + {0x0067,0x3e,0x34,0x06,0x1a,0x29,1152, 864, 0}, /* 37 1152x864-75Hz */ + {0x0047,0x44,0x3a,0x06,0x1a,0x29,1152, 864, 0}, /* 38 1152x864-85Hz */ + {0x00c7,0x3f,0x28,0x00,0x16,0x39, 848, 480, 0}, /* 39 848x480-38Hzi */ + {0xc067,0x40,0x3d,0x0b,0x16,0x39, 848, 480, 0}, /* 3a 848x480-60Hz */ + {0x00c7,0x41,0x28,0x00,0x17,0x3f, 856, 480, 0}, /* 3b 856x480-38Hzi */ + {0xc047,0x42,0x28,0x00,0x17,0x3f, 856, 480, 0}, /* 3c 856x480-60Hz */ + {0x0067,0x43,0x3e,0x0c,0x1b,0x48,1360, 768, 0}, /* 3d 1360x768-60Hz */ + {0x0077,0x46,0x3f,0x08,0x08,0x55,1280, 768, 0}, /* 3e 1280x768-60Hz */ + {0x006f,0x47,0x03,0x06,0x15,0x5f, 768, 576, 0}, /* 3f 768x576 */ + {0x0027,0x48,0x13,0x08,0x00,0x67,1360,1024, 0}, /* 40 1360x1024-59Hz (BARCO1366 only) */ + {0xffff, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +static const SiS_VBModeStruct SiS300_VBModeIDTable[] = +{ + {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, + {0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x02}, + {0x03,0x00,0x00,0x00,0x02,0x00,0x02,0x00}, + {0x03,0x00,0x00,0x00,0x02,0x00,0x02,0x01}, + {0x03,0x00,0x00,0x00,0x03,0x00,0x03,0x02}, + {0x05,0x00,0x00,0x01,0x04,0x00,0x00,0x00}, + {0x06,0x00,0x00,0x01,0x05,0x00,0x02,0x00}, + {0x07,0x00,0x00,0x00,0x03,0x00,0x03,0x01}, + {0x07,0x00,0x00,0x00,0x03,0x00,0x03,0x02}, + {0x0d,0x00,0x00,0x01,0x04,0x00,0x00,0x00}, + {0x0e,0x00,0x00,0x01,0x05,0x00,0x02,0x00}, + {0x0f,0x00,0x00,0x01,0x05,0x00,0x02,0x01}, + {0x10,0x00,0x00,0x01,0x05,0x00,0x02,0x01}, + {0x11,0x00,0x00,0x01,0x05,0x00,0x02,0x03}, + {0x12,0x00,0x00,0x01,0x05,0x00,0x02,0x03}, + {0x13,0x00,0x00,0x01,0x04,0x00,0x04,0x00}, + {0x6a,0x00,0x00,0x01,0x07,0x00,0x08,0x0a}, + {0x2e,0x00,0x00,0x01,0x05,0x00,0x06,0x08}, + {0x2f,0x00,0x00,0x01,0x05,0x00,0x06,0x06}, + {0x30,0x00,0x00,0x01,0x07,0x00,0x08,0x0a}, + {0x31,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x32,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x33,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x34,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x35,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x36,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x37,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c}, + {0x38,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c}, + {0x3a,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, + {0x40,0x00,0x00,0x01,0x04,0x00,0x05,0x05}, + {0x41,0x00,0x00,0x01,0x04,0x00,0x05,0x05}, + {0x43,0x00,0x00,0x01,0x05,0x00,0x06,0x08}, + {0x44,0x00,0x00,0x01,0x05,0x00,0x06,0x08}, + {0x46,0x00,0x00,0x01,0x07,0x00,0x08,0x0a}, + {0x47,0x00,0x00,0x01,0x07,0x00,0x08,0x0a}, + {0x49,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c}, + {0x4a,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c}, + {0x4c,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, + {0x4d,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, + {0x4f,0x00,0x00,0x01,0x04,0x00,0x05,0x05}, + {0x50,0x00,0x00,0x01,0x04,0x00,0x05,0x07}, + {0x51,0x00,0x00,0x01,0x07,0x00,0x07,0x09}, + {0x52,0x00,0x00,0x01,0x00,0x00,0x09,0x0b}, + {0x53,0x00,0x00,0x01,0x04,0x00,0x05,0x07}, + {0x54,0x00,0x00,0x01,0x07,0x00,0x07,0x09}, + {0x56,0x00,0x00,0x01,0x04,0x00,0x05,0x07}, + {0x57,0x00,0x00,0x01,0x07,0x00,0x07,0x09}, + {0x58,0x00,0x00,0x01,0x00,0x00,0x09,0x0b}, + {0x59,0x00,0x00,0x01,0x04,0x00,0x05,0x05}, + {0x5c,0x00,0x00,0x01,0x00,0x00,0x09,0x0b}, + {0x5d,0x00,0x00,0x01,0x05,0x00,0x06,0x06}, + {0x5e,0x00,0x00,0x01,0x05,0x00,0x06,0x06}, + {0x5f,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x60,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x61,0x00,0x00,0x01,0x06,0x00,0x00,0x00}, + {0x62,0x00,0x00,0x01,0x05,0x00,0x06,0x08}, + {0x63,0x00,0x00,0x01,0x07,0x00,0x08,0x0a}, + {0x64,0x00,0x00,0x01,0x00,0x00,0x0a,0x0c}, + {0x65,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, + {0x6c,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, + {0x6d,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, + {0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00} +}; + +static const SiS_CRT1TableStruct SiS300_CRT1Table[] = +{ +#if 1 + {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 0x00 - 320x200 */ + 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00, /* HRE [4],[15] is invalid - but correcting it does not work */ + 0x00}}, +#endif +#if 0 + {{0x2d,0x27,0x27,0x91,0x2c,0x92,0xbf,0x1f, /* 0x00 - corrected 320x200-72 - does not work */ + 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x04, + 0x00}}, +#endif + {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* 0x01 */ + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, /* HRE [4],[15] is invalid - but correcting it does not work */ + 0x00}}, +#if 0 + {{0x2d,0x27,0x27,0x91,0x2c,0x92,0x0b,0x3e, /* 0x01 - corrected 320x240-60 - does not work */ + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x04, + 0x00}}, +#endif + {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, /* 0x02 */ + 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05, + 0x01}}, +#if 0 + {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, /* 0x02 - corrected 400x300-60 */ + 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05, + 0x01}}, +#endif + {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5, + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01, + 0x01}}, + {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05, + 0x00}}, +#if 0 + {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, /* 0x05 */ + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05, + 0x00}}, +#endif + {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* 0x05 - corrected 640x480-60 */ + 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05, + 0x00}}, +#if 0 + {{0x63,0x4f,0x50,0x86,0x56,0x9b,0x06,0x3e, /* 0x06 */ + 0xe8,0x8b,0xdf,0xe7,0xff,0x10,0x00,0x01, + 0x00}}, +#endif + {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e, /* 0x06 - corrected 640x480-72 */ + 0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f, + 0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01, + 0x00}}, + {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f, + 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05, + 0x00}}, +#if 0 + {{0x66,0x4f,0x4f,0x86,0x56,0x9e,0x03,0x3e, /* 0x09 */ + 0xe4,0x87,0xdf,0xdf,0x04,0x00,0x00,0x01, + 0x00}}, +#endif + {{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e, /* 0x09 - corrected 640x480-100 */ + 0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05, + 0x00}}, +#if 0 + {{0x6c,0x4f,0x4f,0x83,0x59,0x9e,0x00,0x3e, /* 0x0a */ + 0xe5,0x8d,0xdf,0xdf,0x01,0x00,0x00,0x01, + 0x00}}, +#endif + {{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e, /* 0x0a - corrected 640x480-120 */ + 0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05, + 0x00}}, + {{0x63,0x4f,0x4f,0x87,0x56,0x9d,0xfb,0x1f, + 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x01, + 0x00}}, + {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f, + 0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01, /* Corrected VDE, VBE */ + 0x00}}, + {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0, + 0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05, + 0x01}}, + {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0, + 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06, + 0x01}}, + {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0, + 0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06, + 0x01}}, + {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0, + 0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06, + 0x01}}, + {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0, + 0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06, + 0x01}}, + {{0x8c,0x63,0x63,0x87,0x72,0x16,0x7e,0xf0, + 0x59,0x8d,0x57,0x57,0x7f,0x00,0x00,0x06, + 0x01}}, + {{0x7e,0x63,0x63,0x82,0x6c,0x14,0x75,0xe0, + 0x58,0x0b,0x57,0x57,0x76,0x20,0x00,0x06, + 0x01}}, + {{0x7e,0x63,0x63,0x82,0x6c,0x14,0x75,0xe0, /* 0x14 */ + 0x58,0x0b,0x57,0x57,0x76,0x20,0x00,0x06, + 0x01}}, + {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f, + 0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02, + 0x00}}, + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, + 0x01}}, + {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, + 0x01}}, + {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5, + 0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02, + 0x01}}, + {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5, + 0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02, + 0x01}}, + {{0x9f,0x7f,0x7f,0x83,0x83,0x93,0x1e,0xf5, /* 0x1a */ + 0x00,0x84,0xff,0xff,0x1f,0x10,0x00,0x02, + 0x01}}, + {{0xa2,0x7f,0x7f,0x86,0x84,0x94,0x37,0xf5, + 0x0b,0x82,0xff,0xff,0x38,0x10,0x00,0x02, + 0x01}}, + {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba, + 0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03, + 0x00}}, + {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a, + 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07, + 0x01}}, + {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a, /* 0x1e */ + 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07, + 0x01}}, + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a, + 0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07, + 0x01}}, + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, + 0x00}}, + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, + 0x00}}, + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, + 0x00}}, + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, + 0x00}}, + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, /* 36: 1600x1200x85Hz */ + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, + 0x00}}, + {{0x3f,0xef,0xef,0x83,0xfd,0x1a,0xda,0x1f, /* 37: 1920x1440x60Hz */ + 0xa0,0x84,0x9f,0x9f,0xdb,0x1f,0x01,0x01, + 0x00}}, + {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba, + 0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05, + 0x00}}, +#if 0 + {{0xdc,0x9f,0x9f,0x00,0xab,0x19,0xe6,0xef, /* 0x27: 1280x960-70 - invalid! */ + 0xc0,0xc3,0xbf,0xbf,0xe7,0x10,0x00,0x07, + 0x01}}, +#endif + {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff, /* 0x27: 1280x960-60 - correct */ + 0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07, + 0x01}}, + {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba, /* 0x28 */ + 0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06, + 0x01}}, + {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba, + 0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06, + 0x01}}, + {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba, + 0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06, + 0x01}}, + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1, + 0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02, + 0x01}}, + {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1, + 0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02, + 0x01}}, + {{0xa7,0x7f,0x7f,0x88,0x89,0x15,0x26,0xf1, + 0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02, + 0x01}}, + {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4, + 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07, + 0x01}}, + {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4, + 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07, + 0x01}}, + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4, + 0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07, + 0x01}}, + {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e, + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05, + 0x00}}, + {{0x7b,0x59,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 0x32 */ + 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05, + 0x01}}, + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1, /* 0x33 - 1024x600 */ + 0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02, + 0x01}}, + {{0xa3,0x8f,0x8f,0x97,0x96,0x97,0x24,0xf5, /* 0x34 - 1152x768 - corrected */ + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, + 0x01}}, + {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba, /* 0x35 */ + 0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06, + 0x01}}, /* 0x35 */ + {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba, + 0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06, + 0x01}}, /* 0x36 */ + {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba, + 0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06, + 0x01}}, /* 0x37 */ + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1, + 0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02, + 0x01}}, /* 0x38 */ + {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1, + 0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02, + 0x01}}, /* 0x39 */ + {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1, /* 95 was 15 - illegal HBE! */ + 0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02, + 0x01}}, /* 0x3a */ + {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4, + 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07, + 0x01}}, /* 0x3b */ + {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4, + 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07, + 0x01}}, /* 0x3c */ + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4, + 0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07, + 0x01}}, /* 0x3d */ + {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* 1152x864-75 */ + 0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07, + 0x01}}, /* 0x3e */ + {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* 848x480-38i */ + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, + 0x00}}, /* 0x3f */ + {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* 848x480-60 */ + 0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06, + 0x00}}, /* 0x40 */ + {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* 856x480-38i */ + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, + 0x00}}, /* 0x41 */ + {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* 856x480-60 */ + 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02, + 0x00}}, /* 0x42 */ + {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* 1360x768-60 */ + 0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03, + 0x01}}, /* 0x43 */ + {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* 1152x864-84 */ + 0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03, + 0x01}}, /* 0x44 */ + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* 1280x960-85 */ + 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07, + 0x01}}, /* 0x45 */ + {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5, /* 1280x768-60 */ + 0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07, + 0x01}}, /* 0x46 */ + {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */ + 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05, + 0x01}}, /* 0x47 */ + {{0xce,0xa9,0xa9,0x92,0xb1,0x07,0x28,0x52, /* 1360x1024 (Barco iQ Pro R300) */ + 0x02,0x8e,0xff,0x00,0x29,0x0d,0x00,0x03, + 0x00}}, /* 0x48 */ + {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff, /* 1152x864-60 */ + 0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07, + 0x41}} /* 0x49 */ +}; + +static const SiS_MCLKDataStruct SiS300_MCLKData_630[] = +{ + { 0x5a,0x64,0x80, 66}, + { 0xb3,0x45,0x80, 83}, + { 0x37,0x61,0x80,100}, + { 0x37,0x22,0x80,133}, + { 0x37,0x61,0x80,100}, + { 0x37,0x61,0x80,100}, + { 0x37,0x61,0x80,100}, + { 0x37,0x61,0x80,100} +}; + +static const SiS_MCLKDataStruct SiS300_MCLKData_300[] = +{ + { 0x68,0x43,0x80,125}, + { 0x68,0x43,0x80,125}, + { 0x68,0x43,0x80,125}, + { 0x37,0x61,0x80,100}, + { 0x37,0x61,0x80,100}, + { 0x37,0x61,0x80,100}, + { 0x37,0x61,0x80,100}, + { 0x37,0x61,0x80,100} +}; + +static SiS_VCLKDataStruct SiS300_VCLKData[] = +{ + { 0x1b,0xe1, 25}, /* 0x00 */ + { 0x4e,0xe4, 28}, /* 0x01 */ + { 0x57,0xe4, 32}, /* 0x02 */ + { 0xc3,0xc8, 36}, /* 0x03 */ + { 0x42,0xc3, 40}, /* 0x04 */ + { 0x5d,0xc4, 45}, /* 0x05 */ + { 0x52,0x65, 50}, /* 0x06 */ + { 0x53,0x65, 50}, /* 0x07 */ + { 0x6d,0x66, 56}, /* 0x08 */ + { 0x5a,0x64, 65}, /* 0x09 */ + { 0x46,0x44, 68}, /* 0x0a */ + { 0x3e,0x43, 75}, /* 0x0b */ + { 0x6d,0x46, 76}, /* 0x0c */ /* 800x600 | LVDS_2(CH), MITAC(CH); - 730, A901(301B): 0xb1,0x46, 76 */ + { 0x41,0x43, 79}, /* 0x0d */ + { 0x31,0x42, 79}, /* 0x0e */ + { 0x46,0x25, 85}, /* 0x0f */ + { 0x78,0x29, 87}, /* 0x10 */ + { 0x62,0x44, 95}, /* 0x11 */ + { 0x2b,0x22,105}, /* 0x12 */ + { 0x49,0x24,106}, /* 0x13 */ + { 0xc3,0x28,108}, /* 0x14 */ + { 0x3c,0x23,109}, /* 0x15 */ + { 0xf7,0x2c,132}, /* 0x16 */ + { 0xd4,0x28,136}, /* 0x17 */ + { 0x41,0x05,158}, /* 0x18 */ + { 0x43,0x05,162}, /* 0x19 */ + { 0xe1,0x0f,175}, /* 0x1a */ + { 0xfc,0x12,189}, /* 0x1b */ + { 0xde,0x26,194}, /* 0x1c */ + { 0x54,0x05,203}, /* 0x1d */ + { 0x3f,0x03,230}, /* 0x1e */ + { 0x30,0x02,234}, /* 0x1f */ + { 0x24,0x01,266}, /* 0x20 */ + { 0x52,0x2a, 54}, /* 0x21 */ /* 301 TV */ + { 0x52,0x6a, 27}, /* 0x22 */ /* 301 TV */ + { 0x62,0x24, 70}, /* 0x23 */ /* 301 TV */ + { 0x62,0x64, 70}, /* 0x24 */ /* 301 TV */ + { 0xa8,0x4c, 30}, /* 0x25 */ /* 301 TV */ + { 0x20,0x26, 33}, /* 0x26 */ /* 301 TV */ + { 0x31,0xc2, 39}, /* 0x27 */ + { 0xbf,0xc8, 35}, /* 0x28 */ /* 856x480 */ + { 0x60,0x36, 30}, /* 0x29 */ /* CH/UNTSC TEXT | LVDS_2(CH) - 730, A901(301B), Mitac(CH): 0xe0, 0xb6, 30 */ + { 0x40,0x4a, 28}, /* 0x2a */ /* CH-TV */ + { 0x9f,0x46, 44}, /* 0x2b */ /* CH-TV */ + { 0x97,0x2c, 26}, /* 0x2c */ /* CH-TV */ + { 0x44,0xe4, 25}, /* 0x2d */ /* CH-TV */ + { 0x7e,0x32, 47}, /* 0x2e */ /* CH-TV */ + { 0x8a,0x24, 31}, /* 0x2f */ /* CH/PAL TEXT | LVDS_2(CH), Mitac(CH) - 730, A901(301B): 0x57, 0xe4, 31 */ + { 0x97,0x2c, 26}, /* 0x30 */ /* CH-TV */ + { 0xce,0x3c, 39}, /* 0x31 */ /* CH-TV */ + { 0x52,0x4a, 36}, /* 0x32 */ /* CH/PAL 800x600 5/6 */ + { 0x34,0x61, 95}, /* 0x33 */ + { 0x78,0x27,108}, /* 0x34 */ /* Replacement for index 0x14 for 630 (?) */ + { 0x70,0x28, 90}, /* 0x35 */ /* 1152x864@60 */ + { 0x45,0x6b, 21}, /* 0x36 */ /* Chrontel SuperOverscan */ + { 0x52,0xe2, 49}, /* 0x37 */ /* 16:9 modes */ + { 0x2b,0x61, 78}, /* 0x38 */ /* 16:9 modes */ + { 0x70,0x44,108}, /* 0x39 */ /* 16:9 modes */ + { 0x54,0x42,135}, /* 0x3a */ /* 16:9 modes */ + { 0x41,0x22,157}, /* 0x3b */ /* 16:9 modes */ + { 0x52,0x07,149}, /* 0x3c */ /* 1280x960-85 */ + { 0x62,0xc6, 34}, /* 0x3d */ /* 848x480-60 */ + { 0x30,0x23, 88}, /* 0x3e */ /* 1360x768-60 */ + { 0x70,0x29, 81}, /* 0x3f */ /* 1280x768-60 */ + { 0x72,0x2a, 76}, /* 0x40 */ /* test for SiS730 --- LIMIT for table (&0x3f) */ + { 0x15,0x21, 79}, /* 0x41 */ /* test for SiS730 */ + { 0xa1,0x42,108}, /* 0x42 */ /* 1280x960 LCD */ + { 0x37,0x61,100}, /* 0x43 */ /* 1280x960 LCD */ + { 0xe3,0x9a,106}, /* 0x44 */ /* 1360x1024 - special for Barco iQ R300 */ + { 0xe2,0x46,135}, /* 0x45 */ /* 1280x1024-75, better clock for VGA2 */ + { 0x70,0x29, 81}, /* 0x46 */ /* unused */ + { 0, 0, 0}, /* 0x47 custom (will be filled out) */ + { 0xce,0x25,189} /* 0x48 */ /* Replacement for index 0x1b for 730 (and 540?) */ +}; + +#ifdef LINUX_KERNEL +static UCHAR SiS300_SR07 = 0x10; +#endif + +static const DRAM4Type SiS300_SR15[8] = +{ + {0x01,0x09,0xa3,0x00}, + {0x43,0x43,0x43,0x00}, + {0x1e,0x1e,0x1e,0x00}, + {0x2a,0x2a,0x2a,0x00}, + {0x06,0x06,0x06,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00} +}; + +#ifdef LINUX_KERNEL +static UCHAR SiS300_SR1F = 0x00; +static UCHAR SiS300_SR21 = 0x16; +static UCHAR SiS300_SR22 = 0xb2; +static UCHAR SiS300_SR23 = 0xf6; +static UCHAR SiS300_SR24 = 0x0d; +static UCHAR SiS300_SR25[] = {0x0,0x0}; +static UCHAR SiS300_SR31 = 0x00; +static UCHAR SiS300_SR32 = 0x11; +static UCHAR SiS300_SR33 = 0x00; +static UCHAR SiS300_CRT2Data_1_2 = 0x40; +static UCHAR SiS300_CRT2Data_4_D = 0x00; +static UCHAR SiS300_CRT2Data_4_E = 0x00; +static UCHAR SiS300_CRT2Data_4_10 = 0x80; + +static const USHORT SiS300_RGBSenseData = 0xd1; +static const USHORT SiS300_VideoSenseData = 0xb3; +static const USHORT SiS300_YCSenseData = 0xb9; +static const USHORT SiS300_RGBSenseData2 = 0x0190; +static const USHORT SiS300_VideoSenseData2 = 0x0174; +static const USHORT SiS300_YCSenseData2 = 0x016b; + +static const DRAM4Type SiS300_CR40[5]; + +static UCHAR SiS300_CR49[2]; +#endif + +static const SiS_PanelDelayTblStruct SiS300_PanelDelayTbl[] = +{ + {{0x05,0xaa}}, + {{0x05,0x14}}, + {{0x05,0x36}}, + {{0x05,0x14}}, + {{0x05,0x14}}, + {{0x05,0x14}}, + {{0x05,0x90}}, + {{0x05,0x90}}, + {{0x05,0x14}}, + {{0x05,0x14}}, + {{0x05,0x14}}, + {{0x05,0x14}}, + {{0x20,0x80}}, + {{0x05,0x14}}, + {{0x05,0x40}}, + {{0x05,0x60}} +}; + +#if 0 +static const SiS_PanelDelayTblStruct SiS300_PanelDelayTblLVDS[] = +{ + {{0x05,0xaa}}, + {{0x05,0x14}}, + {{0x05,0x36}}, + {{0x05,0x14}}, + {{0x05,0x14}}, + {{0x05,0x14}}, + {{0x05,0x90}}, + {{0x05,0x90}}, + {{0x05,0x14}}, + {{0x05,0x14}}, + {{0x05,0x14}}, + {{0x05,0x14}}, /* 2.07a (JVC): 14,96 */ + {{0x05,0x28}}, /* 2.04.5c: 20, 80 - Clevo (2.04.2c): 05, 28 */ + {{0x05,0x14}}, + {{0x05,0x14}}, /* Some BIOSes: 05, 40 */ + {{0x05,0x60}} +}; +#endif + +/**************************************************************/ +/* SIS VIDEO BRIDGE ----------------------------------------- */ +/**************************************************************/ + +static const SiS_LCDDataStruct SiS300_St2LCD1024x768Data[] = +{ + { 62, 25, 800, 546,1344, 806}, + { 32, 15, 930, 546,1344, 806}, + { 32, 15, 930, 546,1344, 806}, + { 104, 45, 945, 496,1344, 806}, + { 62, 25, 800, 546,1344, 806}, + { 31, 18,1008, 624,1344, 806}, + { 1, 1,1344, 806,1344, 806} +}; + +static const SiS_LCDDataStruct SiS300_ExtLCD1024x768Data[] = +{ + { 12, 5, 896, 512,1344, 806}, + { 12, 5, 896, 510,1344, 806}, + { 32, 15,1008, 505,1344, 806}, + { 32, 15,1008, 514,1344, 806}, + { 12, 5, 896, 500,1344, 806}, + { 42, 25,1024, 625,1344, 806}, + { 1, 1,1344, 806,1344, 806}, + { 12, 5, 896, 500,1344, 806}, + { 42, 25,1024, 625,1344, 806}, + { 1, 1,1344, 806,1344, 806}, + { 12, 5, 896, 500,1344, 806}, + { 42, 25,1024, 625,1344, 806}, + { 1, 1,1344, 806,1344, 806} +}; + +static const SiS_LCDDataStruct SiS300_St2LCD1280x1024Data[] = +{ + { 22, 5, 800, 510,1650,1088}, + { 22, 5, 800, 510,1650,1088}, + { 176, 45, 900, 510,1650,1088}, + { 176, 45, 900, 510,1650,1088}, + { 22, 5, 800, 510,1650,1088}, + { 13, 5,1024, 675,1560,1152}, + { 16, 9,1266, 804,1688,1072}, + { 1, 1,1688,1066,1688,1066} +}; + +static const SiS_LCDDataStruct SiS300_ExtLCD1280x1024Data[] = +{ + { 211, 60,1024, 501,1688,1066}, + { 211, 60,1024, 508,1688,1066}, + { 211, 60,1024, 501,1688,1066}, + { 211, 60,1024, 508,1688,1066}, + { 211, 60,1024, 500,1688,1066}, + { 211, 75,1024, 625,1688,1066}, + { 211, 120,1280, 798,1688,1066}, + { 1, 1,1688,1066,1688,1066} +}; + +static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_1[] = +{ /* VESA Timing */ + {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}}, + {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}}, + {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}, + {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}, + {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}} +}; + +static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_2[] = +{ /* Non-VESA */ + {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x28,0x13,0xe7,0x0b,0xe8,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x38,0x18,0x16,0x00,0x00,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}} +}; + +static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_3[] = +{ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_1[] = +{ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_2[] = +{ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_3[] = +{ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +/**************************************************************/ +/* LVDS/Chrontel -------------------------------------------- */ +/**************************************************************/ + +static const SiS_LVDSDataStruct SiS300_CHTVUPALData[] = +{ + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 750, 840, 750}, + { 936, 836, 936, 836} +}; + +static const SiS_LVDSDataStruct SiS300_CHTVOPALData[] = +{ + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 625, 840, 625}, + { 960, 750, 960, 750} +}; + +static const SiS_LVDSDataStruct SiS300_CHTVSOPALData[] = +{ + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 500, 840, 500}, + { 944, 625, 944, 625} +}; + + +static const SiS_LVDSDesStruct SiS300_PanelType00_1[] = +{ + { 1059, 626 }, /* 2.08 */ + { 1059, 624 }, + { 1059, 626 }, + { 1059, 624 }, + { 1059, 624 }, + { 0, 627 }, + { 0, 627 }, + { 0, 0 }, + { 0, 0 } +#if 0 + {0, 626}, + {0, 624}, + {0, 626}, + {0, 624}, + {0, 624}, + {0, 627}, + {0, 627}, + {0, 0}, + {0, 0} +#endif +}; + +static const SiS_LVDSDesStruct SiS300_PanelType01_1[] = +{ + { 0, 0 }, /* 2.08 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 } +#if 0 + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +#endif +}; + +static const SiS_LVDSDesStruct SiS300_PanelType02_1[] = +{ + { 1059, 626 }, /* 2.08 */ + { 1059, 624 }, + { 1059, 626 }, + { 1059, 624 }, + { 1059, 624 }, + { 0, 627 }, + { 0, 627 }, + { 0, 0 }, + { 0, 0 } +#if 0 + {0, 626}, + {0, 624}, + {0, 626}, + {0, 624}, + {0, 624}, + {0, 627}, + {0, 627}, + {0, 0}, + {0, 0} +#endif +}; + +static const SiS_LVDSDesStruct SiS300_PanelType03_1[] = +{ + { 8, 436}, + { 8, 440}, + { 8, 436}, + { 8, 440}, + { 8, 512}, + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType04_1[] = /* 1280x1024 */ +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType05_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType06_1[] = /* Clevo Trumpion 1024x768 */ +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType07_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType08_1[] = +{ + {1059, 626}, + {1059, 624}, + {1059, 626}, + {1059, 624}, + {1059, 624}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType09_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType0a_1[] = +{ + {1059, 626}, + {1059, 624}, + {1059, 626}, + {1059, 624}, + {1059, 624}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType0b_1[] = +{ + {1343, 0}, + {1343, 0}, + {1343, 0}, + {1343, 0}, + {1343, 0}, + {1343, 0}, + { 0, 799}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType0c_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType0d_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType0e_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, /* 640x480 */ + {1343, 0}, /* 800x600 */ + { 0, 805}, /* 1024x768 */ + { 0, 794}, /* 1280x1024 */ + { 0, 0} /* 1280x960 - not applicable */ +}; + +static const SiS_LVDSDesStruct SiS300_PanelType0f_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType00_2[] = +{ + {976, 527}, + {976, 502}, + {976, 527}, + {976, 502}, + {976, 567}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType01_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType02_2[] = +{ + {976, 527}, + {976, 502}, + {976, 527}, + {976, 502}, + {976, 567}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType03_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + {1152, 622}, + {1152, 597} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType04_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType05_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType06_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType07_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType08_2[] = +{ + {976, 527}, + {976, 502}, + {976, 527}, + {976, 502}, + {976, 567}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType09_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType0a_2[] = +{ + {976, 527}, + {976, 502}, + {976, 527}, + {976, 502}, + {976, 567}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType0b_2[] = +{ + { 1152, 700}, + { 1152, 675}, + { 1152, 700}, + { 1152, 675}, + { 1152, 740}, + { 1232, 799}, + { 0, 799}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType0c_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType0d_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType0e_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelType0f_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelTypeNS_1[]= +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 805}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS300_PanelTypeNS_2[] = +{ + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0} +}; + +/* Custom data for Barco iQ R200/300/400 (BIOS 2.00.07) */ +static const SiS_LVDSDesStruct SiS300_PanelType04_1a[] = /* 1280x1024 (1366x1024) */ +{ + {1330, 798}, /* 320x200 */ + {1330, 794}, + {1330, 798}, + {1330, 794}, + {1330, 0}, /* 640x480 / 320x240 */ + {1343, 0}, /* 800x600 / 400x300 */ + { 0, 805}, /* 1024x768 / 512x384 */ + {1688,1066}, /* 1280x1024 */ + { 0, 0} /* 1360x1024 */ +}; + +static const SiS_LVDSDesStruct SiS300_PanelType04_2a[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + {1688,1066}, + { 0, 0} +}; + +/* Custom data for Barco iQ G200/300/400 (BIOS 2.00.07) */ +static const SiS_LVDSDesStruct SiS300_PanelType04_1b[] = /* 1024x768 */ +{ + {1330, 798}, /* 320x200 */ + {1330, 794}, + {1330, 798}, + {1330, 794}, + {1330, 0}, /* 640x480 / 320x240 */ + {1343, 0}, /* 800x600 / 400x300 */ + { 0, 805} /* 1024x768 / 512x384 */ +}; + +static const SiS_LVDSDesStruct SiS300_PanelType04_2b[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805} +}; + +/* CRT1 CRTC for slave modes */ + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1[] = +{ + {{0x65,0x4f,0x89,0x56,0x83,0xaf,0x1f, + 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, + 0x00 }}, + {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, + 0x00 }}, + {{0x65,0x4f,0x89,0x56,0x83,0xaf,0x1f, + 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, + 0x00 }}, + {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, + 0x00 }}, + {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e, + 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05, + 0x00 }}, + {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1_H[] = +{ + {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f, + 0x90,0x85,0x8f,0xab,0x30,0x00,0x04, + 0x00 }}, + {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04, + 0x00 }}, + {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f, + 0x90,0x85,0x8f,0xab,0x30,0x00,0x04, + 0x00 }}, + {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04, + 0x00 }}, + {{0x30,0x27,0x94,0x2c,0x92,0x04,0x3e, + 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x04, + 0x00 }}, + {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x05, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1[] = +{ + {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x88,0x54,0x9f,0x04,0x3e, + 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01, + 0x00}}, + {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0, + 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26, + 0x01}}, + {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x02, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1_H[] = +{ + {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, + 0x00 }}, + {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, + 0x60,0x87,0x5D,0x83,0x10,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, + 0x60,0x87,0x5D,0x83,0x10,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e, + 0xE2,0x89,0xdf,0x05,0x00,0x00,0x44, + 0x00}}, + {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0, + 0x5A,0x8F,0x57,0x7D,0x20,0x00,0x55, + 0x01}}, + {{0x4f,0x3F,0x93,0x45,0x0D,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x01, + 0x01 }} + +#if 0 + {{0x37,0x27,0x9B,0x2b,0x94,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, + 0x00 }}, + {{0x37,0x27,0x9B,0x2b,0x94,0x97,0x1f, + 0x60,0x87,0x5D,0x83,0x01,0x00,0x44, + 0x00}}, + {{0x37,0x27,0x9B,0x2b,0x94,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, + 0x00}}, + {{0x37,0x27,0x9B,0x2b,0x94,0x97,0x1f, + 0x60,0x87,0x5D,0x83,0x01,0x00,0x44, + 0x00}}, + {{0x37,0x27,0x9B,0x2b,0x94,0x04,0x3e, + 0xE2,0x89,0xDf,0x05,0x00,0x00,0x44, + 0x00}}, + {{0x41,0x31,0x85,0x35,0x1d,0x7c,0xf0, + 0x5A,0x8F,0x57,0x7D,0x20,0x00,0x55, + 0x01}}, + {{0x4f,0x3F,0x93,0x45,0x0D,0x24,0xf5, + 0x02,0x88,0xFf,0x25,0x10,0x00,0x01, + 0x01 }} +#endif +}; + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1[] = +{ + {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x54,0x9f,0x04,0x3e, + 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01, + 0x00 }}, + {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0, + 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26, + 0x01 }}, + {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x02, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1_H[] = +{ + {{0x2f,0x27,0x93,0x2b,0x90,0xb4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x04, + 0x00 }}, + {{0x2f,0x27,0x93,0x2b,0x90,0x82,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x04, + 0x00 }}, + {{0x2f,0x27,0x93,0x2b,0x90,0xb4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x04, + 0x00 }}, + {{0x2f,0x27,0x93,0x2b,0x90,0x82,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x04, + 0x00 }}, + {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e, + 0xe2,0x89,0xdf,0x05,0x00,0x00,0x04, + 0x00 }}, + {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0, + 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55, + 0x01 }}, + {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x01, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2[] = +{ + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, + 0xf4,0x88,0x8f,0x73,0x20,0x00,0x06, + 0x00 }}, + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, + 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x06, + 0x00 }}, + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, + 0xf4,0x88,0x8f,0x73,0x20,0x00,0x06, + 0x00 }}, + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, + 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x06, + 0x00 }}, + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0xba, + 0x1c,0x80,0xdf,0x73,0x00,0x00,0x06, + 0x00 }}, + {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2_H[] = +{ + {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e, + 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05, + 0x00 }}, + {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e, + 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05, + 0x00 }}, + {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e, + 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05, + 0x00 }}, + {{0x3d,0x27,0x81,0x3a,0x1a,0x72,0x3e, + 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05, + 0x00 }}, + {{0x3d,0x27,0x81,0x32,0x1a,0x72,0xba, + 0x1c,0x80,0xdf,0x73,0x00,0x00,0x05, + 0x00 }}, + {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x05, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2[] = +{ + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x72,0x88,0xdf,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1, + 0xae,0x84,0x57,0x25,0x30,0x00,0x02, + 0x01 }}, + {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x02, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2_H[] = +{ + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x72,0x88,0xdf,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1, + 0xae,0x84,0x57,0x25,0x30,0x00,0x01, + 0x01 }}, + {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x01, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2[] = +{ + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x72,0x88,0xdf,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1, + 0xae,0x84,0x57,0x25,0x30,0x00,0x02, + 0x01 }}, + {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x02, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2_H[] = +{ + {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x72,0x88,0xdf,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x31,0x93,0x3e,0x86,0x24,0xf1, + 0xae,0x84,0x57,0x25,0x30,0x00,0x01, + 0x01 }}, + {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x01, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1XXXxXXX_1[] = +{ + {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05, + 0x00}}, + {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, + 0x01}}, + {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x02, + 0x01}}, + {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a, + 0x00,0x84,0xff,0x29,0x09,0x00,0x07, + 0x01}}, + {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x07, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_LVDSCRT1XXXxXXX_1_H[] = +{ + {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00, + 0x00}}, + {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00, + 0x00}}, + {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00, + 0x00}}, + {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00, + 0x00}}, + {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e, + 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00, + 0x00}}, + {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x01, + 0x01}}, + {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x01, + 0x01}} +}; + + +static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1UNTSC[] = +{ + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01, + 0x00 }}, + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01, + 0x00 }}, + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01, + 0x00 }}, + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01, + 0x00 }}, + {{0x5d,0x4f,0x81,0x53,0x9c,0x56,0xba, + 0x18,0x84,0xdf,0x57,0x00,0x00,0x01, + 0x00 }}, + {{0x80,0x63,0x84,0x6c,0x17,0xec,0xf0, + 0x90,0x8c,0x57,0xed,0x20,0x00,0x06, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1ONTSC[] = +{ + {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e, + 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01, + 0x00 }}, + {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e, + 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01, + 0x00 }}, + {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e, + 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01, + 0x00 }}, + {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e, + 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01, + 0x00 }}, + {{0x5d,0x4f,0x81,0x56,0x9c,0x0b,0x3e, + 0xe8,0x84,0xdf,0x0c,0x00,0x00,0x01, + 0x00 }}, + {{0x7d,0x63,0x81,0x6a,0x16,0xba,0xf0, + 0x7f,0x86,0x57,0xbb,0x00,0x00,0x06, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1UPAL[] = +{ + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x64,0x4f,0x88,0x55,0x80,0xec,0xba, + 0x50,0x84,0xdf,0xed,0x00,0x00,0x05, + 0x00 }}, + {{0x70,0x63,0x94,0x68,0x8d,0x42,0xf1, + 0xc8,0x8c,0x57,0xe9,0x20,0x00,0x05, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1OPAL[] = +{ + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x64,0x4f,0x88,0x55,0x80,0x6f,0xba, + 0x20,0x83,0xdf,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x73,0x63,0x97,0x69,0x8e,0xec,0xf0, + 0x90,0x8c,0x57,0xed,0x20,0x00,0x05, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS300_CHTVCRT1SOPAL[] = +{ + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x64,0x4f,0x88,0x55,0x80,0x6f,0xba, /* TODO */ + 0x20,0x83,0xdf,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x73,0x63,0x97,0x69,0x8e,0xec,0xf0, /* TODO */ + 0x90,0x8c,0x57,0xed,0x20,0x00,0x05, + 0x01 }} +}; + +static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] = +{ + {{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x6a,0x6a,0x00,0x2d,0xfa,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 17: 640x480 NTSC 7/8 */ + {{0x8d,0xc4,0x00,0x3b,0xfb,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 24: 800x600 NTSC 7/10 */ +}; + +static const SiS_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] = +{ + {{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x69,0x6a,0x00,0x1e,0xfd,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 16: 640x480 NTSC 1/1 */ + {{0x8c,0xb4,0x00,0x32,0xf9,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 23: 800x600 NTSC 3/4 */ +}; + +static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] = +{ + {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x63,0x94,0x01,0x50,0x30,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 15: 640x480 PAL 5/6 */ + {{0x84,0x64,0x01,0x4e,0x2f,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 21: 800x600 PAL 3/4 */ + +}; + +static const SiS_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] = +{ + {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */ + {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x61,0x94,0x01,0x36,0x30,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 14: 640x480 PAL 1/1 */ + {{0x83,0x76,0x01,0x40,0x31,0,0,0,0,0,0,0,0,0,0,0}} /* Mode 20: 800x600 PAL 5/6 */ + +}; + +static const SiS_CHTVRegDataStruct SiS300_CHTVReg_SOPAL[] = +{ + {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */ + {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}}, + {{0x60,0x30,0x00,0x10,0x00,0,0,0,0,0,0,0,0,0,0,0}}, /* TW: Mode 13: 640x480 PAL 5/4 */ + {{0x81,0x50,0x00,0x1b,0x00,0,0,0,0,0,0,0,0,0,0,0}} /* TW: Mode 19: 800x600 PAL 1/1 */ +}; + +static const UCHAR SiS300_CHTVVCLKUNTSC[] = {0x29,0x29,0x29,0x29,0x2a,0x2e}; + +static const UCHAR SiS300_CHTVVCLKONTSC[] = {0x2c,0x2c,0x2c,0x2c,0x2d,0x2b}; + +static const UCHAR SiS300_CHTVVCLKSONTSC[] = {0x2c,0x2c,0x2c,0x2c,0x2d,0x2b}; + +static const UCHAR SiS300_CHTVVCLKUPAL[] = {0x2f,0x2f,0x2f,0x2f,0x2f,0x31}; + +static const UCHAR SiS300_CHTVVCLKOPAL[] = {0x2f,0x2f,0x2f,0x2f,0x30,0x32}; + +static const UCHAR SiS300_CHTVVCLKSOPAL[] = {0x2f,0x2f,0x2f,0x2f,0x36,0x29}; + + diff --git a/drivers/video/sis/310vtbl.h b/drivers/video/sis/310vtbl.h new file mode 100644 index 000000000000..2c71d048f7c4 --- /dev/null +++ b/drivers/video/sis/310vtbl.h @@ -0,0 +1,2754 @@ +/* $XFree86$ */ +/* $XdotOrg$ */ +/* + * Register settings for SiS 315/330 series + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the named License, + * * or any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program; if not, write to the Free Software + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Otherwise, the following license terms apply: + * + * * Redistribution and use in source and binary forms, with or without + * * modification, are permitted provided that the following conditions + * * are met: + * * 1) Redistributions of source code must retain the above copyright + * * notice, this list of conditions and the following disclaimer. + * * 2) Redistributions in binary form must reproduce the above copyright + * * notice, this list of conditions and the following disclaimer in the + * * documentation and/or other materials provided with the distribution. + * * 3) The name of the author may not be used to endorse or promote products + * * derived from this software without specific prior written permission. + * * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + */ + +static const SiS_StStruct SiS310_SModeIDTable[]= +{ + {0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00, 0x40}, + {0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00, 0x40}, + {0x01,0x1010,0x17,0x02,0x02,0x00,0x01,0x01, 0x40}, + {0x03,0x8208,0x03,0x00,0x00,0x00,0x01,0x02, 0x40}, + {0x03,0x0210,0x16,0x01,0x01,0x00,0x01,0x02, 0x40}, + {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03, 0x40}, + {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x04, 0x40}, + {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x05, 0x40}, + {0x07,0x0000,0x07,0x03,0x03,0x00,0x01,0x03, 0x40}, + {0x07,0x0000,0x19,0x02,0x02,0x00,0x01,0x03, 0x40}, + {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x04, 0x40}, + {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x05, 0x40}, + {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x05, 0x40}, + {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x05, 0x40}, + {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x05, 0x40}, + {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x05, 0x40}, + {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x04, 0x40}, + {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x05, 0x40}, + {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x05, 0x40}, + {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00, 0x40} +}; + +static const SiS_ExtStruct SiS310_EModeIDTable[]= +{ + {0x6a,0x2212,0x0102,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x? */ + {0x2e,0x0a1b,0x0101,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */ + {0x2f,0x0a1b,0x0100,SIS_RI_640x400, 0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */ + {0x30,0x2a1b,0x0103,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */ + {0x31,0x4a1b,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */ + {0x32,0x4a1b,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */ + {0x33,0x4a1d,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */ + {0x34,0x6a1d,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */ + {0x35,0x4a1f,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */ + {0x36,0x6a1f,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */ + {0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x? */ + {0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */ + {0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x8 */ + {0x3c,0x0e3b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x8 */ + {0x3d,0x0e7d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x16 */ + {0x40,0x9a1c,0x010d,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x15 */ + {0x41,0x9a1d,0x010e,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x16 */ + {0x43,0x0a1c,0x0110,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, + {0x44,0x0a1d,0x0111,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */ + {0x46,0x2a1c,0x0113,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, + {0x47,0x2a1d,0x0114,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */ + {0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x07,0x13, 4}, + {0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */ + {0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, + {0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x16 */ + {0x50,0x9a1b,0x0132,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x8 */ + {0x51,0xba1b,0x0133,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x8 */ + {0x52,0xba1b,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x8 */ + {0x56,0x9a1d,0x0135,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x16 */ + {0x57,0xba1d,0x0136,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x16 */ + {0x58,0xba1d,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x16 */ + {0x59,0x9a1b,0x0138,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x8 */ + {0x5a,0x021b,0x0138,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x8 fstn */ + {0x5b,0x0a1d,0x0135,SIS_RI_320x240, 0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x16 fstn */ + {0x5c,0xba1f,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x32 */ + {0x5d,0x0a1d,0x0139,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, + {0x5e,0x0a1f,0x0000,SIS_RI_640x400, 0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */ + {0x62,0x0a3f,0x013a,SIS_RI_640x480, 0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */ + {0x63,0x2a3f,0x013b,SIS_RI_800x600, 0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */ + {0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */ + {0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x32 */ + {0x66,0x0eff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x32 */ + {0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x8 */ + {0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x16 */ + {0x6b,0x07ff,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x32 */ + {0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x8 */ + {0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x16 */ + {0x6e,0x07ff,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x32 */ + {0x70,0x6a1b,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x8 */ + {0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x8 */ + {0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x16 */ + {0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x16 */ + {0x76,0x6a1f,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x32 */ + {0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x32 */ + {0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x32 */ + {0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x8 */ + {0x7a,0x6a1d,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x16 */ + {0x7c,0x0e3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x8 */ + {0x7d,0x0e7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x16 */ + {0x7e,0x0eff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x32 */ + {0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x8 */ + {0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x16 */ + {0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x32 */ + {0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x8 */ + {0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x16 */ + {0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x32*/ + {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1}, /* 1152x864 */ + {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1}, + {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1}, + {0x39,0x6a1b,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x46,-1}, /* 848x480 */ + {0x3b,0x6a3d,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x46,-1}, + {0x3e,0x6a7f,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x00,0x46,-1}, + {0x3f,0x6a1b,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x48,-1}, /* 856x480 */ + {0x42,0x6a3d,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x48,-1}, + {0x45,0x6a7f,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x00,0x48,-1}, + {0x48,0x6a3b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4a,-1}, /* 1360x768 */ + {0x4b,0x6a7d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4a,-1}, + {0x4e,0x6aff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4a,-1}, + {0x4f,0x9a1f,0x0000,SIS_RI_320x200, 0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x32 */ + {0x53,0x9a1f,0x0000,SIS_RI_320x240, 0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x32 */ + {0x54,0xba1f,0x0000,SIS_RI_400x300, 0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x32 */ + {0x5f,0x6a1b,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4b,-1}, /* 768x576 */ + {0x60,0x6a1d,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4b,-1}, + {0x61,0x6a3f,0x0000,SIS_RI_768x576, 0x00,0x00,0x06,0x06,0x4b,-1}, + {0x14,0x0e3b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4c, 7}, /* 1280x800 */ + {0x15,0x0e7d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4c, 7}, + {0x16,0x0eff,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4c, 7}, + {0x17,0x0e3b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4d, 9}, /* 1680x1050 */ + {0x18,0x0e7d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4d, 9}, + {0x19,0x0eff,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4d, 9}, + {0x2c,0x267b,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4e,-1}, /* 1920x1080(i) */ + {0x2d,0x26fd,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4e,-1}, + {0x73,0x27ff,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4e,-1}, + {0x1d,0x6a1b,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x4f,-1}, /* 960x540 */ + {0x1e,0x6a3d,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x4f,-1}, + {0x1f,0x6a7f,0x0000,SIS_RI_960x540, 0x00,0x00,0x00,0x00,0x4f,-1}, + {0x20,0x6a1b,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x50,-1}, /* 960x600 */ + {0x21,0x6a3d,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x50,-1}, + {0x22,0x6a7f,0x0000,SIS_RI_960x600, 0x00,0x00,0x00,0x00,0x50,-1}, + {0xff,0x0000,0x0000,0, 0x00,0x00,0x00,0x00,0x00,-1} +}; + +static const SiS_Ext2Struct SiS310_RefIndex[]= +{ + {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x0 */ + {0x0067,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x1 */ + {0x0067,0x0f,0x08,0x48,0x05,0x6a, 800, 600, 0x40}, /* 0x2 */ + {0x0067,0x10,0x07,0x8b,0x05,0x6a, 800, 600, 0x40}, /* 0x3 */ + {0x0047,0x11,0x0a,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x4 */ + {0x0047,0x12,0x0d,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x5 */ + {0x0047,0x13,0x13,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x6 */ + {0x0107,0x14,0x1c,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x7 */ + {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x8 */ + {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x9 */ + {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40}, /* 0xa */ + {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40}, /* 0xb */ + {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xc */ + {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xd */ + {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xe */ + {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xf */ + {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30}, /* 0x10 */ + {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30}, /* 0x11 */ + {0x006f,0x3d,0x03,0x06,0x14,0x32, 720, 576, 0x30}, /* 0x12 */ + {0x0087,0x15,0x06,0x00,0x06,0x37,1024, 768, 0x30}, /* 0x13 */ + {0xc877,0x16,0x0b,0x06,0x06,0x37,1024, 768, 0x20}, /* 0x14 */ + {0xc067,0x17,0x0f,0x49,0x06,0x37,1024, 768, 0x20}, /* 0x15 */ + {0x0067,0x18,0x11,0x00,0x06,0x37,1024, 768, 0x20}, /* 0x16 */ + {0x0047,0x19,0x16,0x8c,0x06,0x37,1024, 768, 0x20}, /* 0x17 */ + {0x0107,0x1a,0x1b,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x18 */ + {0x0107,0x1b,0x1f,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x19 */ + {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30}, /* 0x1a */ + {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00}, /* 0x1b */ + {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1c */ + {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1d */ + {0x0227,0x20,0x21,0x09,0x09,0x3c,1600,1200, 0x00}, /* 0x1e */ + {0x0407,0x21,0x22,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x1f */ + {0x0407,0x22,0x23,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x20 */ + {0x0407,0x23,0x25,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x21 */ + {0x0007,0x24,0x26,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x22 */ + {0x0007,0x25,0x2c,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x23 */ + {0x0007,0x26,0x34,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x24 */ + {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0x30}, /* 0x25 */ + {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30}, /* 0x26 */ + {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30}, /* 0x27 */ + {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30}, /* 0x28 */ + {0x8007,0x27,0x27,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x29 */ + {0x4007,0x28,0x29,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2a */ + {0x4007,0x29,0x2e,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2b */ + {0x4007,0x2a,0x30,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2c */ + {0x4007,0x2b,0x35,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2d */ + {0x4005,0x2c,0x39,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2e */ + {0x4007,0x2d,0x2b,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x2f */ + {0x4007,0x2e,0x31,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x30 */ + {0x4007,0x2f,0x33,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x31 */ + {0x4007,0x30,0x37,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x32 */ + {0x4005,0x31,0x38,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x33 */ + {0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x34 */ + {0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x35 */ + {0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x36 */ + {0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x37 */ + {0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x38 */ + {0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x39 */ + {0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3a */ + {0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3b */ + {0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3c */ + {0x0127,0x3b,0x19,0x08,0x0a,0x7c,1280, 960, 0x30}, /* 0x3d */ + {0x0227,0x4c,0x59,0x08,0x0a,0x7c,1280, 960, 0x20}, /* 0x3e */ + {0xc07f,0x4e,0x00,0x06,0x04,0x5a, 320, 240, 0x30}, /* 0x3f */ /* FSTN 320x240 */ + {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30}, /* 0x40 */ /* 0x5b was 0x12 */ + {0x0127,0x43,0x4d,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x41 */ + {0x0207,0x4b,0x5a,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x42 1400x1050-75Hz */ + {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x43 1152x864-60Hz */ + {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x44 1152x864-75Hz */ + {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x45 1152x864-85Hz */ + {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30}, /* 0x46 848x480-38Hzi */ + {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30}, /* 0x47 848x480-60Hz */ + {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x48 856x480-38Hzi */ + {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x49 856x480-60Hz */ + {0x0067,0x49,0x58,0x0c,0x1b,0x48,1360, 768, 0x30}, /* 0x4a 1360x768-60Hz */ + {0x006f,0x4d,0x03,0x06,0x15,0x5f, 768, 576, 0x30}, /* 0x4b 768x576-56Hz */ + {0x0067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30}, /* 0x4c 1280x800-60Hz */ + {0x0067,0x50,0x5d,0x0c,0x0e,0x17,1680,1050, 0x30}, /* 0x4d 1680x1050-60Hz */ + {0x0087,0x51,0x69,0x00,0x00,0x2c,1920,1080, 0x30}, /* 0x4e 1920x1080 60Hzi */ + {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30}, /* 0x4f 960x540 60Hz */ + {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30}, /* 0x50 960x600 60Hz */ + {0xffff,0x00,0x00,0x00,0x00,0x00, 0, 0, 0} +}; + +#ifdef LINUX_XF86 +static const struct { + UCHAR Ext_ModeID; /* ModeID in new ROM */ + UCHAR Ext_MyModeID; /* corresponding ModeID in my tables (0 = identical) */ + USHORT Ext_VESAID; /* corresponding VESA ID in new ROM */ +} SiS_EModeIDTable661[] = { + { 0x6a, 0x00, 0x0102 }, + { 0x1d, 0x20, 0x0000 }, + { 0x1e, 0x21, 0x0000 }, + { 0x1f, 0x22, 0x0000 }, + { 0x20, 0x29, 0x0000 }, + { 0x21, 0x2a, 0x0000 }, + { 0x22, 0x2b, 0x0000 }, + { 0x23, 0x00, 0x011c }, + { 0x24, 0x00, 0x011d }, + { 0x25, 0x00, 0x011e }, + { 0x26, 0x00, 0x011f }, + { 0x27, 0x00, 0x0120 }, + { 0x28, 0x00, 0x0121 }, + { 0x2a, 0x14, 0x013d }, + { 0x2b, 0x15, 0x013e }, + { 0x2c, 0x16, 0x013f }, + { 0x2e, 0x00, 0x0101 }, + { 0x2f, 0x00, 0x0100 }, + { 0x30, 0x00, 0x0103 }, + { 0x37, 0x00, 0x0104 }, + { 0x38, 0x00, 0x0105 }, + { 0x3a, 0x00, 0x0107 }, + { 0x3c, 0x00, 0x0125 }, + { 0x3d, 0x00, 0x0126 }, + { 0x40, 0x00, 0x010d }, + { 0x41, 0x00, 0x010e }, + { 0x43, 0x00, 0x0110 }, + { 0x44, 0x00, 0x0111 }, + { 0x46, 0x00, 0x0113 }, + { 0x47, 0x00, 0x0114 }, + { 0x49, 0x00, 0x0116 }, + { 0x4a, 0x00, 0x0117 }, + { 0x4c, 0x00, 0x0119 }, + { 0x4d, 0x00, 0x011a }, + { 0x50, 0x00, 0x0127 }, + { 0x51, 0x00, 0x0128 }, + { 0x52, 0x00, 0x0129 }, + { 0x56, 0x00, 0x012a }, + { 0x57, 0x00, 0x012b }, + { 0x58, 0x00, 0x012c }, + { 0x59, 0x00, 0x012d }, + { 0x5a, 0x17, 0x012e }, + { 0x5b, 0x18, 0x012f }, + { 0x5c, 0x19, 0x0130 }, + { 0x5d, 0x00, 0x0131 }, + { 0x62, 0x00, 0x0112 }, + { 0x63, 0x00, 0x0115 }, + { 0x64, 0x00, 0x0118 }, + { 0x65, 0x00, 0x011b }, + { 0x66, 0x00, 0x0132 }, + { 0x75, 0x00, 0x013a }, + { 0x78, 0x00, 0x013b }, + { 0x79, 0x00, 0x013c }, + { 0x7b, 0x7c, 0x0136 }, + { 0x7c, 0x7d, 0x0137 }, + { 0x7d, 0x7e, 0x0138 }, + { 0xff, 0xff, 0xffff } +}; +#endif + +static const SiS_CRT1TableStruct SiS310_CRT1Table[]= +{ + {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, + 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00, + 0x00}}, /* 0x0 */ + {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, + 0x00}}, /* 0x1 */ + {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, + 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05, + 0x01}}, /* 0x2 */ + {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5, + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01, + 0x01}}, /* 0x3 */ + {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05, + 0x00}}, /* 0x4 */ +#if 0 + {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05, + 0x00}}, /* 0x5 */ +#endif + {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* 0x05 - corrected 640x480-60 */ + 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05, + 0x00}}, +#if 0 + {{0x63,0x4f,0x50,0x86,0x56,0x9b,0x06,0x3e, + 0xe8,0x8b,0xdf,0xe7,0xff,0x10,0x00,0x01, + 0x00}}, /* 0x6 */ +#endif + {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e, /* 0x06 - corrected 640x480-72 */ + 0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f, + 0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01, + 0x00}}, /* 0x7 */ + {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f, + 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05, + 0x00}}, /* 0x8 */ + {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f, + 0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05, /* Corrected VBE */ + 0x61}}, /* 0x9 */ + {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e, + 0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05, + 0x61}}, /* 0xa */ + {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e, + 0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05, /* Corrected VBE */ + 0x61}}, /* 0xb */ + {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f, + 0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01, /* Corrected VDE, VBE */ + 0x00}}, /* 0xc */ + {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0, + 0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05, + 0x01}}, /* 0xd */ + {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0, + 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06, + 0x01}}, /* 0xe */ + {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0, + 0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06, + 0x01}}, /* 0xf */ + {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0, + 0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06, + 0x01}}, /* 0x10 */ + {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0, + 0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06, + 0x01}}, /* 0x11 */ + {{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0, + 0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06, + 0x61}}, /* 0x12 */ + {{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0, + 0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06, + 0x61}}, /* 0x13 */ + {{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0, + 0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06, + 0x61}}, /* 0x14 */ + {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f, + 0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02, + 0x00}}, /* 0x15 */ + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, + 0x01}}, /* 0x16 */ + {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, + 0x01}}, /* 0x17 */ + {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5, + 0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02, + 0x01}}, /* 0x18 */ + {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5, + 0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02, + 0x01}}, /* 0x19 */ + {{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5, + 0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02, + 0x62}}, /* 0x1a */ + {{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5, + 0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02, + 0x62}}, /* 0x1b */ + {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba, + 0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03, + 0x00}}, /* 0x1c */ + {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a, + 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07, + 0x01}}, /* 0x1d */ + {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a, + 0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07, + 0x01}}, /* 0x1e */ + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a, + 0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07, + 0x01}}, /* 0x1f */ + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, + 0x00}}, /* 0x20 */ + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, + 0x00}}, /* 0x21 @ 4084 */ + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, + 0x00}}, /* 0x22 */ + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, + 0x00}}, /* 0x23 */ + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, + 0x00}}, /* 0x24 */ + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, + 0x00}}, /* 0x25 */ + {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10, + 0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04, + 0x00}}, /* 0x26 */ + {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f, + 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01, + 0x00}}, /* 0x27 */ + {{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f, + 0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05, + 0x63}}, /* 0x28 */ + {{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f, + 0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05, + 0x63}}, /* 0x29 */ + {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f, + 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01, + 0x00}}, /* 0x2a */ + {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f, + 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01, + 0x00}}, /* 0x2b */ + {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f, + 0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01, + 0x00}}, /* 0x2c */ + {{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba, + 0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05, + 0x44}}, /* 0x2d */ + {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba, + 0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05, + 0x44}}, /* 0x2e */ + {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba, + 0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05, + 0x44}}, /* 0x2f */ + {{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba, + 0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05, + 0x44}}, /* 0x30 */ + {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba, + 0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05, + 0x00}}, /* 0x31 */ + {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba, + 0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06, + 0x01}}, /* 0x32 */ + {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba, + 0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06, + 0x01}}, /* 0x33 */ + {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba, + 0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06, + 0x01}}, /* 0x34 */ + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1, + 0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02, + 0x01}}, /* 0x35 */ + {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1, + 0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02, + 0x01}}, /* 0x36 */ + {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1, /* 95 was 15 - illegal HBE! */ + 0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02, + 0x01}}, /* 0x37 */ + {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4, + 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07, + 0x01}}, /* 0x38 */ + {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4, + 0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07, + 0x01}}, /* 0x39 */ + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4, + 0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07, + 0x01}}, /* 0x3a */ +#if 0 + {{0xdc,0x9f,0x9f,0x00,0xab,0x19,0xe6,0xef, /* 1280x960 - invalid */ + 0xc0,0xc3,0xbf,0xbf,0xe7,0x10,0x00,0x07, + 0x01}}, /* 0x3b */ +#endif + {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff, /* 1280x960-60 - corrected */ + 0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07, + 0x01}}, /* 0x3b */ + {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e, + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05, + 0x00}}, /* 0x3c */ + {{0x7b,0x59,0x63,0x9f,0x6a,0x93,0x6f,0xf0, + 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05, + 0x01}}, /* 0x3d */ + {{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15, + 0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02, + 0x00}}, /* 0x3e */ + {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e, + 0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02, + 0x00}}, /* 0x3f */ + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1, + 0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02, + 0x01}}, /* 0x40 */ + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, + 0x01}}, /* 0x41 */ + {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5, + 0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07, + 0x01}}, /* 0x42 */ + {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10, + 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03, + 0x00}}, /* 0x43 */ + {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* 1152x864-75 */ + 0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07, + 0x01}}, /* 0x44 */ + {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* 848x480-38i */ + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, + 0x00}}, /* 0x45 */ + {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* 848x480-60 */ + 0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06, + 0x00}}, /* 0x46 */ + {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* 856x480-38i */ + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, + 0x00}}, /* 0x47 */ + {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* 856x480-60 */ + 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02, + 0x00}}, /* 0x48 */ + {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* 1360x768-60 */ + 0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03, + 0x01}}, /* 0x49 */ + {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* 1152x864-84 */ + 0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03, + 0x01}}, /* 0x4a */ + {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10, /* 1400x1050-75 */ + 0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03, + 0x00}}, /* 0x4b */ + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* 1280x960-85 */ + 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07, + 0x01}}, /* 0x4c */ + {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */ + 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05, + 0x01}}, /* 0x4d */ + {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* FSTN 320x480, TEMP - possibly invalid */ + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, + 0x00}}, /* 0x4e */ + {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff, /* 1280x800-60 */ + 0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07, + 0x21}}, /* 0x4f */ + {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10, /* 1680x1050-60 */ + 0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c, + 0x20}}, /* 0x50 */ + {{0x0e,0xef,0xef,0x92,0xfe,0x03,0x30,0xf0, /* 1920x1080-60i */ + 0x1e,0x83,0x1b,0x1c,0x31,0x00,0x01,0x00, + 0x61}}, /* 0x51 */ + {{0x85,0x77,0x77,0x89,0x7d,0x01,0x31,0xf0, /* 960x540-60 */ + 0x1e,0x84,0x1b,0x1c,0x32,0x00,0x00,0x02, + 0x41}}, /* 0x52 */ + {{0x87,0x77,0x77,0x8b,0x81,0x0b,0x68,0xf0, /* 960x600-60 */ + 0x5a,0x80,0x57,0x57,0x69,0x00,0x00,0x02, + 0x01}}, /* 0x53 */ + {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff, /* 1152x864-60 */ + 0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07, + 0x41}} /* 0x54 */ +}; + +static const SiS_MCLKDataStruct SiS310_MCLKData_0_315[] = +{ + { 0x3b,0x22,0x01,143}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166} +}; + +static const SiS_MCLKDataStruct SiS310_MCLKData_0_650[] = +{ + { 0x5a,0x64,0x82, 66}, + { 0xb3,0x45,0x82, 83}, + { 0x37,0x61,0x82,100}, + { 0x37,0x22,0x82,133}, + { 0x37,0x61,0x82,100}, + { 0x37,0x22,0x82,133}, + { 0x37,0x22,0x82,133}, + { 0x37,0x22,0x82,133} +}; + +static const SiS_MCLKDataStruct SiS310_MCLKData_0_330[] = +{ + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166}, + { 0x7c,0x08,0x01,200}, + { 0x79,0x06,0x01,250}, + { 0x7c,0x08,0x01,200}, + { 0x7c,0x08,0x01,200}, + { 0x7c,0x08,0x01,200}, + { 0x79,0x06,0x01,250} +}; + +static const SiS_MCLKDataStruct SiS310_MCLKData_0_660[] = +{ + { 0x5c,0x23,0x82,166}, + { 0x5c,0x23,0x82,166}, + { 0x37,0x21,0x82,200}, + { 0x37,0x22,0x82,133}, + { 0x29,0x21,0x82,150}, + { 0x5c,0x23,0x82,166}, + { 0x65,0x23,0x82,183}, + { 0x37,0x21,0x82,200} +}; + +static const SiS_MCLKDataStruct SiS310_MCLKData_0_760[] = +{ + { 0x37,0x22,0x82,133}, + { 0x5c,0x23,0x82,166}, + { 0x65,0x23,0x82,183}, + { 0x7c,0x08,0x82,200}, + { 0x29,0x21,0x82,150}, + { 0x5c,0x23,0x82,166}, + { 0x65,0x23,0x82,183}, + { 0x37,0x21,0x82,200} +}; + +static const SiS_MCLKDataStruct SiS310_MCLKData_0_761[] = +{ + { 0x37,0x22,0x82,133}, /* Preliminary */ + { 0x5c,0x23,0x82,166}, + { 0x65,0x23,0x82,183}, + { 0x7c,0x08,0x82,200}, + { 0x29,0x21,0x82,150}, + { 0x5c,0x23,0x82,166}, + { 0x65,0x23,0x82,183}, + { 0x37,0x21,0x82,200} +}; + +static const SiS_MCLKDataStruct SiS310_MCLKData_0_340[] = +{ + { 0x79,0x06,0x01,250}, + { 0x7c,0x08,0x01,200}, + { 0x7c,0x08,0x80,200}, + { 0x79,0x06,0x80,250}, + { 0x29,0x01,0x81,300}, + { 0x29,0x01,0x81,300}, + { 0x29,0x01,0x81,300}, + { 0x29,0x01,0x81,300} +}; + +static const SiS_MCLKDataStruct SiS310_MCLKData_1[] = /* ECLK */ +{ + { 0x29,0x21,0x82,150}, + { 0x5c,0x23,0x82,166}, + { 0x65,0x23,0x82,183}, + { 0x37,0x21,0x82,200}, + { 0x37,0x22,0x82,133}, + { 0x37,0x22,0x82,133}, + { 0x37,0x22,0x82,133}, + { 0x37,0x22,0x82,133} +}; + +static const SiS_MCLKDataStruct SiS310_MCLKData_1_340[] = +{ + { 0x7c,0x08,0x01,200}, + { 0x7c,0x08,0x01,200}, + { 0x7c,0x08,0x80,200}, + { 0x79,0x06,0x80,250}, + { 0x29,0x01,0x81,300}, + { 0x29,0x01,0x81,300}, + { 0x29,0x01,0x81,300}, + { 0x29,0x01,0x81,300} +}; + +static SiS_VCLKDataStruct SiS310_VCLKData[]= +{ + { 0x1b,0xe1, 25}, /* 0x00 */ + { 0x4e,0xe4, 28}, /* 0x01 */ + { 0x57,0xe4, 31}, /* 0x02 */ + { 0xc3,0xc8, 36}, /* 0x03 */ + { 0x42,0xe2, 40}, /* 0x04 */ + { 0xfe,0xcd, 43}, /* 0x05 */ + { 0x5d,0xc4, 44}, /* 0x06 */ + { 0x52,0xe2, 49}, /* 0x07 */ + { 0x53,0xe2, 50}, /* 0x08 */ + { 0x74,0x67, 52}, /* 0x09 */ + { 0x6d,0x66, 56}, /* 0x0a */ + { 0x5a,0x64, 65}, /* 0x0b */ /* was 6c c3 - WRONG */ + { 0x46,0x44, 67}, /* 0x0c */ + { 0xb1,0x46, 68}, /* 0x0d */ + { 0xd3,0x4a, 72}, /* 0x0e */ + { 0x29,0x61, 75}, /* 0x0f */ + { 0x6e,0x46, 76}, /* 0x10 */ + { 0x2b,0x61, 78}, /* 0x11 */ + { 0x31,0x42, 79}, /* 0x12 */ + { 0xab,0x44, 83}, /* 0x13 */ + { 0x46,0x25, 84}, /* 0x14 */ + { 0x78,0x29, 86}, /* 0x15 */ + { 0x62,0x44, 94}, /* 0x16 */ + { 0x2b,0x41,104}, /* 0x17 */ + { 0x3a,0x23,105}, /* 0x18 */ + { 0x70,0x44,108}, /* 0x19 */ + { 0x3c,0x23,109}, /* 0x1a */ + { 0x5e,0x43,113}, /* 0x1b */ + { 0xbc,0x44,116}, /* 0x1c */ + { 0xe0,0x46,132}, /* 0x1d */ + { 0x54,0x42,135}, /* 0x1e */ + { 0xea,0x2a,139}, /* 0x1f */ + { 0x41,0x22,157}, /* 0x20 */ + { 0x70,0x24,162}, /* 0x21 */ + { 0x30,0x21,175}, /* 0x22 */ + { 0x4e,0x22,189}, /* 0x23 */ + { 0xde,0x26,194}, /* 0x24 */ + { 0x62,0x06,202}, /* 0x25 */ + { 0x3f,0x03,229}, /* 0x26 */ + { 0xb8,0x06,234}, /* 0x27 */ + { 0x34,0x02,253}, /* 0x28 */ + { 0x58,0x04,255}, /* 0x29 */ + { 0x24,0x01,265}, /* 0x2a */ + { 0x9b,0x02,267}, /* 0x2b */ + { 0x70,0x05,270}, /* 0x2c */ + { 0x25,0x01,272}, /* 0x2d */ + { 0x9c,0x02,277}, /* 0x2e */ + { 0x27,0x01,286}, /* 0x2f */ + { 0x3c,0x02,291}, /* 0x30 */ + { 0xef,0x0a,292}, /* 0x31 */ + { 0xf6,0x0a,310}, /* 0x32 */ + { 0x95,0x01,315}, /* 0x33 */ + { 0xf0,0x09,324}, /* 0x34 */ + { 0xfe,0x0a,331}, /* 0x35 */ + { 0xf3,0x09,332}, /* 0x36 */ + { 0xea,0x08,340}, /* 0x37 */ + { 0xe8,0x07,376}, /* 0x38 */ + { 0xde,0x06,389}, /* 0x39 */ + { 0x52,0x2a, 54}, /* 0x3a 301 TV */ + { 0x52,0x6a, 27}, /* 0x3b 301 TV */ + { 0x62,0x24, 70}, /* 0x3c 301 TV */ + { 0x62,0x64, 70}, /* 0x3d 301 TV */ + { 0xa8,0x4c, 30}, /* 0x3e 301 TV */ + { 0x20,0x26, 33}, /* 0x3f 301 TV */ + { 0x31,0xc2, 39}, /* 0x40 */ + { 0x60,0x36, 30}, /* 0x41 Chrontel */ + { 0x40,0x4a, 28}, /* 0x42 Chrontel */ + { 0x9f,0x46, 44}, /* 0x43 Chrontel */ + { 0x97,0x2c, 26}, /* 0x44 */ + { 0x44,0xe4, 25}, /* 0x45 Chrontel */ + { 0x7e,0x32, 47}, /* 0x46 Chrontel */ + { 0x8a,0x24, 31}, /* 0x47 Chrontel */ + { 0x97,0x2c, 26}, /* 0x48 Chrontel */ + { 0xce,0x3c, 39}, /* 0x49 */ + { 0x52,0x4a, 36}, /* 0x4a Chrontel */ + { 0x34,0x61, 95}, /* 0x4b */ + { 0x78,0x27,108}, /* 0x4c - was 102 */ + { 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */ + { 0x41,0x4e, 21}, /* 0x4e */ + { 0xa1,0x4a, 29}, /* 0x4f Chrontel */ + { 0x19,0x42, 42}, /* 0x50 */ + { 0x54,0x46, 58}, /* 0x51 Chrontel */ + { 0x25,0x42, 61}, /* 0x52 */ + { 0x44,0x44, 66}, /* 0x53 Chrontel */ + { 0x3a,0x62, 70}, /* 0x54 Chrontel */ + { 0x62,0xc6, 34}, /* 0x55 848x480-60 */ + { 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */ + { 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */ + { 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */ + { 0x52,0x07,149}, /* 0x59 1280x960-85 */ + { 0x56,0x07,156}, /* 0x5a 1400x1050-75 */ + { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */ + { 0x45,0x25, 83}, /* 0x5c 1280x800 */ + { 0x70,0x0a,147}, /* 0x5d 1680x1050 */ + { 0x70,0x24,162}, /* 0x5e 1600x1200 */ + { 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */ + { 0x63,0x46, 68}, /* 0x60 1280x768_2 */ + { 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */ + { 0, 0, 0}, /* 0x62 - custom (will be filled out at run-time) */ + { 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */ + { 0x70,0x28, 90}, /* 0x64 1152x864@60 */ + { 0x41,0xc4, 32}, /* 0x65 848x480@60 */ + { 0x5c,0xc6, 32}, /* 0x66 856x480@60 */ + { 0x76,0xe7, 27}, /* 0x67 720x480@60 */ + { 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */ + { 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */ + { 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */ + { 0xe3,0x56, 41}, /* 0x6b 960x600@60 */ + { 0x45,0x25, 83}, /* 0x6c 1280x800 */ + { 0x70,0x28, 90} /* 0x6d 1152x864@60 */ +}; + +static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]= +{ + { 0x1b,0xe1, 25}, /* 0x00 */ + { 0x4e,0xe4, 28}, /* 0x01 */ + { 0x57,0xe4, 31}, /* 0x02 */ + { 0xc3,0xc8, 36}, /* 0x03 */ + { 0x42,0x47, 40}, /* 0x04 */ + { 0xfe,0xcd, 43}, /* 0x05 */ + { 0x5d,0xc4, 44}, /* 0x06 */ + { 0x52,0x47, 49}, /* 0x07 */ + { 0x53,0x47, 50}, /* 0x08 */ + { 0x74,0x67, 52}, /* 0x09 */ + { 0x6d,0x66, 56}, /* 0x0a */ + { 0x35,0x62, 65}, /* 0x0b */ /* Was 0x5a,0x64 - 650/LVDS+301: 35,62 */ + { 0x46,0x44, 67}, /* 0x0c */ + { 0xb1,0x46, 68}, /* 0x0d */ + { 0xd3,0x4a, 72}, /* 0x0e */ + { 0x29,0x61, 75}, /* 0x0f */ + { 0x6d,0x46, 75}, /* 0x10 */ + { 0x41,0x43, 78}, /* 0x11 */ + { 0x31,0x42, 79}, /* 0x12 */ + { 0xab,0x44, 83}, /* 0x13 */ + { 0x46,0x25, 84}, /* 0x14 */ + { 0x78,0x29, 86}, /* 0x15 */ + { 0x62,0x44, 94}, /* 0x16 */ + { 0x2b,0x22,104}, /* 0x17 */ + { 0x49,0x24,105}, /* 0x18 */ + { 0xf8,0x2f,108}, /* 0x19 */ /* 1400x1050 LCD */ + { 0x3c,0x23,109}, /* 0x1a */ + { 0x5e,0x43,113}, /* 0x1b */ + { 0xbc,0x44,116}, /* 0x1c */ + { 0xe0,0x46,132}, /* 0x1d */ +#if 0 + { 0xd4,0x28,135}, /* 0x1e */ + { 0xea,0x2a,139}, /* 0x1f */ + { 0x41,0x22,157}, /* 0x20 */ + { 0x70,0x24,162}, /* 0x21 */ +#endif + { 0xe2,0x46,135}, /* 0x1e */ /* 1280x1024-75, better clock for VGA2 */ + { 0xe5,0x46,139}, /* 0x1f */ /* 1024x768-120, better clock for VGA2 */ + { 0x15,0x01,157}, /* 0x20 */ /* 1280x1024-85, better clock for VGA2 */ + { 0x70,0x09,162}, /* 0x21 */ /* 1600x1200-60, better clock for VGA2 */ + { 0x30,0x21,175}, /* 0x22 */ + { 0x4e,0x22,189}, /* 0x23 */ + { 0xde,0x26,194}, /* 0x24 */ + { 0x70,0x07,202}, /* 0x25 */ + { 0x3f,0x03,229}, /* 0x26 */ + { 0xb8,0x06,234}, /* 0x27 */ + { 0x34,0x02,253}, /* 0x28 */ + { 0x58,0x04,255}, /* 0x29 */ + { 0x24,0x01,265}, /* 0x2a */ + { 0x9b,0x02,267}, /* 0x2b */ + { 0x70,0x05,270}, /* 0x2c */ + { 0x25,0x01,272}, /* 0x2d */ + { 0x9c,0x02,277}, /* 0x2e */ + { 0x27,0x01,286}, /* 0x2f */ + { 0x3c,0x02,291}, /* 0x30 */ + { 0xef,0x0a,292}, /* 0x31 */ + { 0xf6,0x0a,310}, /* 0x32 */ + { 0x95,0x01,315}, /* 0x33 */ + { 0xf0,0x09,324}, /* 0x34 */ + { 0xfe,0x0a,331}, /* 0x35 */ + { 0xf3,0x09,332}, /* 0x36 */ + { 0xea,0x08,340}, /* 0x37 */ + { 0xe8,0x07,376}, /* 0x38 */ + { 0xde,0x06,389}, /* 0x39 */ + { 0x52,0x2a, 54}, /* 0x3a 301 TV - start */ + { 0x52,0x6a, 27}, /* 0x3b 301 TV */ + { 0x62,0x24, 70}, /* 0x3c 301 TV */ + { 0x62,0x64, 70}, /* 0x3d 301 TV */ + { 0xa8,0x4c, 30}, /* 0x3e 301 TV */ + { 0x20,0x26, 33}, /* 0x3f 301 TV */ + { 0x31,0xc2, 39}, /* 0x40 */ + { 0x2e,0x48, 25}, /* 0x41 Replacement for LCD on 315 for index 0 */ + { 0x24,0x46, 25}, /* 0x42 Replacement for LCD on 315 for modes 0x01, 0x03, 0x0f, 0x10, 0x12 */ + { 0x26,0x64, 28}, /* 0x43 Replacement for LCD on 315 for index 1 */ + { 0x37,0x64, 40}, /* 0x44 Replacement for LCD on 315 for index 4 */ + { 0xa1,0x42,108}, /* 0x45 1280x960 LCD */ + { 0x37,0x61,100}, /* 0x46 1280x960 LCD */ + { 0x78,0x27,108}, /* 0x47 */ + { 0x97,0x2c, 26}, /* 0x48 UNUSED */ + { 0xce,0x3c, 39}, /* 0x49 UNUSED */ + { 0x52,0x4a, 36}, /* 0x4a UNUSED */ + { 0x34,0x61, 95}, /* 0x4b UNUSED */ + { 0x78,0x27,108}, /* 0x4c UNUSED */ + { 0x66,0x43,123}, /* 0x4d 1400x1050-60 */ + { 0x41,0x4e, 21}, /* 0x4e UNUSED */ + { 0xa1,0x4a, 29}, /* 0x4f UNUSED */ + { 0x19,0x42, 42}, /* 0x50 UNUSED */ + { 0x54,0x46, 58}, /* 0x51 UNUSED */ + { 0x25,0x42, 61}, /* 0x52 UNUSED */ + { 0x44,0x44, 66}, /* 0x53 UNUSED */ + { 0x3a,0x62, 70}, /* 0x54 UNUSED */ + { 0x62,0xc6, 34}, /* 0x55 848x480-60 */ + { 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP, UNUSED */ + { 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */ + { 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) TEMP, UNUSED */ + { 0x52,0x07,149}, /* 0x59 1280x960-85 */ + { 0x56,0x07,156}, /* 0x5a 1400x1050-75 */ + { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD (TMDS) */ + { 0xce,0x1e, 73}, /* 0x5c 1280x800_2 LCD (SiS LVDS) - (CRT1: 45 25 83) */ + { 0xbe,0x44,121}, /* 0x5d 1680x1050 LCD */ + { 0x70,0x24,162}, /* 0x5e 1600x1200 LCD */ + { 0x52,0x27, 75}, /* 0x5f 1280x720 (TMDS + HDTV) (correct) */ + { 0xc8,0x48, 77}, /* 0x60 1280x768_2 (SiS LVDS) */ + { 0x31,0x42, 79}, /* 0x61 1280x768_3 (SiS LVDS) - temp */ + { 0, 0, 0}, /* 0x62 - custom (will be filled out at run-time) */ + { 0x9c,0x62, 69}, /* 0x63 1280x720 (SiS LVDS) */ + { 0x70,0x28, 90}, /* 0x64 1152x864@60 */ + { 0x41,0xc4, 32}, /* 0x65 848x480@60 */ + { 0x5c,0xc6, 32}, /* 0x66 856x480@60 */ + { 0x76,0xe7, 27}, /* 0x67 720x480@60 */ + { 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */ + { 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced (UNUSED) */ + { 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */ + { 0xe3,0x56, 41}, /* 0x6b 960x600@60 */ + { 0x9c,0x62, 69}, /* 0x6c 1280x800 (SiS TMDS) (special) */ + { 0x70,0x28, 90} /* 0x6d 1152x864@60 */ +}; + +static const DRAM4Type SiS310_SR15[8] = { + {0x00,0x04,0x60,0x60}, + {0x0f,0x0f,0x0f,0x0f}, + {0xba,0xba,0xba,0xba}, + {0xa9,0xa9,0xac,0xac}, + {0xa0,0xa0,0xa0,0xa8}, + {0x00,0x00,0x02,0x02}, + {0x30,0x30,0x40,0x40}, + {0x00,0xa5,0xfb,0xf6} +}; + +#ifdef LINUX_KERNEL + +static UCHAR SiS310_SR07 = 0x18; + +static const DRAM4Type SiS310_CR40[5] = { + {0x77,0x77,0x33,0x33}, + {0x77,0x77,0x33,0x33}, + {0x00,0x00,0x00,0x00}, + {0x5b,0x5b,0x03,0x03}, + {0x00,0x00,0xf0,0xf8} +}; + +static UCHAR SiS310_CR49[] = {0xaa,0x88}; +static UCHAR SiS310_SR1F = 0x00; +static UCHAR SiS310_SR21 = 0xa5; +static UCHAR SiS310_SR22 = 0xfb; +static UCHAR SiS310_SR23 = 0xf6; +static UCHAR SiS310_SR24 = 0x0d; +static UCHAR SiS310_SR25[] = {0x33,0x3}; +static UCHAR SiS310_SR31 = 0x00; +static UCHAR SiS310_SR32 = 0x11; +static UCHAR SiS310_SR33 = 0x00; +static UCHAR SiS310_CRT2Data_1_2 = 0x00; +static UCHAR SiS310_CRT2Data_4_D = 0x00; +static UCHAR SiS310_CRT2Data_4_E = 0x00; +static UCHAR SiS310_CRT2Data_4_10 = 0x80; +static const USHORT SiS310_RGBSenseData = 0xd1; +static const USHORT SiS310_VideoSenseData = 0xb9; +static const USHORT SiS310_YCSenseData = 0xb3; +static const USHORT SiS310_RGBSenseData2 = 0x0190; +static const USHORT SiS310_VideoSenseData2 = 0x0174; +static const USHORT SiS310_YCSenseData2 = 0x016b; +#endif + +static const SiS_PanelDelayTblStruct SiS310_PanelDelayTbl[]= +{ + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}}, + {{0x10,0x40}} +}; + +static const SiS_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]= +{ + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}}, + {{0x28,0xc8}} +}; + +/**************************************************************/ +/* SIS VIDEO BRIDGE ----------------------------------------- */ +/**************************************************************/ + +static const SiS_LCDDataStruct SiS310_St2LCD1024x768Data[] = +{ + { 62, 25, 800, 546,1344, 806}, + { 32, 15, 930, 546,1344, 806}, + { 62, 25, 800, 546,1344, 806}, + { 104, 45, 945, 496,1344, 806}, + { 62, 25, 800, 546,1344, 806}, + { 31, 18,1008, 624,1344, 806}, + { 1, 1,1344, 806,1344, 806} +}; + +static const SiS_LCDDataStruct SiS310_ExtLCD1024x768Data[] = +{ + { 42, 25,1536, 419,1344, 806}, + { 48, 25,1536, 369,1344, 806}, + { 42, 25,1536, 419,1344, 806}, + { 48, 25,1536, 369,1344, 806}, + { 12, 5, 896, 500,1344, 806}, + { 42, 25,1024, 625,1344, 806}, + { 1, 1,1344, 806,1344, 806} +}; + +static const SiS_LCDDataStruct SiS310_St2LCD1280x1024Data[] = +{ + { 22, 5, 800, 510,1650,1088}, + { 22, 5, 800, 510,1650,1088}, + { 176, 45, 900, 510,1650,1088}, + { 176, 45, 900, 510,1650,1088}, + { 22, 5, 800, 510,1650,1088}, + { 13, 5,1024, 675,1560,1152}, + { 16, 9,1266, 804,1688,1072}, + { 1, 1,1688,1066,1688,1066} +}; + +static const SiS_LCDDataStruct SiS310_ExtLCD1280x1024Data[] = +{ + { 211, 60,1024, 501,1688,1066}, + { 211, 60,1024, 508,1688,1066}, + { 211, 60,1024, 501,1688,1066}, + { 211, 60,1024, 508,1688,1066}, + { 211, 60,1024, 500,1688,1066}, + { 211, 75,1024, 625,1688,1066}, + { 211, 120,1280, 798,1688,1066}, + { 1, 1,1688,1066,1688,1066} +}; + +static const SiS_Part2PortTblStruct SiS310_CRT2Part2_1024x768_1[] = +{ + {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}} +}; + +/* *** LCDA *** */ + +#if 0 +static const SiS_LVDSDataStruct SiS_LCDA1600x1200Data_1[]= +{ /* Clevo, 651+301C */ + {1200, 450, 2048,1250}, + {1200, 400, 2048,1250}, + {1280, 450, 2048,1250}, + {1280, 400, 2048,1250}, + {1200, 530, 2048,1250}, + {1360, 650, 2048,1250}, + {1584, 818, 2048,1250}, + {1688,1066, 2048,1250}, + {1688,1066, 2048,1250}, +#if 0 + {2048,1250, 2048,1250} /* this should be correct */ +#endif +#if 1 + {2160,1250, 2048,1250} /* ? */ +#endif +}; +#endif + +/**************************************************************/ +/* LVDS, CHRONTEL ------------------------------------------- */ +/**************************************************************/ + +static const SiS_LVDSDataStruct SiS310_CHTVUPALData[]= +{ + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 625, 840, 625}, + { 960, 750, 960, 750}, + {1400,1000,1400,1000} +}; + +static const SiS_LVDSDataStruct SiS310_CHTVOPALData[]= +{ + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 625, 840, 625}, + { 944, 625, 944, 625}, + {1400, 875,1400, 875} +}; + +static const SiS_LVDSDataStruct SiS310_CHTVUPALMData[]= +{ + { 840, 600, 840, 600}, + { 840, 600, 840, 600}, + { 840, 600, 840, 600}, + { 840, 600, 840, 600}, + { 784, 600, 784, 600}, + {1064, 750,1064, 750}, + {1160, 945,1160, 945} +}; + +static const SiS_LVDSDataStruct SiS310_CHTVOPALMData[]= +{ + { 840, 525, 840, 525}, + { 840, 525, 840, 525}, + { 840, 525, 840, 525}, + { 840, 525, 840, 525}, + { 784, 525, 784, 525}, + {1040, 700,1040, 700}, + {1160, 840,1160, 840} +}; + +static const SiS_LVDSDataStruct SiS310_CHTVUPALNData[]= +{ + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 625, 840, 625}, + { 960, 750, 960, 750}, + {1400,1000,1400,1000} +}; + +static const SiS_LVDSDataStruct SiS310_CHTVOPALNData[]= +{ + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 625, 840, 625}, + { 944, 625, 944, 625}, + {1400, 875,1400, 875} +}; + +static const SiS_LVDSDataStruct SiS310_CHTVSOPALData[]= /* (super overscan - no effect on 7019) */ +{ + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + { 840, 625, 840, 625}, + { 944, 625, 944, 625}, + {1400, 875,1400, 875} +}; + + +static const SiS_LVDSDesStruct SiS310_PanelType00_1[]= /* 800x600 */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType01_1[]= /* 1024x768 */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 805}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType02_1[]= /* 1280x1024 */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 1065}, + { 0, 0}, + { 0, 0} +}; + + +static const SiS_LVDSDesStruct SiS310_PanelType03_1[]= +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType04_1[]= +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType05_1[]= +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType06_1[]= +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType07_1[]= +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType08_1[]= /* 1400x1050 */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType09_1[]= /* 1280x768 */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType0a_1[]= /* 1600x1200 */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType0b_1[]= /* 640x480_2 */ +{ + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 8, 524}, + { 0, 524} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType0c_1[]= /* 640x480_3 */ +{ + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 0, 524}, + { 8, 524}, + { 0, 524} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType0d_1[]= +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType0e_1[]= +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType0f_1[]= +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType00_2[]= +{ + {980, 528}, + {980, 503}, + {980, 528}, + {980, 503}, + {980, 568}, + { 0, 628}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType01_2[]= +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 806}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType02_2[]= +{ + {1368, 754}, + {1368, 729}, + {1368, 754}, + {1368, 729}, + {1368, 794}, + {1448, 854}, + {1560, 938}, + { 0,1066}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType03_2[]= +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType04_2[]= +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType05_2[]= +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType06_2[]= +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType07_2[]= +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType08_2[]= /* 1400x1050 */ +{ + {1308, 741}, + {1308, 716}, + {1308, 741}, + {1308, 716}, + {1308, 781}, + {1388, 841}, + {1500, 925}, + {1628,1053}, + { 0,1065}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType09_2[]= /* 1280x768 */ +{ + {1083, 622}, + {1083, 597}, + {1083, 622}, + {1083, 597}, + {1083, 662}, + {1163, 722}, + {1286, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType0a_2[]= /* 1600x1200 */ +{ + {1568, 920}, + {1568, 895}, + {1568, 920}, + {1568, 895}, + {1568, 960}, + {1648,1020}, + {1760,1104}, + {1888,1232}, + {1948,1245}, + { 0, 0} +#if 0 + {1568, 850}, + {1568, 825}, + {1568, 850}, + {1568, 825}, + {1568, 890}, + {1648, 950}, + {1760,1034}, + {1888,1162}, + {1948,1175}, + { 0, 0} +#endif +}; + +static const SiS_LVDSDesStruct SiS310_PanelType0b_2[]= /* 640x480_2 */ +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType0c_2[]= /* 640x480_3 */ +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType0d_2[]= +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType0e_2[]= +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelType0f_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelTypeNS_1[]= +{ + { 8, 0}, + { 8, 0}, + { 8, 0}, + { 8, 0}, + { 8, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 806}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS310_PanelTypeNS_2[] = +{ + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0} +}; + +/* CRT1 CRTC for SlaveModes and LCDA */ + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1[] = +{ + {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f, + 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, + 0x00 }}, + {{0x6b,0x4f,0x8f,0x55,0x85,0x78,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, + 0x00 }}, + {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f, + 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, + 0x00 }}, + {{0x6b,0x4f,0x8f,0x55,0x85,0x78,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, + 0x00 }}, + {{0x6b,0x4f,0x8f,0x55,0x85,0xfa,0x1f, + 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05, + 0x00 }}, + {{0x7f,0x63,0x83,0x69,0x19,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1_H[] = +{ + {{0x43,0x27,0x87,0x2d,0x1d,0xaa,0x1f, + 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, + 0x00 }}, + {{0x43,0x27,0x87,0x2d,0x1d,0x78,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, + 0x00 }}, + {{0x43,0x27,0x87,0x2d,0x1d,0xfa,0x1f, + 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05, + 0x00 }}, + {{0x43,0x27,0x87,0x2d,0x1d,0x78,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, + 0x00 }}, + {{0x43,0x27,0x87,0x2d,0x1d,0xfa,0x1f, + 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05, + 0x00 }}, + {{0x4d,0x31,0x91,0x37,0x07,0x72,0xf0, + 0x58,0x8d,0x57,0x73,0x20,0x00,0x01, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2[]= +{ + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, + 0xff,0x84,0x8f,0x73,0x00,0x00,0x06, + 0x00 }}, + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, + 0xe6,0x8b,0x5d,0x73,0x00,0x00,0x06, + 0x00 }}, + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, + 0xff,0x84,0x8f,0x73,0x00,0x00,0x06, + 0x00 }}, + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e, + 0xe6,0x8b,0x5d,0x73,0x00,0x00,0x06, + 0x00 }}, + {{0x7f,0x4f,0x83,0x62,0x12,0x72,0xba, + 0x27,0x8c,0xdf,0x73,0x00,0x00,0x06, + 0x00 }}, + {{0x7f,0x63,0x83,0x69,0x19,0x72,0xf0, + 0x58,0x8d,0x57,0x73,0x20,0x00,0x06, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2_H[] = +{ + {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e, + 0xff,0x84,0x8f,0x73,0x00,0x00,0x01, + 0x00 }}, + {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e, + 0xd6,0x8b,0x5d,0x73,0x00,0x00,0x01, + 0x00 }}, + {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e, + 0xff,0x84,0x8f,0x73,0x00,0x00,0x01, + 0x00 }}, + {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e, + 0xd6,0x8b,0x5d,0x73,0x00,0x00,0x01, + 0x00 }}, + {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0xba, + 0x27,0x8c,0xdf,0x73,0x00,0x00,0x01, + 0x00 }}, + {{0x4d,0x31,0x91,0x3a,0x0a,0x72,0xf0, + 0x63,0x88,0x57,0x73,0x00,0x00,0x01, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1[] = +{ + {{0x73,0x4f,0x97,0x53,0x84,0xb4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05, + 0x00}}, + {{0x73,0x4f,0x97,0x53,0x84,0x82,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x05, + 0x00}}, + {{0x73,0x4f,0x97,0x53,0x84,0xb4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05, + 0x00}}, + {{0x73,0x4f,0x97,0x53,0x84,0x82,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x05, + 0x00}}, + {{0x73,0x4f,0x97,0x53,0x84,0x04,0x3e, + 0xE2,0x89,0xDf,0x05,0x00,0x00,0x05, + 0x00}}, + {{0x87,0x63,0x8B,0x67,0x18,0x7c,0xf0, + 0x5A,0x81,0x57,0x7D,0x00,0x00,0x06, + 0x01}}, + {{0xA3,0x7f,0x87,0x83,0x94,0x24,0xf5, + 0x02,0x89,0xFf,0x25,0x10,0x00,0x02, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1_H[] = +{ + {{0x4b,0x27,0x8f,0x2b,0x1c,0xb4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05, + 0x00 }}, + {{0x4b,0x27,0x8f,0x2b,0x1c,0x82,0x1f, + 0x60,0x87,0x5D,0x83,0x01,0x00,0x05, + 0x00}}, + {{0x4b,0x27,0x8f,0x2b,0x1c,0xb4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x05, + 0x00}}, + {{0x4b,0x27,0x8f,0x2b,0x1c,0x82,0x1f, + 0x60,0x87,0x5D,0x83,0x01,0x00,0x05, + 0x00}}, + {{0x4b,0x27,0x8f,0x2b,0x1c,0x04,0x3e, + 0xE2,0x89,0xDf,0x05,0x00,0x00,0x05, + 0x00}}, + {{0x55,0x31,0x99,0x35,0x06,0x7c,0xf0, + 0x5A,0x81,0x57,0x7D,0x00,0x00,0x01, + 0x01}}, + {{0x63,0x3F,0x87,0x43,0x94,0x24,0xf5, + 0x02,0x89,0xFf,0x25,0x10,0x00,0x01, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2[] = +{ + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x57,0x8e,0x8f,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x3e,0x85,0x5d,0x25,0x10,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x57,0x8e,0x8f,0x25,0x30,0x00,0x06, + 0x00 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x3e,0x85,0x5d,0x25,0x10,0x00,0x06, + 0x01 }}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x7f,0x86,0xdf,0x25,0x10,0x00,0x06, + 0x00 }}, + {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1, + 0xbb,0x82,0x57,0x25,0x10,0x00,0x02, + 0x01 }}, + {{0xa3,0x7f,0x87,0x83,0x94,0x24,0xf5, + 0x02,0x89,0xff,0x25,0x10,0x00,0x02, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2_H[] = +{ + {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb, + 0x57,0x8e,0x8f,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb, + 0x3e,0x85,0x5d,0x25,0x10,0x00,0x01, + 0x00 }}, + {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb, + 0x57,0x8e,0x8f,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb, + 0x3e,0x85,0x5d,0x25,0x10,0x00,0x01, + 0x00 }}, + {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb, + 0x7f,0x86,0xdf,0x25,0x10,0x00,0x01, + 0x00 }}, + {{0x71,0x31,0x95,0x46,0x97,0x24,0xf1, + 0xbb,0x82,0x57,0x25,0x10,0x00,0x01, + 0x01 }}, + {{0x63,0x3f,0x87,0x46,0x97,0x24,0xf5, + 0x0f,0x86,0xff,0x25,0x30,0x00,0x01, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1[] = +{ + {{0x7e,0x4f,0x82,0x58,0x04,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06, + 0x00}}, + {{0x7e,0x4f,0x82,0x58,0x04,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06, + 0x00}}, + {{0x7e,0x4f,0x82,0x58,0x04,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06, + 0x00}}, + {{0x7e,0x4f,0x82,0x58,0x04,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06, + 0x00}}, + {{0x7e,0x4f,0x82,0x58,0x04,0x08,0x3e, + 0xe0,0x84,0xdf,0x09,0x00,0x00,0x06, + 0x00}}, + {{0x92,0x63,0x96,0x6c,0x18,0x80,0xf0, + 0x58,0x8c,0x57,0x81,0x20,0x00,0x06, + 0x01}}, + {{0xae,0x7f,0x92,0x88,0x94,0x28,0xf5, + 0x00,0x84,0xff,0x29,0x10,0x00,0x02, + 0x01}}, + {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a, + 0x00,0x84,0xff,0x29,0x09,0x00,0x07, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1_H[] = +{ + {{0x56,0x27,0x9a,0x31,0x1c,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x56,0x27,0x9a,0x31,0x1c,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05, + 0x00}}, + {{0x56,0x27,0x9a,0x31,0x1c,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x56,0x27,0x9a,0x31,0x1c,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05, + 0x01}}, + {{0x56,0x27,0x9a,0x31,0x1c,0x08,0x3e, + 0xe0,0x84,0xdf,0x09,0x00,0x00,0x05, + 0x00}}, + {{0x60,0x31,0x84,0x3a,0x86,0x80,0xf0, + 0x58,0x8c,0x57,0x81,0x20,0x00,0x01, + 0x01}}, + {{0x6e,0x3f,0x92,0x48,0x94,0x28,0xf5, + 0x00,0x84,0xff,0x29,0x10,0x00,0x01, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2[] = +{ + {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92, + 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92, + 0xaf,0x83,0x44,0x43,0x21,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92, + 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92, + 0xaf,0x83,0x44,0x43,0x21,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92, + 0xf0,0x84,0x85,0x84,0x11,0x00,0x02, + 0x01}}, + {{0xce,0x63,0x92,0x8b,0x19,0x28,0xd4, + 0x3f,0x83,0x57,0x29,0x01,0x00,0x03, + 0x01}}, + {{0xce,0x7f,0x92,0x99,0x07,0x28,0xd4, + 0x93,0x87,0xff,0x29,0x21,0x00,0x07, + 0x01}}, + {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a, + 0x00,0x84,0xff,0x29,0x09,0x00,0x07, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2_H[] = +{ + {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92, + 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92, + 0xaf,0x83,0x44,0x43,0x21,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92, + 0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92, + 0xfa,0x83,0x44,0x43,0x31,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92, + 0xf0,0x84,0x85,0x84,0x11,0x00,0x06, + 0x01}}, + {{0x9c,0x31,0x80,0x59,0x87,0x28,0xd4, + 0x3f,0x83,0x57,0x29,0x01,0x00,0x06, + 0x01}}, + {{0x8e,0x3f,0x92,0x59,0x07,0x28,0xd4, + 0x93,0x87,0xff,0x29,0x21,0x00,0x06, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1[] = +{ + {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f, + 0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f, + 0x5e,0x81,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f, + 0x90,0x83,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f, + 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x93,0x54,0x82,0xee,0x1f, + 0xdf,0x82,0xdf,0xef,0x10,0x00,0x05, + 0x00}}, + {{0x83,0x63,0x87,0x68,0x16,0x66,0xf0, + 0x57,0x8e,0x57,0x67,0x20,0x00,0x06, + 0x01}}, + {{0x9f,0x7f,0x83,0x84,0x92,0x0e,0xf1, + 0xff,0x86,0xff,0x0f,0x10,0x00,0x02, + 0x01,}}, + {{0xbf,0x9f,0x83,0xa4,0x12,0x0e,0xde, + 0xff,0x86,0xff,0x0f,0x01,0x00,0x07, + 0x01}}, + {{0xce,0xae,0x92,0xb3,0x01,0x28,0x10, + 0x19,0x80,0x19,0x29,0x0f,0x00,0x03, + 0x00}} +#if 0 + {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f, + 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f, + 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f, + 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f, + 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x93,0x54,0x82,0xee,0x1f, + 0xe2,0x86,0xdf,0xef,0x10,0x00,0x05, + 0x00}}, + {{0x83,0x63,0x87,0x68,0x16,0x66,0xf0, + 0x5a,0x8e,0x57,0x67,0x20,0x00,0x06, + 0x01}}, + {{0x9f,0x7f,0x83,0x84,0x92,0x0e,0xf5, + 0x02,0x86,0xff,0x0f,0x10,0x00,0x02, + 0x01}}, + {{0xbf,0x9f,0x83,0xa4,0x12,0x0e,0x5a, + 0x02,0x86,0xff,0x0f,0x09,0x00,0x07, + 0x01}}, + {{0xce,0xae,0x92,0xb3,0x01,0x28,0x10, + 0x1a,0x80,0x19,0x29,0x0f,0x00,0x03, + 0x00}} +#endif +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1_H[] = +{ + {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f, + 0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, + 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f, + 0x90,0x83,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, + 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f, + 0xdf,0x86,0xdf,0xef,0x10,0x00,0x05, + 0x00}}, + {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0, + 0x57,0x8e,0x57,0x67,0x20,0x00,0x01, + 0x01}}, + {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf1, + 0xff,0x86,0xff,0x0f,0x10,0x00,0x01, + 0x01}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a, + 0x02,0x86,0xff,0x0f,0x09,0x00,0x05, + 0x01}}, + {{0x76,0x56,0x9a,0x5b,0x89,0x28,0x10, + 0x1c,0x80,0x19,0x29,0x0b,0x00,0x05, + 0x00}} +#if 0 + {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f, + 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, + 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f, + 0x92,0x86,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, + 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f, + 0xe2,0x86,0xdf,0xef,0x10,0x00,0x05, + 0x00}}, + {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0, + 0x5a,0x8e,0x57,0x67,0x20,0x00,0x01, + 0x01}}, + {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf5, + 0x02,0x86,0xff,0x0f,0x10,0x00,0x01, + 0x01}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a, + 0x02,0x86,0xff,0x0f,0x09,0x00,0x05, + 0x01}}, + {{0x76,0x56,0x9a,0x5b,0x89,0x28,0x10, + 0x1c,0x80,0x19,0x29,0x0b,0x00,0x05, + 0x00}} +#endif +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_2[] = +{ + {{0xce,0x72,0x91,0x84,0x92,0x28,0x92, + 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x84,0x92,0x28,0x92, + 0xbe,0x82,0x44,0x43,0x01,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x84,0x92,0x28,0x92, + 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x84,0x92,0x28,0x92, + 0xbe,0x82,0x44,0x43,0x01,0x00,0x02, + 0x01}}, + {{0xce,0x72,0x91,0x84,0x92,0x28,0x92, + 0xff,0x83,0x85,0x84,0x11,0x00,0x02, + 0x01}}, + {{0xce,0x63,0x92,0x8e,0x1c,0x28,0xd4, + 0x3f,0x83,0x57,0x29,0x01,0x00,0x03, + 0x01}}, + {{0xce,0x7f,0x92,0x9c,0x0a,0x28,0xd4, + 0x93,0x87,0xff,0x29,0x21,0x00,0x07, + 0x01}}, + {{0xce,0x9f,0x92,0xac,0x1a,0x28,0x5a, + 0x13,0x87,0xff,0x29,0x29,0x00,0x07, + 0x01}}, + {{0xce,0xae,0x92,0xbc,0x0a,0x28,0x10, + 0x20,0x84,0x19,0x29,0x0f,0x00,0x03, + 0x00}} +#if 0 + {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a, + 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03, + 0x00}}, + {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a, + 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03, + 0x01}}, + {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a, + 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03, + 0x00}}, + {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a, + 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03, + 0x00}}, + {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9e, + 0x03,0x87,0xdf,0x29,0x01,0x00,0x03, + 0x00}}, + {{0xce,0x63,0x92,0x96,0x04,0x28,0xd4, + 0x3f,0x83,0x57,0x29,0x01,0x00,0x07, + 0x01}}, + {{0xce,0x7f,0x92,0xa4,0x12,0x28,0xd4, + 0x93,0x87,0xff,0x29,0x21,0x00,0x07, + 0x01}}, + {{0xce,0x9f,0x92,0xb4,0x02,0x28,0x5a, + 0x13,0x87,0xff,0x29,0x29,0x00,0x03, + 0x01}}, + {{0xce,0xae,0x92,0xbc,0x0a,0x28,0x10, + 0x20,0x84,0x19,0x29,0x0f,0x00,0x03, + 0x00}} +#endif +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_2_H[] = +{ + {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92, + 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92, + 0xbe,0x82,0x44,0x43,0x01,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92, + 0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92, + 0xbe,0x82,0x44,0x43,0x01,0x00,0x06, + 0x01}}, + {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92, + 0xff,0x83,0x85,0x84,0x11,0x00,0x06, + 0x01}}, + {{0x9c,0x31,0x80,0x5c,0x8a,0x28,0xd4, + 0x3f,0x83,0x57,0x29,0x01,0x00,0x06, + 0x01}}, + {{0x8e,0x3f,0x92,0x5c,0x0a,0x28,0xd4, + 0x93,0x87,0xff,0x29,0x21,0x00,0x06, + 0x01}}, + {{0x7e,0x4f,0x82,0x5c,0x0a,0x28,0x5a, + 0x13,0x87,0xff,0x29,0x29,0x00,0x06, + 0x01}}, + {{0x76,0x56,0x9a,0x64,0x92,0x28,0x10, + 0x20,0x84,0x19,0x29,0x0f,0x00,0x05, + 0x00}} +#if 0 + {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a, + 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06, + 0x00}}, + {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a, + 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06, + 0x00}}, + {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a, + 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06, + 0x00}}, + {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a, + 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06, + 0x00}}, + {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9e, + 0x03,0x87,0xdf,0x29,0x01,0x00,0x06, + 0x00}}, + {{0x9c,0x31,0x80,0x64,0x92,0x28,0xd4, + 0x3f,0x83,0x57,0x29,0x01,0x00,0x06, + 0x01}}, + {{0x8e,0x3f,0x92,0x64,0x12,0x28,0xd4, + 0x93,0x87,0xff,0x29,0x21,0x00,0x06, + 0x01}}, + {{0x7e,0x4f,0x82,0x64,0x12,0x28,0x5a, + 0x13,0x87,0xff,0x29,0x29,0x00,0x06, + 0x01}}, + {{0x76,0x56,0x9a,0x64,0x92,0x28,0x10, + 0x20,0x84,0x19,0x29,0x0f,0x00,0x05, + 0x00}} +#endif +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1[] = +{ + {{0x83,0x4F,0x87,0x5B,0x13,0x06,0x3E, + 0xB3,0x86,0x8F,0x07,0x20,0x00,0x06, + 0x00}}, + {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F, + 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06, + 0x00}}, + {{0x83,0x4F,0x87,0x5B,0x13,0x06,0x3E, + 0xB3,0x86,0x8F,0x07,0x20,0x00,0x06, + 0x00}}, + {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F, + 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06, + 0x00}}, + {{0x83,0x4F,0x87,0x5B,0x13,0x56,0xBA, + 0x03,0x86,0xDF,0x57,0x00,0x00,0x06, + 0x00}}, + {{0x97,0x63,0x9B,0x6F,0x07,0xCE,0xF0, + 0x7B,0x8E,0x57,0xCF,0x20,0x00,0x02, + 0x01}}, + {{0xB3,0x7F,0x97,0x8B,0x83,0x76,0xF5, + 0x23,0x86,0xFF,0x77,0x10,0x00,0x06, + 0x01}}, + {{0xD3,0x9F,0x97,0xAB,0x03,0x76,0x5A, + 0x23,0x86,0xFF,0x77,0x09,0x00,0x03, + 0x01}}, + {{0xE2,0xAE,0x86,0xBA,0x92,0x90,0x10, + 0x3D,0x80,0x19,0x91,0x0F,0x00,0x03, + 0x00}}, + {{0xFB,0xC7,0x9F,0xD3,0x8B,0x26,0x11, + 0xD3,0x86,0xAF,0x27,0x3F,0x00,0x07, + 0x00}} +#if 0 + {{0x83,0x4f,0x87,0x51,0x09,0xc0,0x1f, + 0x90,0x84,0x8f,0xc1,0x30,0x00,0x06, + 0x00}}, + {{0x83,0x4f,0x87,0x51,0x09,0x8e,0x1f, + 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x06, + 0x00}}, + {{0x83,0x4f,0x87,0x51,0x09,0xc0,0x1f, + 0x90,0x84,0x8f,0xc1,0x30,0x00,0x06, + 0x00}}, + {{0x83,0x4f,0x87,0x51,0x09,0x8e,0x1f, + 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x06, + 0x00}}, + {{0x83,0x4f,0x87,0x51,0x09,0x10,0x3e, + 0xe0,0x84,0xdf,0x11,0x00,0x00,0x06, + 0x00}}, + {{0x97,0x63,0x9b,0x65,0x1d,0x88,0xf0, + 0x58,0x8c,0x57,0x89,0x20,0x00,0x06, + 0x01}}, + {{0xb3,0x7f,0x97,0x81,0x99,0x30,0xf5, + 0x00,0x84,0xff,0x31,0x10,0x00,0x02, + 0x01}}, + {{0xd3,0x9f,0x97,0xa1,0x19,0x30,0x5a, + 0x00,0x84,0xff,0x31,0x09,0x00,0x07, + 0x01}}, + {{0xe2,0xae,0x86,0xb0,0x88,0x4a,0x10, + 0x1a,0x8e,0x19,0x4b,0x2f,0x00,0x03, + 0x00}}, + {{0xfb,0xc7,0x9f,0xc9,0x81,0xe0,0x10, + 0xb0,0x84,0xaf,0xe1,0x2f,0x00,0x07, + 0x00}} +#endif +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1_H[] = +{ + {{0x5B,0x27,0x9F,0x33,0x0B,0x06,0x2E, + 0xB3,0x86,0x8F,0x07,0x20,0x00,0x01, + 0x00}}, + {{0x5B,0x27,0x9F,0x29,0x01,0x8E,0x1F, + 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06, + 0x00}}, + {{0x5B,0x27,0x9F,0x33,0x0B,0x06,0x2E, + 0xB3,0x86,0x8F,0x07,0x20,0x00,0x01, + 0x00}}, + {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F, + 0x81,0x84,0x5D,0xD5,0x10,0x00,0x06, + 0x00}}, + {{0x5B,0x27,0x9F,0x33,0x0B,0x56,0xBA, + 0x03,0x86,0xDF,0x57,0x00,0x00,0x01, + 0x00}}, + {{0x65,0x31,0x89,0x3D,0x95,0xCE,0xF0, + 0x7B,0x8E,0x57,0xCF,0x20,0x00,0x01, + 0x01}}, + {{0x73,0x3F,0x97,0x4B,0x83,0x76,0xF5, + 0x23,0x86,0xFF,0x77,0x10,0x00,0x05, + 0x01}}, + {{0xD3,0x9F,0x97,0xAB,0x03,0x76,0x5A, + 0x23,0x86,0xFF,0x77,0x09,0x00,0x03, + 0x01}}, + {{0xE2,0xAE,0x86,0xBA,0x92,0x90,0x10, + 0x3D,0x80,0x19,0x91,0x0F,0x00,0x03, + 0x00}}, + {{0x97,0x63,0x9B,0x6F,0x07,0xE0,0x10, + 0xB0,0x84,0xAF,0xE1,0x2F,0x00,0x06, + 0x00}} +#if 0 + {{0x5b,0x27,0x9f,0x29,0x01,0xc0,0x1f, + 0x90,0x84,0x8f,0xc1,0x30,0x00,0x01, + 0x00}}, + {{0x5b,0x27,0x9f,0x29,0x01,0x8e,0x1f, + 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x01, + 0x00}}, + {{0x5b,0x27,0x9f,0x29,0x01,0xc0,0x1f, + 0x90,0x84,0x8f,0xc1,0x30,0x00,0x01, + 0x00}}, + {{0x5b,0x27,0x9f,0x29,0x01,0x8e,0x1f, + 0x5e,0x82,0x5d,0x8f,0x10,0x00,0x01, + 0x00}}, + {{0x5b,0x27,0x9f,0x29,0x01,0x10,0x3e, + 0xe0,0x84,0xdf,0x11,0x00,0x00,0x01, + 0x00}}, + {{0x65,0x31,0x89,0x33,0x8b,0x88,0xf0, + 0x58,0x8c,0x57,0x89,0x20,0x00,0x01, + 0x01}}, + {{0x73,0x3f,0x97,0x41,0x99,0x30,0xf5, + 0x00,0x84,0xff,0x31,0x10,0x00,0x01, + 0x01}}, + {{0x83,0x4f,0x87,0x51,0x09,0x30,0x5a, + 0x00,0x84,0xff,0x31,0x09,0x00,0x06, + 0x01}}, + {{0x8a,0x56,0x8e,0x58,0x10,0x4a,0x10, + 0x1a,0x8e,0x19,0x4b,0x2f,0x00,0x06, + 0x00}}, + {{0x97,0x63,0x9b,0x65,0x1d,0xe0,0x10, + 0xb0,0x84,0xaf,0xe1,0x2f,0x00,0x06, + 0x00}} +#endif +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_2[] = +{ + {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97, + 0x43,0x86,0xDB,0xDA,0x11,0x00,0x07, + 0x01}}, + {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97, + 0x2A,0x8D,0xC2,0xC1,0x11,0x00,0x07, + 0x01}}, + {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97, + 0x43,0x86,0xDB,0xDA,0x11,0x00,0x07, + 0x01}}, + {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97, + 0x2A,0x8D,0xC2,0xC1,0x11,0x00,0x07, + 0x01}}, + {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x9F, + 0x6B,0x8E,0x03,0x02,0x01,0x00,0x07, + 0x01}}, + {{0xFB,0x63,0x9F,0xA1,0x99,0x26,0xD5, + 0xA7,0x8A,0xBF,0xBE,0x01,0x00,0x07, + 0x01}}, + {{0xFB,0x7F,0x9F,0xAF,0x87,0x26,0xDD, + 0xFB,0x8E,0x13,0x12,0x31,0x00,0x03, + 0x01}}, + {{0xFB,0x9F,0x9F,0xBF,0x97,0x26,0x5B, + 0x7B,0x8E,0xFF,0x27,0x39,0x00,0x03, + 0x01}}, + {{0xFB,0xAE,0x9F,0xC6,0x9E,0x26,0x11, + 0x88,0x8B,0x19,0x27,0x1F,0x00,0x03, + 0x00}}, + {{0xFB,0xC7,0x9F,0xD3,0x8B,0x26,0x11, + 0xD3,0x86,0xAF,0x27,0x3F,0x00,0x07, + 0x00}} +#if 0 + {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96, + 0x20,0x84,0xb9,0xb8,0x01,0x00,0x07, + 0x01}}, + {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96, + 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x07, + 0x01}}, + {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96, + 0x20,0x84,0xb9,0xb8,0x01,0x00,0x07, + 0x01}}, + {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96, + 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x07, + 0x01}}, + {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96, + 0x48,0x8c,0xe1,0xe0,0x11,0x00,0x07, + 0x01}}, + {{0xfb,0x63,0x9f,0x9a,0x92,0xe0,0xd4, + 0x9b,0x8f,0x9d,0x9c,0x21,0x00,0x07, + 0x01}}, + {{0xfb,0x7f,0x9f,0xa8,0x80,0xe0,0xd4, + 0xef,0x83,0xff,0xe1,0x21,0x00,0x03, + 0x01}}, + {{0xfb,0x9f,0x9f,0xb8,0x90,0xe0,0x5a, + 0x6f,0x83,0xff,0xe1,0x29,0x00,0x03, + 0x01}}, + {{0xfb,0xae,0x9f,0xbf,0x97,0xe0,0x10, + 0x7c,0x80,0x19,0xe1,0x0f,0x00,0x03, + 0x00}}, + {{0xfb,0xc7,0x9f,0xc9,0x84,0xe0,0x10, + 0xc7,0x8b,0xaf,0xe1,0x0f,0x00,0x07, + 0x00}} +#endif +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_2_H[] = +{ + {{0xD3,0x5F,0x9E,0x6F,0x07,0x26,0x97, + 0x43,0x86,0xDB,0xDA,0x11,0x00,0x02, + 0x01}}, + {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97, + 0x6B,0x8E,0x83,0x82,0x01,0x00,0x03, + 0x01}}, + {{0xD3,0x5F,0x9E,0x6F,0x07,0x26,0x97, + 0x43,0x86,0xDB,0xDA,0x11,0x00,0x02, + 0x01}}, + {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97, + 0x07,0x8B,0xA0,0x9F,0x01,0x00,0x02, + 0x01}}, + {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97, + 0x6B,0x8E,0x83,0x82,0x01,0x00,0x03, + 0x01}}, + {{0xC9,0x31,0x8D,0x6F,0x07,0x26,0xD5, + 0xA7,0x8A,0xBF,0xBE,0x01,0x00,0x03, + 0x01}}, + {{0xBB,0x3F,0x9F,0x6F,0x87,0x26,0xDD, + 0xFB,0x8E,0x13,0x12,0x31,0x00,0x02, + 0x01}}, + {{0xAB,0x4F,0x8F,0x68,0x80,0xE0,0x5A, + 0x6F,0x83,0xFF,0xE1,0x29,0x00,0x02, + 0x01}}, + {{0xA3,0x56,0x87,0x67,0x9F,0xE0,0x10, + 0x7C,0x80,0x19,0xE1,0x0F,0x00,0x06, + 0x00}}, + {{0x97,0x63,0x9B,0x68,0x00,0xE0,0x10, + 0xC7,0x8B,0xAF,0xE1,0x0F,0x00,0x02, + 0x00}} +#if 0 + {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96, + 0x20,0x84,0xb9,0xb8,0x01,0x00,0x02, + 0x01}}, + {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96, + 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x02, + 0x01}}, + {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96, + 0x20,0x84,0xb9,0xb8,0x01,0x00,0x02, + 0x01}}, + {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96, + 0x07,0x8b,0xa0,0x9f,0x01,0x00,0x02, + 0x01}}, + {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96, + 0x48,0x8c,0xe1,0xe0,0x11,0x00,0x02, + 0x01}}, + {{0xc9,0x31,0x8d,0x68,0x00,0xe0,0xd4, + 0x9b,0x8f,0x9d,0x9c,0x21,0x00,0x03, + 0x01}}, + {{0xbb,0x3f,0x9f,0x68,0x80,0xe0,0xd4, + 0xef,0x83,0xff,0xe1,0x21,0x00,0x02, + 0x01}}, + {{0xab,0x4f,0x8f,0x68,0x80,0xe0,0x5a, + 0x6f,0x83,0xff,0xe1,0x29,0x00,0x02, + 0x01}}, + {{0xa3,0x56,0x87,0x67,0x9f,0xe0,0x10, + 0x7c,0x80,0x19,0xe1,0x0f,0x00,0x06, + 0x00}}, + {{0x97,0x63,0x9b,0x68,0x00,0xe0,0x10, + 0xc7,0x8b,0xaf,0xe1,0x0f,0x00,0x02, + 0x00}} +#endif +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1XXXxXXX_1[] = +{ + {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05, + 0x00}}, + {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, + 0x01}}, + {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x02, + 0x01}}, + {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a, + 0x00,0x84,0xff,0x29,0x09,0x00,0x07, + 0x01}}, + {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x07, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_LVDSCRT1XXXxXXX_1_H[] = +{ + {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00, + 0x00}}, + {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00, + 0x00}}, + {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00, + 0x00}}, + {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00, + 0x00}}, + {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e, + 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00, + 0x00}}, + {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x01, + 0x01}}, + {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x01, + 0x01}} +}; + + +/* CRT1 CRTC for Chrontel TV slave modes */ + +static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1UNTSC[] = +{ + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01, + 0x00 }}, + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01, + 0x00 }}, + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01, + 0x00 }}, + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01, + 0x00 }}, + {{0x5d,0x4f,0x81,0x56,0x99,0x56,0xba, + 0x0a,0x84,0xdf,0x57,0x00,0x00,0x01, + 0x00 }}, + {{0x80,0x63,0x84,0x6d,0x0f,0xec,0xf0, + 0x7a,0x8f,0x57,0xed,0x20,0x00,0x06, + 0x01 }}, + {{0x8c,0x7f,0x90,0x86,0x09,0xaf,0xf5, + 0x36,0x88,0xff,0xb0,0x10,0x00,0x02, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1ONTSC[] = +{ + {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e, + 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e, + 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e, + 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01, + 0x00 }}, + {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e, + 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01, + 0x00 }}, + {{0x5d,0x4f,0x81,0x58,0x9d,0x0b,0x3e, + 0xe8,0x84,0xdf,0x0c,0x00,0x00,0x01, + 0x00 }}, + {{0x7d,0x63,0x81,0x68,0x0e,0xba,0xf0, + 0x78,0x8a,0x57,0xbb,0x20,0x00,0x06, + 0x01 }}, + {{0x8c,0x7f,0x90,0x82,0x06,0x46,0xf5, + 0x15,0x88,0xff,0x47,0x70,0x00,0x02, + 0x01 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1UPAL[] = +{ + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x64,0x4f,0x88,0x5a,0x9f,0x6f,0xba, + 0x15,0x83,0xdf,0x70,0x00,0x00,0x01, + 0x00 }}, + {{0x73,0x63,0x97,0x69,0x8b,0xec,0xf0, + 0x90,0x8c,0x57,0xed,0x20,0x00,0x05, + 0x01 }}, + {{0xaa,0x7f,0x8e,0x8e,0x96,0xe6,0xf5, + 0x50,0x88,0xff,0xe7,0x10,0x00,0x02, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS310_CHTVCRT1OPAL[] = +{ + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05, + 0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05, + 0x00 }}, + {{0x64,0x4f,0x88,0x58,0x9d,0x6f,0xba, + 0x15,0x83,0xdf,0x70,0x00,0x00,0x01, + 0x00 }}, + {{0x71,0x63,0x95,0x69,0x8c,0x6f,0xf0, + 0x5a,0x8b,0x57,0x70,0x20,0x00,0x05, + 0x01 }}, + {{0xaa,0x7f,0x8e,0x8f,0x96,0x69,0xf5, + 0x28,0x88,0xff,0x6a,0x10,0x00,0x02, + 0x01 }} +}; + + +static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] = +{ + {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x6a,0x77,0xbb,0x6e,0x84,0x2e,0x02,0x5a,0x04,0x00,0x80,0x20,0x7e,0x80,0x98,0x00}}, + {{0xcf,0x77,0xb7,0xc8,0x84,0x3b,0x02,0x5a,0x04,0x00,0x80,0x19,0x88,0x30,0x7f,0x00}}, + {{0xee,0x77,0xbb,0x66,0x87,0x32,0x01,0x5a,0x04,0x00,0x80,0x1b,0xd3,0xf2,0x36,0x00}} +}; /* WRONG: 0x02: should be 0xfx, because if CIVEnable is clear, this should be set; + 0x07: Blacklevel: NTSC/PAL-M: Should be 131 (0x83), and not 0x50/0x5a + PAL/PAL-N: 110 (0x6e) + NTSC-J: 102 (0x66) + 0x0c-0x0f: CIV is not default as in datasheet + MISSING: 0x21: Should set D1 to ZERO (for NTSC, PAL-M) or ONE (PAL, NTSC-J) + Most of this is wrong in all NTSC and PAL register arrays. But I won't correct + it as long as it works. For NTSC-J, the blacklevel is corrected in init301.c; + for PAL-M and PAL-N all above is corrected. + */ + +static const SiS_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] = +{ + {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x69,0x77,0xbb,0x6e,0x84,0x1e,0x00,0x5a,0x04,0x00,0x80,0x25,0x1a,0x43,0x04,0x00}}, + {{0xce,0x77,0xb7,0xb6,0x83,0x2c,0x02,0x5a,0x04,0x00,0x80,0x1c,0x00,0x82,0x97,0x00}}, + {{0xed,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x9f,0xc1,0x0c,0x00}} +}; + +static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] = +{ + {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x41,0x7f,0xb7,0x12,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x26,0x2a,0x55,0x5d,0x00}}, + {{0xc3,0x7f,0xb7,0x7a,0x84,0x40,0x02,0x5a,0x05,0x00,0x80,0x1f,0x84,0x3d,0x28,0x00}}, + {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x20,0x3e,0xe4,0x22,0x00}} +}; + +static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] = +{ + {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x26,0x2a,0x55,0x5d,0x00}}, + {{0xc1,0x7f,0xb7,0x4d,0x8c,0x1e,0x31,0x5a,0x05,0x00,0x80,0x26,0x78,0x19,0x34,0x00}}, + {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x25,0x8c,0xb2,0x2a,0x00}} +}; + +static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] = +{ + {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x72,0x77,0xfb,0x6e,0x84,0x2e,0x02,0x83,0x04,0x00,0x80,0x20,0x76,0xdb,0x6e,0x00}}, + {{0xd7,0x77,0xf7,0xc8,0x84,0x3b,0x02,0x83,0x04,0x00,0x80,0x19,0x84,0x0a,0xc7,0x00}}, + {{0xf6,0x77,0xfb,0x66,0x87,0x32,0x01,0x83,0x04,0x00,0x80,0x1b,0xdc,0xb0,0x8d,0x00}} +#if 0 /* Correct blacklevel and CFRB */ + {{0x72,0x77,0xbb,0x6e,0x84,0x2e,0x02,0x5a,0x04,0x00,0x80,0x20,0x76,0xdb,0x6e,0x00}}, + {{0xd7,0x77,0xb7,0xc8,0x84,0x3b,0x02,0x5a,0x04,0x00,0x80,0x19,0x84,0x0a,0xc7,0x00}}, + {{0xf6,0x77,0xbb,0x66,0x87,0x32,0x01,0x5a,0x04,0x00,0x80,0x1b,0xdc,0xb0,0x8d,0x00}} +#endif +}; + +static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] = +{ + {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x71,0x77,0xfb,0x6e,0x84,0x1e,0x00,0x83,0x04,0x00,0x80,0x25,0x1a,0x1f,0x59,0x00}}, + {{0xd6,0x77,0xf7,0xb6,0x83,0x2c,0x02,0x83,0x04,0x00,0x80,0x1b,0xf8,0x1f,0x82,0x00}}, + {{0xf5,0x77,0xfb,0x66,0x8c,0x21,0x02,0x83,0x04,0x00,0x80,0x1f,0x58,0x46,0x9f,0x00}} +#if 0 /* Correct blacklevel and CFRB */ + {{0x71,0x77,0xbb,0x6e,0x84,0x1e,0x00,0x5a,0x04,0x00,0x80,0x25,0x1a,0x1f,0x59,0x00}}, + {{0xd6,0x77,0xb7,0xb6,0x83,0x2c,0x02,0x5a,0x04,0x00,0x80,0x1b,0xf8,0x1f,0x82,0x00}}, + {{0xf5,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x58,0x46,0x9f,0x00}} +#endif +}; + +static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] = +{ + {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x41,0x7f,0xb7,0x12,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0xc3,0x7f,0xb7,0x7a,0x84,0x40,0x02,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}} +#if 0 /* Correct blacklevel, CIV and CFRB */ + {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x1f,0x0d,0x54,0x5e,0x00}}, + {{0xc3,0x7f,0xb7,0x7a,0x84,0x40,0x02,0x5a,0x05,0x00,0x80,0x19,0x78,0xef,0x35,0x00}}, + {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x1a,0x33,0x3f,0x2f,0x00}} +#endif +}; + +static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] = +{ + {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0xc1,0x7f,0xb7,0x4d,0x8c,0x1e,0x31,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}}, + {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}} +#if 0 /* Correct blacklevel, CIV and CFRB */ + {{0x61,0x7f,0xb7,0x99,0x84,0x35,0x04,0x5a,0x05,0x00,0x80,0x1f,0x0d,0x54,0x5e,0x00}}, + {{0xc1,0x7f,0xb7,0x4d,0x8c,0x1e,0x31,0x5a,0x05,0x00,0x80,0x1f,0x15,0xc0,0x1e,0x00}}, + {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x1d,0xf1,0x6c,0xcb,0x00}} +#endif +}; + +static const UCHAR SiS310_CHTVVCLKUNTSC[] = {0x41,0x41,0x41,0x41,0x42,0x46,0x53}; +static const UCHAR SiS310_CHTVVCLKONTSC[] = {0x48,0x48,0x48,0x48,0x45,0x43,0x51}; + +static const UCHAR SiS310_CHTVVCLKUPAL[] = {0x47,0x47,0x47,0x47,0x48,0x4a,0x54}; +static const UCHAR SiS310_CHTVVCLKOPAL[] = {0x47,0x47,0x47,0x47,0x48,0x4f,0x52}; + +static const UCHAR SiS310_CHTVVCLKUPALM[] = {0x41,0x41,0x41,0x41,0x42,0x46,0x53}; +static const UCHAR SiS310_CHTVVCLKOPALM[] = {0x48,0x48,0x48,0x48,0x45,0x43,0x51}; + +static const UCHAR SiS310_CHTVVCLKUPALN[] = {0x47,0x47,0x47,0x47,0x48,0x4a,0x54}; +static const UCHAR SiS310_CHTVVCLKOPALN[] = {0x47,0x47,0x47,0x47,0x48,0x4f,0x52}; + + diff --git a/drivers/video/sis/Makefile b/drivers/video/sis/Makefile new file mode 100644 index 000000000000..aaed8c2b4a64 --- /dev/null +++ b/drivers/video/sis/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the SiS framebuffer device driver +# + +obj-$(CONFIG_FB_SIS) += sisfb.o + +sisfb-objs := sis_main.o sis_accel.o init.o init301.o diff --git a/drivers/video/sis/init.c b/drivers/video/sis/init.c new file mode 100644 index 000000000000..1994054d45ff --- /dev/null +++ b/drivers/video/sis/init.c @@ -0,0 +1,5318 @@ +/* $XFree86$ */ +/* $XdotOrg$ */ +/* + * Mode initializing code (CRT1 section) for + * for SiS 300/305/540/630/730 and + * SiS 315/550/650/M650/651/661FX/M661FX/740/741(GX)/M741/330/660/M660/760/M760 + * (Universal module for Linux kernel framebuffer and XFree86 4.x) + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the named License, + * * or any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program; if not, write to the Free Software + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Otherwise, the following license terms apply: + * + * * Redistribution and use in source and binary forms, with or without + * * modification, are permitted provided that the following conditions + * * are met: + * * 1) Redistributions of source code must retain the above copyright + * * notice, this list of conditions and the following disclaimer. + * * 2) Redistributions in binary form must reproduce the above copyright + * * notice, this list of conditions and the following disclaimer in the + * * documentation and/or other materials provided with the distribution. + * * 3) The name of the author may not be used to endorse or promote products + * * derived from this software without specific prior written permission. + * * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + * Formerly based on non-functional code-fragements for 300 series by SiS, Inc. + * Used by permission. + * + * TW says: This code looks awful, I know. But please don't do anything about + * this otherwise debugging will be hell. + * The code is extremely fragile as regards the different chipsets, different + * video bridges and combinations thereof. If anything is changed, extreme + * care has to be taken that that change doesn't break it for other chipsets, + * bridges or combinations thereof. + * All comments in this file are by me, regardless if they are marked TW or not. + * + */ + +#include "init.h" + +#ifdef SIS300 +#include "300vtbl.h" +#endif + +#ifdef SIS315H +#include "310vtbl.h" +#endif + +#if defined(ALLOC_PRAGMA) +#pragma alloc_text(PAGE,SiSSetMode) +#endif + +/*********************************************/ +/* POINTER INITIALIZATION */ +/*********************************************/ + +#if defined(SIS300) || defined(SIS315H) +static void +InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + SiS_Pr->SiS_StResInfo = SiS_StResInfo; + SiS_Pr->SiS_ModeResInfo = SiS_ModeResInfo; + SiS_Pr->SiS_StandTable = SiS_StandTable; + + SiS_Pr->SiS_NTSCPhase = SiS_NTSCPhase; + SiS_Pr->SiS_PALPhase = SiS_PALPhase; + SiS_Pr->SiS_NTSCPhase2 = SiS_NTSCPhase2; + SiS_Pr->SiS_PALPhase2 = SiS_PALPhase2; + SiS_Pr->SiS_PALMPhase = SiS_PALMPhase; + SiS_Pr->SiS_PALNPhase = SiS_PALNPhase; + SiS_Pr->SiS_PALMPhase2 = SiS_PALMPhase2; + SiS_Pr->SiS_PALNPhase2 = SiS_PALNPhase2; + SiS_Pr->SiS_SpecialPhase = SiS_SpecialPhase; + SiS_Pr->SiS_SpecialPhaseM = SiS_SpecialPhaseM; + SiS_Pr->SiS_SpecialPhaseJ = SiS_SpecialPhaseJ; + + SiS_Pr->SiS_NTSCTiming = SiS_NTSCTiming; + SiS_Pr->SiS_PALTiming = SiS_PALTiming; + SiS_Pr->SiS_HiTVSt1Timing = SiS_HiTVSt1Timing; + SiS_Pr->SiS_HiTVSt2Timing = SiS_HiTVSt2Timing; + + SiS_Pr->SiS_HiTVExtTiming = SiS_HiTVExtTiming; + SiS_Pr->SiS_HiTVGroup3Data = SiS_HiTVGroup3Data; + SiS_Pr->SiS_HiTVGroup3Simu = SiS_HiTVGroup3Simu; +#if 0 + SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming; + SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text; +#endif + + SiS_Pr->SiS_StPALData = SiS_StPALData; + SiS_Pr->SiS_ExtPALData = SiS_ExtPALData; + SiS_Pr->SiS_StNTSCData = SiS_StNTSCData; + SiS_Pr->SiS_ExtNTSCData = SiS_ExtNTSCData; + SiS_Pr->SiS_St1HiTVData = SiS_StHiTVData; + SiS_Pr->SiS_St2HiTVData = SiS_St2HiTVData; + SiS_Pr->SiS_ExtHiTVData = SiS_ExtHiTVData; + SiS_Pr->SiS_St525iData = SiS_StNTSCData; + SiS_Pr->SiS_St525pData = SiS_St525pData; + SiS_Pr->SiS_St750pData = SiS_St750pData; + SiS_Pr->SiS_Ext525iData = SiS_ExtNTSCData; + SiS_Pr->SiS_Ext525pData = SiS_ExtNTSCData; + SiS_Pr->SiS_Ext750pData = SiS_Ext750pData; + + SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect; + SiS_Pr->pSiS_SoftSetting = &SiS_SoftSetting; + + SiS_Pr->SiS_LCD1280x720Data = SiS_LCD1280x720Data; + SiS_Pr->SiS_StLCD1280x768_2Data = SiS_StLCD1280x768_2Data; + SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data; + SiS_Pr->SiS_LCD1280x800Data = SiS_LCD1280x800Data; + SiS_Pr->SiS_LCD1280x800_2Data = SiS_LCD1280x800_2Data; + SiS_Pr->SiS_LCD1280x960Data = SiS_LCD1280x960Data; + SiS_Pr->SiS_StLCD1400x1050Data = SiS_StLCD1400x1050Data; + SiS_Pr->SiS_ExtLCD1400x1050Data = SiS_ExtLCD1400x1050Data; + SiS_Pr->SiS_LCD1680x1050Data = SiS_LCD1680x1050Data; + SiS_Pr->SiS_StLCD1600x1200Data = SiS_StLCD1600x1200Data; + SiS_Pr->SiS_ExtLCD1600x1200Data = SiS_ExtLCD1600x1200Data; + SiS_Pr->SiS_NoScaleData = SiS_NoScaleData; + + SiS_Pr->SiS_LVDS320x480Data_1 = SiS_LVDS320x480Data_1; + SiS_Pr->SiS_LVDS800x600Data_1 = SiS_LVDS800x600Data_1; + SiS_Pr->SiS_LVDS800x600Data_2 = SiS_LVDS800x600Data_2; + SiS_Pr->SiS_LVDS1024x768Data_1 = SiS_LVDS1024x768Data_1; + SiS_Pr->SiS_LVDS1024x768Data_2 = SiS_LVDS1024x768Data_2; + SiS_Pr->SiS_LVDS1280x1024Data_1 = SiS_LVDS1280x1024Data_1; + SiS_Pr->SiS_LVDS1280x1024Data_2 = SiS_LVDS1280x1024Data_2; + SiS_Pr->SiS_LVDS1400x1050Data_1 = SiS_LVDS1400x1050Data_1; + SiS_Pr->SiS_LVDS1400x1050Data_2 = SiS_LVDS1400x1050Data_2; + SiS_Pr->SiS_LVDS1600x1200Data_1 = SiS_LVDS1600x1200Data_1; + SiS_Pr->SiS_LVDS1600x1200Data_2 = SiS_LVDS1600x1200Data_2; + SiS_Pr->SiS_LVDS1280x768Data_1 = SiS_LVDS1280x768Data_1; + SiS_Pr->SiS_LVDS1280x768Data_2 = SiS_LVDS1280x768Data_2; + SiS_Pr->SiS_LVDS1024x600Data_1 = SiS_LVDS1024x600Data_1; + SiS_Pr->SiS_LVDS1024x600Data_2 = SiS_LVDS1024x600Data_2; + SiS_Pr->SiS_LVDS1152x768Data_1 = SiS_LVDS1152x768Data_1; + SiS_Pr->SiS_LVDS1152x768Data_2 = SiS_LVDS1152x768Data_2; + SiS_Pr->SiS_LVDSXXXxXXXData_1 = SiS_LVDSXXXxXXXData_1; + SiS_Pr->SiS_LVDS1280x960Data_1 = SiS_LVDS1280x960Data_1; + SiS_Pr->SiS_LVDS1280x960Data_2 = SiS_LVDS1280x960Data_2; + SiS_Pr->SiS_LVDS640x480Data_1 = SiS_LVDS640x480Data_1; + SiS_Pr->SiS_LVDS1280x960Data_1 = SiS_LVDS1280x1024Data_1; + SiS_Pr->SiS_LVDS1280x960Data_2 = SiS_LVDS1280x1024Data_2; + SiS_Pr->SiS_LVDS640x480Data_1 = SiS_LVDS640x480Data_1; + SiS_Pr->SiS_LVDS640x480Data_2 = SiS_LVDS640x480Data_2; + + SiS_Pr->SiS_LVDS848x480Data_1 = SiS_LVDS848x480Data_1; + SiS_Pr->SiS_LVDS848x480Data_2 = SiS_LVDS848x480Data_2; + SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS_LVDSBARCO1024Data_1; + SiS_Pr->SiS_LVDSBARCO1024Data_2 = SiS_LVDSBARCO1024Data_2; + SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS_LVDSBARCO1366Data_1; + SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS_LVDSBARCO1366Data_2; + + SiS_Pr->SiS_LVDSCRT11280x768_1 = SiS_LVDSCRT11280x768_1; + SiS_Pr->SiS_LVDSCRT11024x600_1 = SiS_LVDSCRT11024x600_1; + SiS_Pr->SiS_LVDSCRT11152x768_1 = SiS_LVDSCRT11152x768_1; + SiS_Pr->SiS_LVDSCRT11280x768_1_H = SiS_LVDSCRT11280x768_1_H; + SiS_Pr->SiS_LVDSCRT11024x600_1_H = SiS_LVDSCRT11024x600_1_H; + SiS_Pr->SiS_LVDSCRT11152x768_1_H = SiS_LVDSCRT11152x768_1_H; + SiS_Pr->SiS_LVDSCRT11280x768_2 = SiS_LVDSCRT11280x768_2; + SiS_Pr->SiS_LVDSCRT11024x600_2 = SiS_LVDSCRT11024x600_2; + SiS_Pr->SiS_LVDSCRT11152x768_2 = SiS_LVDSCRT11152x768_2; + SiS_Pr->SiS_LVDSCRT11280x768_2_H = SiS_LVDSCRT11280x768_2_H; + SiS_Pr->SiS_LVDSCRT11024x600_2_H = SiS_LVDSCRT11024x600_2_H; + SiS_Pr->SiS_LVDSCRT11152x768_2_H = SiS_LVDSCRT11152x768_2_H; + SiS_Pr->SiS_LVDSCRT1320x480_1 = SiS_LVDSCRT1320x480_1; + SiS_Pr->SiS_LVDSCRT1640x480_1 = SiS_LVDSCRT1640x480_1; + SiS_Pr->SiS_LVDSCRT1640x480_1_H = SiS_LVDSCRT1640x480_1_H; + SiS_Pr->SiS_LVDSCRT1640x480_2 = SiS_LVDSCRT1640x480_2; + SiS_Pr->SiS_LVDSCRT1640x480_2_H = SiS_LVDSCRT1640x480_2_H; + SiS_Pr->SiS_LVDSCRT1640x480_3 = SiS_LVDSCRT1640x480_3; + SiS_Pr->SiS_LVDSCRT1640x480_3_H = SiS_LVDSCRT1640x480_3_H; + + SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData; + SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData; + + SiS_Pr->SiS_CHTVUNTSCDesData = SiS_CHTVUNTSCDesData; + SiS_Pr->SiS_CHTVONTSCDesData = SiS_CHTVONTSCDesData; + SiS_Pr->SiS_CHTVUPALDesData = SiS_CHTVUPALDesData; + SiS_Pr->SiS_CHTVOPALDesData = SiS_CHTVOPALDesData; + + SiS_Pr->SiS_PanelMinLVDS = Panel_800x600; /* lowest value LVDS/LCDA */ + SiS_Pr->SiS_PanelMin301 = Panel_1024x768; /* lowest value 301 */ +} +#endif + +#ifdef SIS300 +static void +InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + InitCommonPointer(SiS_Pr, HwInfo); + + SiS_Pr->SiS_SModeIDTable = SiS300_SModeIDTable; + SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable; + SiS_Pr->SiS_EModeIDTable = SiS300_EModeIDTable; + SiS_Pr->SiS_RefIndex = SiS300_RefIndex; + SiS_Pr->SiS_CRT1Table = SiS300_CRT1Table; + if(HwInfo->jChipType == SIS_300) { + SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_300; /* 300 */ + } else { + SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_630; /* 630, 730 */ + } + SiS_Pr->SiS_VCLKData = SiS300_VCLKData; + SiS_Pr->SiS_VBVCLKData = (SiS_VBVCLKDataStruct *)SiS300_VCLKData; + + SiS_Pr->SiS_SR15 = SiS300_SR15; + +#ifdef LINUX_KERNEL + SiS_Pr->pSiS_SR07 = &SiS300_SR07; + SiS_Pr->SiS_CR40 = SiS300_CR40; + SiS_Pr->SiS_CR49 = SiS300_CR49; + SiS_Pr->pSiS_SR1F = &SiS300_SR1F; + SiS_Pr->pSiS_SR21 = &SiS300_SR21; + SiS_Pr->pSiS_SR22 = &SiS300_SR22; + SiS_Pr->pSiS_SR23 = &SiS300_SR23; + SiS_Pr->pSiS_SR24 = &SiS300_SR24; + SiS_Pr->SiS_SR25 = SiS300_SR25; + SiS_Pr->pSiS_SR31 = &SiS300_SR31; + SiS_Pr->pSiS_SR32 = &SiS300_SR32; + SiS_Pr->pSiS_SR33 = &SiS300_SR33; + SiS_Pr->pSiS_CRT2Data_1_2 = &SiS300_CRT2Data_1_2; + SiS_Pr->pSiS_CRT2Data_4_D = &SiS300_CRT2Data_4_D; + SiS_Pr->pSiS_CRT2Data_4_E = &SiS300_CRT2Data_4_E; + SiS_Pr->pSiS_CRT2Data_4_10 = &SiS300_CRT2Data_4_10; + SiS_Pr->pSiS_RGBSenseData = &SiS300_RGBSenseData; + SiS_Pr->pSiS_VideoSenseData = &SiS300_VideoSenseData; + SiS_Pr->pSiS_YCSenseData = &SiS300_YCSenseData; + SiS_Pr->pSiS_RGBSenseData2 = &SiS300_RGBSenseData2; + SiS_Pr->pSiS_VideoSenseData2 = &SiS300_VideoSenseData2; + SiS_Pr->pSiS_YCSenseData2 = &SiS300_YCSenseData2; +#endif + + SiS_Pr->SiS_PanelDelayTbl = SiS300_PanelDelayTbl; + SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl; + + SiS_Pr->SiS_ExtLCD1024x768Data = SiS300_ExtLCD1024x768Data; + SiS_Pr->SiS_St2LCD1024x768Data = SiS300_St2LCD1024x768Data; + SiS_Pr->SiS_ExtLCD1280x1024Data = SiS300_ExtLCD1280x1024Data; + SiS_Pr->SiS_St2LCD1280x1024Data = SiS300_St2LCD1280x1024Data; + + SiS_Pr->SiS_CRT2Part2_1024x768_1 = SiS300_CRT2Part2_1024x768_1; + SiS_Pr->SiS_CRT2Part2_1280x1024_1 = SiS300_CRT2Part2_1280x1024_1; + SiS_Pr->SiS_CRT2Part2_1024x768_2 = SiS300_CRT2Part2_1024x768_2; + SiS_Pr->SiS_CRT2Part2_1280x1024_2 = SiS300_CRT2Part2_1280x1024_2; + SiS_Pr->SiS_CRT2Part2_1024x768_3 = SiS300_CRT2Part2_1024x768_3; + SiS_Pr->SiS_CRT2Part2_1280x1024_3 = SiS300_CRT2Part2_1280x1024_3; + + SiS_Pr->SiS_CHTVUPALData = SiS300_CHTVUPALData; + SiS_Pr->SiS_CHTVOPALData = SiS300_CHTVOPALData; + SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVUPALNData = SiS300_CHTVUPALData; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData; + + SiS_Pr->SiS_PanelType00_1 = SiS300_PanelType00_1; + SiS_Pr->SiS_PanelType01_1 = SiS300_PanelType01_1; + SiS_Pr->SiS_PanelType02_1 = SiS300_PanelType02_1; + SiS_Pr->SiS_PanelType03_1 = SiS300_PanelType03_1; + SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1; + SiS_Pr->SiS_PanelType05_1 = SiS300_PanelType05_1; + SiS_Pr->SiS_PanelType06_1 = SiS300_PanelType06_1; + SiS_Pr->SiS_PanelType07_1 = SiS300_PanelType07_1; + SiS_Pr->SiS_PanelType08_1 = SiS300_PanelType08_1; + SiS_Pr->SiS_PanelType09_1 = SiS300_PanelType09_1; + SiS_Pr->SiS_PanelType0a_1 = SiS300_PanelType0a_1; + SiS_Pr->SiS_PanelType0b_1 = SiS300_PanelType0b_1; + SiS_Pr->SiS_PanelType0c_1 = SiS300_PanelType0c_1; + SiS_Pr->SiS_PanelType0d_1 = SiS300_PanelType0d_1; + SiS_Pr->SiS_PanelType0e_1 = SiS300_PanelType0e_1; + SiS_Pr->SiS_PanelType0f_1 = SiS300_PanelType0f_1; + SiS_Pr->SiS_PanelType00_2 = SiS300_PanelType00_2; + SiS_Pr->SiS_PanelType01_2 = SiS300_PanelType01_2; + SiS_Pr->SiS_PanelType02_2 = SiS300_PanelType02_2; + SiS_Pr->SiS_PanelType03_2 = SiS300_PanelType03_2; + SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2; + SiS_Pr->SiS_PanelType05_2 = SiS300_PanelType05_2; + SiS_Pr->SiS_PanelType06_2 = SiS300_PanelType06_2; + SiS_Pr->SiS_PanelType07_2 = SiS300_PanelType07_2; + SiS_Pr->SiS_PanelType08_2 = SiS300_PanelType08_2; + SiS_Pr->SiS_PanelType09_2 = SiS300_PanelType09_2; + SiS_Pr->SiS_PanelType0a_2 = SiS300_PanelType0a_2; + SiS_Pr->SiS_PanelType0b_2 = SiS300_PanelType0b_2; + SiS_Pr->SiS_PanelType0c_2 = SiS300_PanelType0c_2; + SiS_Pr->SiS_PanelType0d_2 = SiS300_PanelType0d_2; + SiS_Pr->SiS_PanelType0e_2 = SiS300_PanelType0e_2; + SiS_Pr->SiS_PanelType0f_2 = SiS300_PanelType0f_2; + SiS_Pr->SiS_PanelTypeNS_1 = SiS300_PanelTypeNS_1; + SiS_Pr->SiS_PanelTypeNS_2 = SiS300_PanelTypeNS_2; + + if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) { + SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1a; + SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2a; + } + if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) { + SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1b; + SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2b; + } + + SiS_Pr->SiS_LVDSCRT1800x600_1 = SiS300_LVDSCRT1800x600_1; + SiS_Pr->SiS_LVDSCRT1800x600_1_H = SiS300_LVDSCRT1800x600_1_H; + SiS_Pr->SiS_LVDSCRT1800x600_2 = SiS300_LVDSCRT1800x600_2; + SiS_Pr->SiS_LVDSCRT1800x600_2_H = SiS300_LVDSCRT1800x600_2_H; + SiS_Pr->SiS_LVDSCRT11024x768_1 = SiS300_LVDSCRT11024x768_1; + SiS_Pr->SiS_LVDSCRT11024x768_1_H = SiS300_LVDSCRT11024x768_1_H; + SiS_Pr->SiS_LVDSCRT11024x768_2 = SiS300_LVDSCRT11024x768_2; + SiS_Pr->SiS_LVDSCRT11024x768_2_H = SiS300_LVDSCRT11024x768_2_H; + SiS_Pr->SiS_LVDSCRT11280x1024_1 = SiS300_LVDSCRT11280x1024_1; + SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS300_LVDSCRT11280x1024_1_H; + SiS_Pr->SiS_LVDSCRT11280x1024_2 = SiS300_LVDSCRT11280x1024_2; + SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS300_LVDSCRT11280x1024_2_H; + SiS_Pr->SiS_LVDSCRT1XXXxXXX_1 = SiS300_LVDSCRT1XXXxXXX_1; + SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H = SiS300_LVDSCRT1XXXxXXX_1_H; + + SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC; + SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC; + SiS_Pr->SiS_CHTVCRT1UPAL = SiS300_CHTVCRT1UPAL; + SiS_Pr->SiS_CHTVCRT1OPAL = SiS300_CHTVCRT1OPAL; + SiS_Pr->SiS_CHTVCRT1SOPAL = SiS300_CHTVCRT1SOPAL; + SiS_Pr->SiS_CHTVReg_UNTSC = SiS300_CHTVReg_UNTSC; + SiS_Pr->SiS_CHTVReg_ONTSC = SiS300_CHTVReg_ONTSC; + SiS_Pr->SiS_CHTVReg_UPAL = SiS300_CHTVReg_UPAL; + SiS_Pr->SiS_CHTVReg_OPAL = SiS300_CHTVReg_OPAL; + SiS_Pr->SiS_CHTVReg_UPALM = SiS300_CHTVReg_UNTSC; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVReg_OPALM = SiS300_CHTVReg_ONTSC; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVReg_UPALN = SiS300_CHTVReg_UPAL; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVReg_OPALN = SiS300_CHTVReg_OPAL; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVReg_SOPAL = SiS300_CHTVReg_SOPAL; + SiS_Pr->SiS_CHTVVCLKUNTSC = SiS300_CHTVVCLKUNTSC; + SiS_Pr->SiS_CHTVVCLKONTSC = SiS300_CHTVVCLKONTSC; + SiS_Pr->SiS_CHTVVCLKUPAL = SiS300_CHTVVCLKUPAL; + SiS_Pr->SiS_CHTVVCLKOPAL = SiS300_CHTVVCLKOPAL; + SiS_Pr->SiS_CHTVVCLKUPALM = SiS300_CHTVVCLKUNTSC; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVVCLKOPALM = SiS300_CHTVVCLKONTSC; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVVCLKUPALN = SiS300_CHTVVCLKUPAL; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL; +} +#endif + +#ifdef SIS315H +static void +InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + InitCommonPointer(SiS_Pr, HwInfo); + + SiS_Pr->SiS_SModeIDTable = SiS310_SModeIDTable; + SiS_Pr->SiS_EModeIDTable = SiS310_EModeIDTable; + SiS_Pr->SiS_RefIndex = (SiS_Ext2Struct *)SiS310_RefIndex; + SiS_Pr->SiS_CRT1Table = SiS310_CRT1Table; + if(HwInfo->jChipType >= SIS_340) { + SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340; /* 340 */ + } else if(HwInfo->jChipType >= SIS_761) { + SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_761; /* 761 - preliminary */ + } else if(HwInfo->jChipType >= SIS_760) { + SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760; /* 760 */ + } else if(HwInfo->jChipType >= SIS_661) { + SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660; /* 661/741 */ + } else if(HwInfo->jChipType == SIS_330) { + SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330; /* 330 */ + } else if(HwInfo->jChipType > SIS_315PRO) { + SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650; /* 550, 650, 740 */ + } else { + SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315; /* 315 */ + } + if(HwInfo->jChipType >= SIS_340) { + SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1_340; + } else { + SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1; + } + SiS_Pr->SiS_VCLKData = SiS310_VCLKData; + SiS_Pr->SiS_VBVCLKData = SiS310_VBVCLKData; + + SiS_Pr->SiS_SR15 = SiS310_SR15; + +#ifdef LINUX_KERNEL + SiS_Pr->pSiS_SR07 = &SiS310_SR07; + SiS_Pr->SiS_CR40 = SiS310_CR40; + SiS_Pr->SiS_CR49 = SiS310_CR49; + SiS_Pr->pSiS_SR1F = &SiS310_SR1F; + SiS_Pr->pSiS_SR21 = &SiS310_SR21; + SiS_Pr->pSiS_SR22 = &SiS310_SR22; + SiS_Pr->pSiS_SR23 = &SiS310_SR23; + SiS_Pr->pSiS_SR24 = &SiS310_SR24; + SiS_Pr->SiS_SR25 = SiS310_SR25; + SiS_Pr->pSiS_SR31 = &SiS310_SR31; + SiS_Pr->pSiS_SR32 = &SiS310_SR32; + SiS_Pr->pSiS_SR33 = &SiS310_SR33; + SiS_Pr->pSiS_CRT2Data_1_2 = &SiS310_CRT2Data_1_2; + SiS_Pr->pSiS_CRT2Data_4_D = &SiS310_CRT2Data_4_D; + SiS_Pr->pSiS_CRT2Data_4_E = &SiS310_CRT2Data_4_E; + SiS_Pr->pSiS_CRT2Data_4_10 = &SiS310_CRT2Data_4_10; + SiS_Pr->pSiS_RGBSenseData = &SiS310_RGBSenseData; + SiS_Pr->pSiS_VideoSenseData = &SiS310_VideoSenseData; + SiS_Pr->pSiS_YCSenseData = &SiS310_YCSenseData; + SiS_Pr->pSiS_RGBSenseData2 = &SiS310_RGBSenseData2; + SiS_Pr->pSiS_VideoSenseData2 = &SiS310_VideoSenseData2; + SiS_Pr->pSiS_YCSenseData2 = &SiS310_YCSenseData2; +#endif + + SiS_Pr->SiS_PanelDelayTbl = SiS310_PanelDelayTbl; + SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS; + + SiS_Pr->SiS_St2LCD1024x768Data = SiS310_St2LCD1024x768Data; + SiS_Pr->SiS_ExtLCD1024x768Data = SiS310_ExtLCD1024x768Data; + SiS_Pr->SiS_St2LCD1280x1024Data = SiS310_St2LCD1280x1024Data; + SiS_Pr->SiS_ExtLCD1280x1024Data = SiS310_ExtLCD1280x1024Data; + + SiS_Pr->SiS_CRT2Part2_1024x768_1 = SiS310_CRT2Part2_1024x768_1; + + SiS_Pr->SiS_PanelType00_1 = SiS310_PanelType00_1; + SiS_Pr->SiS_PanelType01_1 = SiS310_PanelType01_1; + SiS_Pr->SiS_PanelType02_1 = SiS310_PanelType02_1; + SiS_Pr->SiS_PanelType03_1 = SiS310_PanelType03_1; + SiS_Pr->SiS_PanelType04_1 = SiS310_PanelType04_1; + SiS_Pr->SiS_PanelType05_1 = SiS310_PanelType05_1; + SiS_Pr->SiS_PanelType06_1 = SiS310_PanelType06_1; + SiS_Pr->SiS_PanelType07_1 = SiS310_PanelType07_1; + SiS_Pr->SiS_PanelType08_1 = SiS310_PanelType08_1; + SiS_Pr->SiS_PanelType09_1 = SiS310_PanelType09_1; + SiS_Pr->SiS_PanelType0a_1 = SiS310_PanelType0a_1; + SiS_Pr->SiS_PanelType0b_1 = SiS310_PanelType0b_1; + SiS_Pr->SiS_PanelType0c_1 = SiS310_PanelType0c_1; + SiS_Pr->SiS_PanelType0d_1 = SiS310_PanelType0d_1; + SiS_Pr->SiS_PanelType0e_1 = SiS310_PanelType0e_1; + SiS_Pr->SiS_PanelType0f_1 = SiS310_PanelType0f_1; + SiS_Pr->SiS_PanelType00_2 = SiS310_PanelType00_2; + SiS_Pr->SiS_PanelType01_2 = SiS310_PanelType01_2; + SiS_Pr->SiS_PanelType02_2 = SiS310_PanelType02_2; + SiS_Pr->SiS_PanelType03_2 = SiS310_PanelType03_2; + SiS_Pr->SiS_PanelType04_2 = SiS310_PanelType04_2; + SiS_Pr->SiS_PanelType05_2 = SiS310_PanelType05_2; + SiS_Pr->SiS_PanelType06_2 = SiS310_PanelType06_2; + SiS_Pr->SiS_PanelType07_2 = SiS310_PanelType07_2; + SiS_Pr->SiS_PanelType08_2 = SiS310_PanelType08_2; + SiS_Pr->SiS_PanelType09_2 = SiS310_PanelType09_2; + SiS_Pr->SiS_PanelType0a_2 = SiS310_PanelType0a_2; + SiS_Pr->SiS_PanelType0b_2 = SiS310_PanelType0b_2; + SiS_Pr->SiS_PanelType0c_2 = SiS310_PanelType0c_2; + SiS_Pr->SiS_PanelType0d_2 = SiS310_PanelType0d_2; + SiS_Pr->SiS_PanelType0e_2 = SiS310_PanelType0e_2; + SiS_Pr->SiS_PanelType0f_2 = SiS310_PanelType0f_2; + SiS_Pr->SiS_PanelTypeNS_1 = SiS310_PanelTypeNS_1; + SiS_Pr->SiS_PanelTypeNS_2 = SiS310_PanelTypeNS_2; + + SiS_Pr->SiS_CHTVUPALData = SiS310_CHTVUPALData; + SiS_Pr->SiS_CHTVOPALData = SiS310_CHTVOPALData; + SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData; + SiS_Pr->SiS_CHTVOPALMData = SiS310_CHTVOPALMData; + SiS_Pr->SiS_CHTVUPALNData = SiS310_CHTVUPALNData; + SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData; + SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData; + + SiS_Pr->SiS_LVDSCRT1800x600_1 = SiS310_LVDSCRT1800x600_1; + SiS_Pr->SiS_LVDSCRT11024x768_1 = SiS310_LVDSCRT11024x768_1; + SiS_Pr->SiS_LVDSCRT11280x1024_1 = SiS310_LVDSCRT11280x1024_1; + SiS_Pr->SiS_LVDSCRT11400x1050_1 = SiS310_LVDSCRT11400x1050_1; + SiS_Pr->SiS_LVDSCRT11600x1200_1 = SiS310_LVDSCRT11600x1200_1; + SiS_Pr->SiS_LVDSCRT1800x600_1_H = SiS310_LVDSCRT1800x600_1_H; + SiS_Pr->SiS_LVDSCRT11024x768_1_H = SiS310_LVDSCRT11024x768_1_H; + SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS310_LVDSCRT11280x1024_1_H; + SiS_Pr->SiS_LVDSCRT11400x1050_1_H = SiS310_LVDSCRT11400x1050_1_H; + SiS_Pr->SiS_LVDSCRT11600x1200_1_H = SiS310_LVDSCRT11600x1200_1_H; + SiS_Pr->SiS_LVDSCRT1800x600_2 = SiS310_LVDSCRT1800x600_2; + SiS_Pr->SiS_LVDSCRT11024x768_2 = SiS310_LVDSCRT11024x768_2; + SiS_Pr->SiS_LVDSCRT11280x1024_2 = SiS310_LVDSCRT11280x1024_2; + SiS_Pr->SiS_LVDSCRT11400x1050_2 = SiS310_LVDSCRT11400x1050_2; + SiS_Pr->SiS_LVDSCRT11600x1200_2 = SiS310_LVDSCRT11600x1200_2; + SiS_Pr->SiS_LVDSCRT1800x600_2_H = SiS310_LVDSCRT1800x600_2_H; + SiS_Pr->SiS_LVDSCRT11024x768_2_H = SiS310_LVDSCRT11024x768_2_H; + SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS310_LVDSCRT11280x1024_2_H; + SiS_Pr->SiS_LVDSCRT11400x1050_2_H = SiS310_LVDSCRT11400x1050_2_H; + SiS_Pr->SiS_LVDSCRT11600x1200_2_H = SiS310_LVDSCRT11600x1200_2_H; + SiS_Pr->SiS_LVDSCRT1XXXxXXX_1 = SiS310_LVDSCRT1XXXxXXX_1; + SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H = SiS310_LVDSCRT1XXXxXXX_1_H; + SiS_Pr->SiS_CHTVCRT1UNTSC = SiS310_CHTVCRT1UNTSC; + SiS_Pr->SiS_CHTVCRT1ONTSC = SiS310_CHTVCRT1ONTSC; + SiS_Pr->SiS_CHTVCRT1UPAL = SiS310_CHTVCRT1UPAL; + SiS_Pr->SiS_CHTVCRT1OPAL = SiS310_CHTVCRT1OPAL; + SiS_Pr->SiS_CHTVCRT1SOPAL = SiS310_CHTVCRT1OPAL; + + SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC; + SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC; + SiS_Pr->SiS_CHTVReg_UPAL = SiS310_CHTVReg_UPAL; + SiS_Pr->SiS_CHTVReg_OPAL = SiS310_CHTVReg_OPAL; + SiS_Pr->SiS_CHTVReg_UPALM = SiS310_CHTVReg_UPALM; + SiS_Pr->SiS_CHTVReg_OPALM = SiS310_CHTVReg_OPALM; + SiS_Pr->SiS_CHTVReg_UPALN = SiS310_CHTVReg_UPALN; + SiS_Pr->SiS_CHTVReg_OPALN = SiS310_CHTVReg_OPALN; + SiS_Pr->SiS_CHTVReg_SOPAL = SiS310_CHTVReg_OPAL; + + SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC; + SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC; + SiS_Pr->SiS_CHTVVCLKUPAL = SiS310_CHTVVCLKUPAL; + SiS_Pr->SiS_CHTVVCLKOPAL = SiS310_CHTVVCLKOPAL; + SiS_Pr->SiS_CHTVVCLKUPALM = SiS310_CHTVVCLKUPALM; + SiS_Pr->SiS_CHTVVCLKOPALM = SiS310_CHTVVCLKOPALM; + SiS_Pr->SiS_CHTVVCLKUPALN = SiS310_CHTVVCLKUPALN; + SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN; + SiS_Pr->SiS_CHTVVCLKSOPAL = SiS310_CHTVVCLKOPAL; +} +#endif + +static void +SiSInitPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + switch(HwInfo->jChipType) { +#ifdef SIS315H + case SIS_315H: + case SIS_315: + case SIS_315PRO: + case SIS_550: + case SIS_650: + case SIS_740: + case SIS_330: + case SIS_661: + case SIS_741: + case SIS_660: + case SIS_760: + case SIS_761: + case SIS_340: + InitTo310Pointer(SiS_Pr, HwInfo); + break; +#endif +#ifdef SIS300 + case SIS_300: + case SIS_540: + case SIS_630: + case SIS_730: + InitTo300Pointer(SiS_Pr, HwInfo); + break; +#endif + default: + break; + } +} + +/*********************************************/ +/* HELPER: Get ModeID */ +/*********************************************/ + +#ifdef LINUX_XF86 +USHORT +SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, + int Depth, BOOLEAN FSTN, int LCDwidth, int LCDheight) +{ + USHORT ModeIndex = 0; + + switch(HDisplay) + { + case 320: + if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth]; + else if(VDisplay == 240) { + if(FSTN) ModeIndex = ModeIndex_320x240_FSTN[Depth]; + else ModeIndex = ModeIndex_320x240[Depth]; + } + break; + case 400: + if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) { + if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth]; + } + break; + case 512: + if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 768))) { + if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth]; + } + break; + case 640: + if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth]; + else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth]; + break; + case 720: + if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth]; + else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth]; + break; + case 768: + if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth]; + break; + case 800: + if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth]; + else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth]; + break; + case 848: + if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth]; + break; + case 856: + if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth]; + break; + case 960: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth]; + else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth]; + } + break; + case 1024: + if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth]; + else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth]; + else if(VGAEngine == SIS_300_VGA) { + if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth]; + } + break; + case 1152: + if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth]; + if(VGAEngine == SIS_300_VGA) { + if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth]; + } + break; + case 1280: + switch(VDisplay) { + case 720: + ModeIndex = ModeIndex_1280x720[Depth]; + break; + case 768: + if(VGAEngine == SIS_300_VGA) { + ModeIndex = ModeIndex_300_1280x768[Depth]; + } else { + ModeIndex = ModeIndex_310_1280x768[Depth]; + } + break; + case 800: + if(VGAEngine == SIS_315_VGA) { + ModeIndex = ModeIndex_1280x800[Depth]; + } + break; + case 960: + ModeIndex = ModeIndex_1280x960[Depth]; + break; + case 1024: + ModeIndex = ModeIndex_1280x1024[Depth]; + break; + } + break; + case 1360: + if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth]; + if(VGAEngine == SIS_300_VGA) { + if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth]; + } + break; + case 1400: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 1050) { + ModeIndex = ModeIndex_1400x1050[Depth]; + } + } + break; + case 1600: + if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth]; + break; + case 1680: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth]; + } + break; + case 1920: + if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth]; + else if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth]; + } + break; + case 2048: + if(VDisplay == 1536) { + if(VGAEngine == SIS_300_VGA) { + ModeIndex = ModeIndex_300_2048x1536[Depth]; + } else { + ModeIndex = ModeIndex_310_2048x1536[Depth]; + } + } + break; + } + + return(ModeIndex); +} +#endif + +USHORT +SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, + int Depth, BOOLEAN FSTN, USHORT CustomT, int LCDwidth, int LCDheight) +{ + USHORT ModeIndex = 0; + + if(VBFlags & (VB_LVDS | VB_30xBDH)) { + + switch(HDisplay) + { + case 320: + if(CustomT != CUT_PANEL848) { + if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth]; + else if(VDisplay == 240) { + if(!FSTN) ModeIndex = ModeIndex_320x240[Depth]; + else if(VGAEngine == SIS_315_VGA) { + ModeIndex = ModeIndex_320x240_FSTN[Depth]; + } + } + } + break; + case 400: + if(CustomT != CUT_PANEL848) { + if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) { + if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth]; + } + } + break; + case 512: + if(CustomT != CUT_PANEL848) { + if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) { + if(LCDwidth >= 1024 && LCDwidth != 1152 && LCDheight >= 768) { + if(VDisplay == 384) { + ModeIndex = ModeIndex_512x384[Depth]; + } + } + } + } + break; + case 640: + if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth]; + else if(VDisplay == 400) { + if(CustomT != CUT_PANEL848) ModeIndex = ModeIndex_640x400[Depth]; + } + break; + case 800: + if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth]; + break; + case 848: + if(CustomT == CUT_PANEL848) { + if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth]; + } + break; + case 1024: + if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth]; + else if(VGAEngine == SIS_300_VGA) { + if((VDisplay == 600) && (LCDheight == 600)) { + ModeIndex = ModeIndex_1024x600[Depth]; + } + } + break; + case 1152: + if(VGAEngine == SIS_300_VGA) { + if((VDisplay == 768) && (LCDheight == 768)) { + ModeIndex = ModeIndex_1152x768[Depth]; + } + } + break; + case 1280: + if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth]; + else if(VGAEngine == SIS_315_VGA) { + if((VDisplay == 768) && (LCDheight == 768)) { + ModeIndex = ModeIndex_310_1280x768[Depth]; + } + } + break; + case 1360: + if(VGAEngine == SIS_300_VGA) { + if(CustomT == CUT_BARCO1366) { + if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth]; + } + } + if(CustomT == CUT_PANEL848) { + if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth]; + } + break; + case 1400: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth]; + } + break; + case 1600: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth]; + } + break; + } + + } else if(VBFlags & VB_SISBRIDGE) { + + switch(HDisplay) + { + case 320: + if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth]; + else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth]; + break; + case 400: + if(LCDwidth >= 800 && LCDheight >= 600) { + if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth]; + } + break; + case 512: + if(LCDwidth >= 1024 && LCDheight >= 768 && LCDwidth != 1152) { + if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth]; + } + break; + case 640: + if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth]; + else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth]; + break; + case 720: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth]; + else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth]; + } + break; + case 768: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth]; + } + break; + case 800: + if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth]; + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth]; + } + break; + case 848: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth]; + } + break; + case 856: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth]; + } + break; + case 960: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth]; + else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth]; + } + break; + case 1024: + if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth]; + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth]; + } + break; + case 1152: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth]; + } + break; + case 1280: + switch(VDisplay) { + case 720: + ModeIndex = ModeIndex_1280x720[Depth]; + case 768: + if(VGAEngine == SIS_300_VGA) { + ModeIndex = ModeIndex_300_1280x768[Depth]; + } else { + ModeIndex = ModeIndex_310_1280x768[Depth]; + } + break; + case 800: + if(VGAEngine == SIS_315_VGA) { + ModeIndex = ModeIndex_1280x800[Depth]; + } + break; + case 960: + ModeIndex = ModeIndex_1280x960[Depth]; + break; + case 1024: + ModeIndex = ModeIndex_1280x1024[Depth]; + break; + } + break; + case 1360: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth]; + } + break; + case 1400: + if(VGAEngine == SIS_315_VGA) { + if(VBFlags & (VB_301C | VB_302LV | VB_302ELV)) { + if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth]; + } + } + break; + case 1600: + if(VGAEngine == SIS_315_VGA) { + if(VBFlags & (VB_301C | VB_302LV | VB_302ELV)) { + if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth]; + } + } + break; +#ifndef VB_FORBID_CRT2LCD_OVER_1600 + case 1680: + if(VGAEngine == SIS_315_VGA) { + if(VBFlags & (VB_301C | VB_302LV | VB_302ELV)) { + if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth]; + } + } + break; +#endif + } + } + + return ModeIndex; +} + +USHORT +SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth) +{ + USHORT ModeIndex = 0; + + if(VBFlags & VB_CHRONTEL) { + + switch(HDisplay) + { + case 512: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth]; + } + break; + case 640: + if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth]; + else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth]; + break; + case 800: + if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth]; + break; + case 1024: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth]; + } + break; + } + + } else if(VBFlags & VB_SISTVBRIDGE) { + + switch(HDisplay) + { + case 320: + if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth]; + else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth]; + break; + case 400: + if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth]; + break; + case 512: + if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) || + (VBFlags & TV_HIVISION) || + ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) { + if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth]; + } + break; + case 640: + if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth]; + else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth]; + break; + case 720: + if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) { + if(VDisplay == 480) { + ModeIndex = ModeIndex_720x480[Depth]; + } else if(VDisplay == 576) { + if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) || + ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) + ModeIndex = ModeIndex_720x576[Depth]; + } + } + break; + case 768: + if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) { + if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) || + ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) { + if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth]; + } + } + break; + case 800: + if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth]; + else if(VDisplay == 480) { + if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) { + ModeIndex = ModeIndex_800x480[Depth]; + } + } + break; + case 960: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 600) { + if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) { + ModeIndex = ModeIndex_960x600[Depth]; + } + } + } + break; + case 1024: + if(VDisplay == 768) { + if(VBFlags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)) { + ModeIndex = ModeIndex_1024x768[Depth]; + } + } else if(VDisplay == 576) { + if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) { + ModeIndex = ModeIndex_1024x576[Depth]; + } + } + break; + case 1280: + if(VDisplay == 720) { + if((VBFlags & TV_HIVISION) || + ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) { + ModeIndex = ModeIndex_1280x720[Depth]; + } + } else if(VDisplay == 1024) { + if((VBFlags & TV_HIVISION) || + ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) { + ModeIndex = ModeIndex_1280x1024[Depth]; + } + } + break; + } + } + return ModeIndex; +} + +USHORT +SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth) +{ + USHORT ModeIndex = 0; + + if(!(VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0; + + switch(HDisplay) + { + case 320: + if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth]; + else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth]; + break; + case 400: + if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth]; + break; + case 512: + if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth]; + break; + case 640: + if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth]; + else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth]; + break; + case 720: + if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth]; + else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth]; + break; + case 768: + if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth]; + break; + case 800: + if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth]; + else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth]; + break; + case 848: + if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth]; + break; + case 856: + if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth]; + break; + case 960: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth]; + else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth]; + } + break; + case 1024: + if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth]; + else if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth]; + break; + case 1152: + if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth]; + else if(VGAEngine == SIS_300_VGA) { + if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth]; + } + break; + case 1280: + if(VDisplay == 768) { + if(VGAEngine == SIS_300_VGA) { + ModeIndex = ModeIndex_300_1280x768[Depth]; + } else { + ModeIndex = ModeIndex_310_1280x768[Depth]; + } + } else if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth]; + else if(VDisplay == 720) ModeIndex = ModeIndex_1280x720[Depth]; + else if(VDisplay == 800) ModeIndex = ModeIndex_1280x800[Depth]; + else if(VDisplay == 960) ModeIndex = ModeIndex_1280x960[Depth]; + break; + case 1360: + if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth]; + break; + case 1400: + if(VGAEngine == SIS_315_VGA) { + if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth]; + } + break; + case 1600: + if(VGAEngine == SIS_315_VGA) { + if(VBFlags & (VB_301B|VB_301C|VB_302B)) { + if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth]; + } + } + break; + case 1680: + if(VGAEngine == SIS_315_VGA) { + if(VBFlags & (VB_301B|VB_301C|VB_302B)) { + if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth]; + } + } + break; + } + + return ModeIndex; +} + + +/*********************************************/ +/* HELPER: SetReg, GetReg */ +/*********************************************/ + +void +SiS_SetReg(SISIOADDRESS port, USHORT index, USHORT data) +{ + OutPortByte(port,index); + OutPortByte(port + 1,data); +} + +void +SiS_SetRegByte(SISIOADDRESS port, USHORT data) +{ + OutPortByte(port,data); +} + +void +SiS_SetRegShort(SISIOADDRESS port, USHORT data) +{ + OutPortWord(port,data); +} + +void +SiS_SetRegLong(SISIOADDRESS port, ULONG data) +{ + OutPortLong(port,data); +} + +UCHAR +SiS_GetReg(SISIOADDRESS port, USHORT index) +{ + OutPortByte(port,index); + return(InPortByte(port + 1)); +} + +UCHAR +SiS_GetRegByte(SISIOADDRESS port) +{ + return(InPortByte(port)); +} + +USHORT +SiS_GetRegShort(SISIOADDRESS port) +{ + return(InPortWord(port)); +} + +ULONG +SiS_GetRegLong(SISIOADDRESS port) +{ + return(InPortLong(port)); +} + +void +SiS_SetRegANDOR(SISIOADDRESS Port,USHORT Index,USHORT DataAND,USHORT DataOR) +{ + USHORT temp; + + temp = SiS_GetReg(Port,Index); + temp = (temp & (DataAND)) | DataOR; + SiS_SetReg(Port,Index,temp); +} + +void +SiS_SetRegAND(SISIOADDRESS Port,USHORT Index,USHORT DataAND) +{ + USHORT temp; + + temp = SiS_GetReg(Port,Index); + temp &= DataAND; + SiS_SetReg(Port,Index,temp); +} + +void +SiS_SetRegOR(SISIOADDRESS Port,USHORT Index,USHORT DataOR) +{ + USHORT temp; + + temp = SiS_GetReg(Port,Index); + temp |= DataOR; + SiS_SetReg(Port,Index,temp); +} + +/*********************************************/ +/* HELPER: DisplayOn, DisplayOff */ +/*********************************************/ + +void +SiS_DisplayOn(SiS_Private *SiS_Pr) +{ + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF); +} + +void +SiS_DisplayOff(SiS_Private *SiS_Pr) +{ + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20); +} + + +/*********************************************/ +/* HELPER: Init Port Addresses */ +/*********************************************/ + +void +SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr) +{ + SiS_Pr->SiS_P3c4 = BaseAddr + 0x14; + SiS_Pr->SiS_P3d4 = BaseAddr + 0x24; + SiS_Pr->SiS_P3c0 = BaseAddr + 0x10; + SiS_Pr->SiS_P3ce = BaseAddr + 0x1e; + SiS_Pr->SiS_P3c2 = BaseAddr + 0x12; + SiS_Pr->SiS_P3ca = BaseAddr + 0x1a; + SiS_Pr->SiS_P3c6 = BaseAddr + 0x16; + SiS_Pr->SiS_P3c7 = BaseAddr + 0x17; + SiS_Pr->SiS_P3c8 = BaseAddr + 0x18; + SiS_Pr->SiS_P3c9 = BaseAddr + 0x19; + SiS_Pr->SiS_P3cb = BaseAddr + 0x1b; + SiS_Pr->SiS_P3cd = BaseAddr + 0x1d; + SiS_Pr->SiS_P3da = BaseAddr + 0x2a; + SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04; /* Digital video interface registers (LCD) */ + SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10; /* 301 TV Encoder registers */ + SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12; /* 301 Macrovision registers */ + SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */ + SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2; /* 301 palette address port registers */ + SiS_Pr->SiS_DDC_Port = BaseAddr + 0x14; /* DDC Port ( = P3C4, SR11/0A) */ + SiS_Pr->SiS_VidCapt = BaseAddr + SIS_VIDEO_CAPTURE; + SiS_Pr->SiS_VidPlay = BaseAddr + SIS_VIDEO_PLAYBACK; +} + +/*********************************************/ +/* HELPER: GetSysFlags */ +/*********************************************/ + +static void +SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + unsigned char cr5f, temp1, temp2; + + /* 661 and newer: NEVER write non-zero to SR11[7:4] */ + /* (SR11 is used for DDC and in enable/disablebridge) */ + SiS_Pr->SiS_SensibleSR11 = FALSE; + SiS_Pr->SiS_MyCR63 = 0x63; + if(HwInfo->jChipType >= SIS_330) { + SiS_Pr->SiS_MyCR63 = 0x53; + if(HwInfo->jChipType >= SIS_661) { + SiS_Pr->SiS_SensibleSR11 = TRUE; + } + } + + /* You should use the macros, not these flags directly */ + + SiS_Pr->SiS_SysFlags = 0; + if(HwInfo->jChipType == SIS_650) { + cr5f = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0; + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07); + temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8; + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8); + temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8; + if((!temp1) || (temp2)) { + switch(cr5f) { + case 0x80: + case 0x90: + case 0xc0: + SiS_Pr->SiS_SysFlags |= SF_IsM650; break; + case 0xa0: + case 0xb0: + case 0xe0: + SiS_Pr->SiS_SysFlags |= SF_Is651; break; + } + } else { + switch(cr5f) { + case 0x90: + temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8; + switch(temp1) { + case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break; + case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break; + default: SiS_Pr->SiS_SysFlags |= SF_IsM650; break; + } + break; + case 0xb0: + SiS_Pr->SiS_SysFlags |= SF_Is652; break; + default: + SiS_Pr->SiS_SysFlags |= SF_IsM650; break; + } + } + } + if(HwInfo->jChipType == SIS_760) { + temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78); + if(temp1 & 0x30) SiS_Pr->SiS_SysFlags |= SF_760LFB; + } +} + +/*********************************************/ +/* HELPER: Init PCI & Engines */ +/*********************************************/ + +static void +SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + switch(HwInfo->jChipType) { + case SIS_300: + case SIS_540: + case SIS_630: + case SIS_730: + /* Set - PCI LINEAR ADDRESSING ENABLE (0x80) + * - RELOCATED VGA IO (0x20) + * - MMIO ENABLE (0x1) + */ + SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1); + /* - Enable 2D (0x40) + * - Enable 3D (0x02) + * - Enable 3D Vertex command fetch (0x10) ? + * - Enable 3D command parser (0x08) ? + */ + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A); + break; + case SIS_315H: + case SIS_315: + case SIS_315PRO: + case SIS_650: + case SIS_740: + case SIS_330: + case SIS_661: + case SIS_741: + case SIS_660: + case SIS_760: + case SIS_761: + case SIS_340: + SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1); + /* - Enable 2D (0x40) + * - Enable 3D (0x02) + * - Enable 3D vertex command fetch (0x10) + * - Enable 3D command parser (0x08) + * - Enable 3D G/L transformation engine (0x80) + */ + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0xDA); + break; + case SIS_550: + SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1); + /* No 3D engine ! */ + /* - Enable 2D (0x40) + */ + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x40); + } +} + +/*********************************************/ +/* HELPER: SetLVDSetc */ +/*********************************************/ + +void +SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT temp; + + SiS_Pr->SiS_IF_DEF_LVDS = 0; + SiS_Pr->SiS_IF_DEF_TRUMPION = 0; + SiS_Pr->SiS_IF_DEF_CH70xx = 0; + SiS_Pr->SiS_IF_DEF_DSTN = 0; + SiS_Pr->SiS_IF_DEF_FSTN = 0; + SiS_Pr->SiS_IF_DEF_CONEX = 0; + + SiS_Pr->SiS_ChrontelInit = 0; + + /* Check for SiS30x first */ + temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00); + if((temp == 1) || (temp == 2)) return; + + switch(HwInfo->jChipType) { +#ifdef SIS300 + case SIS_540: + case SIS_630: + case SIS_730: + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); + temp = (temp & 0x0E) >> 1; + if((temp >= 2) && (temp <= 5)) SiS_Pr->SiS_IF_DEF_LVDS = 1; + if(temp == 3) SiS_Pr->SiS_IF_DEF_TRUMPION = 1; + if((temp == 4) || (temp == 5)) { + /* Save power status (and error check) - UNUSED */ + SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e); + SiS_Pr->SiS_IF_DEF_CH70xx = 1; + } + break; +#endif +#ifdef SIS315H + case SIS_550: + case SIS_650: + case SIS_740: + case SIS_330: + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); + temp = (temp & 0x0E) >> 1; + if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1; + if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2; + break; + case SIS_661: + case SIS_741: + case SIS_660: + case SIS_760: + case SIS_761: + case SIS_340: + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + temp = (temp & 0xe0) >> 5; + if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1; + if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2; + if(temp == 4) SiS_Pr->SiS_IF_DEF_CONEX = 1; /* Not yet supported */ + break; +#endif + default: + break; + } +} + +/*********************************************/ +/* HELPER: Enable DSTN/FSTN */ +/*********************************************/ + +void +SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable) +{ + SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0; +} + +void +SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable) +{ + SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0; +} + +/*********************************************/ +/* HELPER: Determine ROM usage */ +/*********************************************/ + +BOOLEAN +SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT romversoffs, romvmaj = 1, romvmin = 0; + + if(HwInfo->jChipType >= SIS_761) { + /* I very much assume 761 and 340 will use new layout */ + return TRUE; + } else if(HwInfo->jChipType >= SIS_661) { + if((ROMAddr[0x1a] == 'N') && + (ROMAddr[0x1b] == 'e') && + (ROMAddr[0x1c] == 'w') && + (ROMAddr[0x1d] == 'V')) { + return TRUE; + } + romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8); + if(romversoffs) { + if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) { + romvmaj = ROMAddr[romversoffs] - '0'; + romvmin = ((ROMAddr[romversoffs+2] -'0') * 10) + (ROMAddr[romversoffs+3] - '0'); + } + } + if((romvmaj != 0) || (romvmin >= 92)) { + return TRUE; + } + } else if(IS_SIS650740) { + if((ROMAddr[0x1a] == 'N') && + (ROMAddr[0x1b] == 'e') && + (ROMAddr[0x1c] == 'w') && + (ROMAddr[0x1d] == 'V')) { + return TRUE; + } + } + return FALSE; +} + +static void +SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT romptr = 0; + + SiS_Pr->SiS_UseROM = FALSE; + SiS_Pr->SiS_ROMNew = FALSE; + + if((ROMAddr) && (HwInfo->UseROM)) { + if(HwInfo->jChipType == SIS_300) { + /* 300: We check if the code starts below 0x220 by + * checking the jmp instruction at the beginning + * of the BIOS image. + */ + if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a) + SiS_Pr->SiS_UseROM = TRUE; + } else if(HwInfo->jChipType < SIS_315H) { + /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps + * the others do as well + */ + SiS_Pr->SiS_UseROM = TRUE; + } else { + /* 315/330 series stick to the standard(s) */ + SiS_Pr->SiS_UseROM = TRUE; + if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr, HwInfo))) { + SiS_Pr->SiS_EMIOffset = 14; + SiS_Pr->SiS661LCD2TableSize = 36; + /* Find out about LCD data table entry size */ + if((romptr = SISGETROMW(0x0102))) { + if(ROMAddr[romptr + (32 * 16)] == 0xff) + SiS_Pr->SiS661LCD2TableSize = 32; + else if(ROMAddr[romptr + (34 * 16)] == 0xff) + SiS_Pr->SiS661LCD2TableSize = 34; + else if(ROMAddr[romptr + (36 * 16)] == 0xff) /* 0.94 */ + SiS_Pr->SiS661LCD2TableSize = 36; + else if( (ROMAddr[romptr + (38 * 16)] == 0xff) || /* 2.00.00 - 2.02.00 */ + (ROMAddr[0x6F] & 0x01) ) { /* 2.03.00+ */ + SiS_Pr->SiS661LCD2TableSize = 38; + SiS_Pr->SiS_EMIOffset = 16; + } + } + } + } + } +} + +/*********************************************/ +/* HELPER: SET SEGMENT REGISTERS */ +/*********************************************/ + +static void +SiS_SetSegRegLower(SiS_Private *SiS_Pr, USHORT value) +{ + USHORT temp; + + value &= 0x00ff; + temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0xf0; + temp |= (value >> 4); + SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp); + temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0xf0; + temp |= (value & 0x0f); + SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp); +} + +static void +SiS_SetSegRegUpper(SiS_Private *SiS_Pr, USHORT value) +{ + USHORT temp; + + value &= 0x00ff; + temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0x0f; + temp |= (value & 0xf0); + SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp); + temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0x0f; + temp |= (value << 4); + SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp); +} + +static void +SiS_SetSegmentReg(SiS_Private *SiS_Pr, USHORT value) +{ + SiS_SetSegRegLower(SiS_Pr, value); + SiS_SetSegRegUpper(SiS_Pr, value); +} + +static void +SiS_ResetSegmentReg(SiS_Private *SiS_Pr) +{ + SiS_SetSegmentReg(SiS_Pr, 0); +} + +static void +SiS_SetSegmentRegOver(SiS_Private *SiS_Pr, USHORT value) +{ + USHORT temp = value >> 8; + + temp &= 0x07; + temp |= (temp << 4); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x1d,temp); + SiS_SetSegmentReg(SiS_Pr, value); +} + +static void +SiS_ResetSegmentRegOver(SiS_Private *SiS_Pr) +{ + SiS_SetSegmentRegOver(SiS_Pr, 0); +} + +static void +SiS_ResetSegmentRegisters(SiS_Private *SiS_Pr,PSIS_HW_INFO HwInfo) +{ + if((IS_SIS65x) || (HwInfo->jChipType >= SIS_661)) { + SiS_ResetSegmentReg(SiS_Pr); + SiS_ResetSegmentRegOver(SiS_Pr); + } +} + +/*********************************************/ +/* HELPER: GetVBType */ +/*********************************************/ + +void +SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT flag=0, rev=0, nolcd=0, p4_0f, p4_25, p4_27; + + SiS_Pr->SiS_VBType = 0; + + if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX)) + return; + + flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00); + + if(flag > 3) return; + + rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); + + if(flag >= 2) { + SiS_Pr->SiS_VBType = VB_SIS302B; + } else if(flag == 1) { + if(rev >= 0xC0) { + SiS_Pr->SiS_VBType = VB_SIS301C; + } else if(rev >= 0xB0) { + SiS_Pr->SiS_VBType = VB_SIS301B; + /* Check if 30xB DH version (no LCD support, use Panel Link instead) */ + nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23); + if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD; + } else { + SiS_Pr->SiS_VBType = VB_SIS301; + } + } + if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) { + if(rev >= 0xE0) { + flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39); + if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV; + else SiS_Pr->SiS_VBType = VB_SIS301C; /* VB_SIS302ELV; */ + } else if(rev >= 0xD0) { + SiS_Pr->SiS_VBType = VB_SIS301LV; + } + } + if(SiS_Pr->SiS_VBType & (VB_301C | VB_301LV | VB_302LV | VB_302ELV)) { + p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f); + p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25); + p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27); + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f); + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08); + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd); + if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) { + SiS_Pr->SiS_VBType |= VB_UMC; + } + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f); + } +} + +/*********************************************/ +/* HELPER: Check RAM size */ +/*********************************************/ + +#ifdef LINUX_KERNEL +static BOOLEAN +SiS_CheckMemorySize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo, USHORT ModeIdIndex) +{ + USHORT AdapterMemSize = HwInfo->ulVideoMemorySize / (1024*1024); + USHORT memorysize,modeflag; + + if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + } else { + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } + } + + memorysize = modeflag & MemoryInfoFlag; + memorysize >>= MemorySizeShift; /* Get required memory size */ + memorysize++; + + if(AdapterMemSize < memorysize) return FALSE; + return TRUE; +} +#endif + +/*********************************************/ +/* HELPER: Get DRAM type */ +/*********************************************/ + +#ifdef SIS315H +static UCHAR +SiS_Get310DRAMType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR data, temp; + + if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) { + data = (*SiS_Pr->pSiS_SoftSetting) & 0x03; + } else { + if(HwInfo->jChipType >= SIS_340) { + /* TODO */ + data = 0; + } if(HwInfo->jChipType >= SIS_661) { + data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07; + if(SiS_Pr->SiS_ROMNew) { + data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6); + } + } else if(IS_SIS550650740) { + data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07; + } else { /* 315, 330 */ + data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03; + if(HwInfo->jChipType == SIS_330) { + if(data > 1) { + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30; + switch(temp) { + case 0x00: data = 1; break; + case 0x10: data = 3; break; + case 0x20: data = 3; break; + case 0x30: data = 2; break; + } + } else { + data = 0; + } + } + } + } + + return data; +} + +static USHORT +SiS_GetMCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT index; + + index = SiS_Get310DRAMType(SiS_Pr, HwInfo); + if(HwInfo->jChipType >= SIS_661) { + if(SiS_Pr->SiS_ROMNew) { + return((USHORT)(SISGETROMW((0x90 + (index * 5) + 3)))); + } + return(SiS_Pr->SiS_MCLKData_0[index].CLOCK); + } else if(index >= 4) { + index -= 4; + return(SiS_Pr->SiS_MCLKData_1[index].CLOCK); + } else { + return(SiS_Pr->SiS_MCLKData_0[index].CLOCK); + } +} +#endif + +/*********************************************/ +/* HELPER: ClearBuffer */ +/*********************************************/ + +#ifdef LINUX_KERNEL +static void +SiS_ClearBuffer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo) +{ + UCHAR SISIOMEMTYPE *VideoMemoryAddress = HwInfo->pjVideoMemoryAddress; + ULONG AdapterMemorySize = HwInfo->ulVideoMemorySize; + USHORT SISIOMEMTYPE *pBuffer; + int i; + + if(SiS_Pr->SiS_ModeType >= ModeEGA) { + if(ModeNo > 0x13) { + SiS_SetMemory(VideoMemoryAddress, AdapterMemorySize, 0); + } else { + pBuffer = (USHORT SISIOMEMTYPE *)VideoMemoryAddress; + for(i=0; i<0x4000; i++) writew(0x0000, &pBuffer[i]); + } + } else { + if(SiS_Pr->SiS_ModeType < ModeCGA) { + pBuffer = (USHORT SISIOMEMTYPE *)VideoMemoryAddress; + for(i=0; i<0x4000; i++) writew(0x0720, &pBuffer[i]); + } else { + SiS_SetMemory(VideoMemoryAddress, 0x8000, 0); + } + } +} +#endif + +/*********************************************/ +/* HELPER: SearchModeID */ +/*********************************************/ + +BOOLEAN +SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex) +{ + UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO; + + if(*ModeNo <= 0x13) { + + if((*ModeNo) <= 0x05) (*ModeNo) |= 0x01; + + for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) { + if(SiS_Pr->SiS_SModeIDTable[*ModeIdIndex].St_ModeID == (*ModeNo)) break; + if(SiS_Pr->SiS_SModeIDTable[*ModeIdIndex].St_ModeID == 0xFF) return FALSE; + } + + if(*ModeNo == 0x07) { + if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */ + /* else 350 lines */ + } + if(*ModeNo <= 0x03) { + if(!(VGAINFO & 0x80)) (*ModeIdIndex)++; + if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */ + /* else 350 lines */ + } + /* else 200 lines */ + + } else { + + for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) { + if(SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo)) break; + if(SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF) return FALSE; + } + + } + return TRUE; +} + +/*********************************************/ +/* HELPER: GetModePtr */ +/*********************************************/ + +UCHAR +SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex) +{ + UCHAR index; + + if(ModeNo <= 0x13) { + index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex; + } else { + if(SiS_Pr->SiS_ModeType <= ModeEGA) index = 0x1B; + else index = 0x0F; + } + return index; +} + +/*********************************************/ +/* HELPER: LowModeTests */ +/*********************************************/ + +static BOOLEAN +SiS_DoLowModeTest(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo) +{ + USHORT temp,temp1,temp2; + + if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12)) + return(TRUE); + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11); + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80); + temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55); + temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp); + if((HwInfo->jChipType >= SIS_315H) || + (HwInfo->jChipType == SIS_300)) { + if(temp2 == 0x55) return(FALSE); + else return(TRUE); + } else { + if(temp2 != 0x55) return(TRUE); + else { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01); + return(FALSE); + } + } +} + +static void +SiS_SetLowModeTest(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo) +{ + if(SiS_DoLowModeTest(SiS_Pr, ModeNo, HwInfo)) { + SiS_Pr->SiS_SetFlag |= LowModeTests; + } +} + +/*********************************************/ +/* HELPER: ENABLE CRT1 */ +/*********************************************/ + +static void +SiS_SetupCR5x(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + if(IS_SIS650) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f); + if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20); + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7); + } + } else if(IS_SIS661741660760) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7); + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f); + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7); + if(!SiS_Pr->SiS_ROMNew) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef); + } + } +} + +static void +SiS_HandleCRT1(SiS_Private *SiS_Pr) +{ + /* Enable CRT1 gating */ + SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf); +#if 0 + if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) { + if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) || + (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40); + } + } +#endif +} + +/*********************************************/ +/* HELPER: GetColorDepth */ +/*********************************************/ + +USHORT +SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex) +{ + USHORT ColorDepth[6] = { 1, 2, 4, 4, 6, 8}; + SHORT index; + USHORT modeflag; + + /* Do NOT check UseCustomMode, will skrew up FIFO */ + if(ModeNo == 0xfe) { + modeflag = SiS_Pr->CModeFlag; + } else { + if(ModeNo <= 0x13) + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + else + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } + + index = (modeflag & ModeTypeMask) - ModeEGA; + if(index < 0) index = 0; + return(ColorDepth[index]); +} + +/*********************************************/ +/* HELPER: GetOffset */ +/*********************************************/ + +USHORT +SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo) +{ + USHORT xres, temp, colordepth, infoflag; + + if(SiS_Pr->UseCustomMode) { + infoflag = SiS_Pr->CInfoFlag; + xres = SiS_Pr->CHDisplay; + } else { + infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag; + xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes; + } + + colordepth = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex); + + temp = xres / 16; + if(infoflag & InterlaceMode) temp <<= 1; + temp *= colordepth; + if(xres % 16) { + colordepth >>= 1; + temp += colordepth; + } + + return(temp); +} + +/*********************************************/ +/* SEQ */ +/*********************************************/ + +static void +SiS_SetSeqRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo) +{ + UCHAR SRdata; + USHORT i; + + SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03); /* Set SR0 */ + + SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0]; + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SRdata |= 0x01; + } + if(HwInfo->jChipType >= SIS_661) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + SRdata |= 0x01; /* 8 dot clock */ + } + } + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->SiS_VBType & VB_NoLCD) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + SRdata |= 0x01; /* 8 dot clock */ + } + } + } + } + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + SRdata |= 0x01; /* 8 dot clock */ + } + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + SRdata |= 0x01; /* 8 dot clock */ + } + } + } + + SRdata |= 0x20; /* screen off */ + + SiS_SetReg(SiS_Pr->SiS_P3c4,0x01,SRdata); + + for(i = 2; i <= 4; i++) { + SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1]; + SiS_SetReg(SiS_Pr->SiS_P3c4,i,SRdata); + } +} + +/*********************************************/ +/* MISC */ +/*********************************************/ + +static void +SiS_SetMiscRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo) +{ + UCHAR Miscdata; + + Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC; + + if(HwInfo->jChipType < SIS_661) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + Miscdata |= 0x0C; + } + } + } + + SiS_SetRegByte(SiS_Pr->SiS_P3c2,Miscdata); +} + +/*********************************************/ +/* CRTC */ +/*********************************************/ + +static void +SiS_SetCRTCRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT StandTableIndex) +{ + UCHAR CRTCdata; + USHORT i; + + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); /* Unlock CRTC */ + + for(i = 0; i <= 0x18; i++) { + CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i]; + SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata); /* Set CRTC(3d4) */ + } + if(HwInfo->jChipType >= SIS_661) { + SiS_SetupCR5x(SiS_Pr, HwInfo); + for(i = 0x13; i <= 0x14; i++) { + CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i]; + SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata); + } + } else if( ( (HwInfo->jChipType == SIS_630) || + (HwInfo->jChipType == SIS_730) ) && + (HwInfo->jChipRevision >= 0x30) ) { /* for 630S0 */ + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE); + } + } + } +} + +/*********************************************/ +/* ATT */ +/*********************************************/ + +static void +SiS_SetATTRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, + PSIS_HW_INFO HwInfo) +{ + UCHAR ARdata; + USHORT i; + + for(i = 0; i <= 0x13; i++) { + ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i]; +#if 0 + if((i <= 0x0f) || (i == 0x11)) { + if(ds:489 & 0x08) { + continue; + } + } +#endif + if(i == 0x13) { + /* Pixel shift. If screen on LCD or TV is shifted left or right, + * this might be the cause. + */ + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata=0; + } + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0; + } + } + } + if(HwInfo->jChipType >= SIS_661) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0; + } + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(HwInfo->jChipType >= SIS_315H) { + if(IS_SIS550650740660) { + /* 315, 330 don't do this */ + if(SiS_Pr->SiS_VBType & VB_SIS301B302B) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0; + } else { + ARdata = 0; + } + } + } else { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0; + } + } + } + SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */ + SiS_SetRegByte(SiS_Pr->SiS_P3c0,i); /* set index */ + SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata); /* set data */ + } + SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */ + SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14); /* set index */ + SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00); /* set data */ + + SiS_GetRegByte(SiS_Pr->SiS_P3da); + SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20); /* Enable Attribute */ + SiS_GetRegByte(SiS_Pr->SiS_P3da); +} + +/*********************************************/ +/* GRC */ +/*********************************************/ + +static void +SiS_SetGRCRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex) +{ + UCHAR GRdata; + USHORT i; + + for(i = 0; i <= 0x08; i++) { + GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i]; + SiS_SetReg(SiS_Pr->SiS_P3ce,i,GRdata); + } + + if(SiS_Pr->SiS_ModeType > ModeVGA) { + /* 256 color disable */ + SiS_SetRegAND(SiS_Pr->SiS_P3ce,0x05,0xBF); + } +} + +/*********************************************/ +/* CLEAR EXTENDED REGISTERS */ +/*********************************************/ + +static void +SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo) +{ + USHORT i; + + for(i = 0x0A; i <= 0x0E; i++) { + SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00); + } + + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE); + if(ModeNo <= 0x13) { + if(ModeNo == 0x06 || ModeNo >= 0x0e) { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20); + } + } + } +} + +/*********************************************/ +/* RESET VCLK */ +/*********************************************/ + +static void +SiS_ResetCRT1VCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + if(HwInfo->jChipType >= SIS_315H) { + if(HwInfo->jChipType < SIS_661) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return; + } + } else { + if((SiS_Pr->SiS_IF_DEF_LVDS == 0) && + (!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) { + return; + } + } + + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xCF,0x20); + } else { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20); + } + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[1].SR2B); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[1].SR2C); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80); + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10); + } else { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10); + } + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[0].SR2B); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[0].SR2C); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80); +} + +/*********************************************/ +/* SYNC */ +/*********************************************/ + +static void +SiS_SetCRT1Sync(SiS_Private *SiS_Pr, USHORT RefreshRateTableIndex) +{ + USHORT sync; + + if(SiS_Pr->UseCustomMode) { + sync = SiS_Pr->CInfoFlag >> 8; + } else { + sync = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8; + } + + sync &= 0xC0; + sync |= 0x2f; + SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync); +} + +/*********************************************/ +/* CRTC/2 */ +/*********************************************/ + +static void +SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + PSIS_HW_INFO HwInfo) +{ + UCHAR index; + USHORT temp,i,j,modeflag; + + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); /* unlock cr0-7 */ + + if(SiS_Pr->UseCustomMode) { + + modeflag = SiS_Pr->CModeFlag; + + for(i=0,j=0;i<=7;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]); + } + for(j=0x10;i<=10;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]); + } + for(j=0x15;i<=12;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]); + } + for(j=0x0A;i<=15;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]); + } + + temp = SiS_Pr->CCRT1CRTC[16] & 0xE0; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp); + + temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5; + if(modeflag & DoubleScanMode) temp |= 0x80; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp); + + } else { + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } + + index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; + + for(i=0,j=0;i<=7;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]); + } + for(j=0x10;i<=10;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]); + } + for(j=0x15;i<=12;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]); + } + for(j=0x0A;i<=15;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]); + } + + temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp); + + temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5; + if(modeflag & DoubleScanMode) temp |= 0x80; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp); + + } + + if(SiS_Pr->SiS_ModeType > ModeVGA) SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F); +} + +/*********************************************/ +/* OFFSET & PITCH */ +/*********************************************/ +/* (partly overruled by SetPitch() in XF86) */ +/*********************************************/ + +static void +SiS_SetCRT1Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + PSIS_HW_INFO HwInfo) +{ + USHORT temp, DisplayUnit, infoflag; + + if(SiS_Pr->UseCustomMode) { + infoflag = SiS_Pr->CInfoFlag; + } else { + infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag; + } + + DisplayUnit = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwInfo); + + temp = (DisplayUnit >> 8) & 0x0f; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp); + + temp = DisplayUnit & 0xFF; + SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,temp); + + if(infoflag & InterlaceMode) DisplayUnit >>= 1; + + DisplayUnit <<= 5; + temp = (DisplayUnit & 0xff00) >> 8; + if(DisplayUnit & 0xff) temp++; + temp++; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp); +} + +/*********************************************/ +/* VCLK */ +/*********************************************/ + +static void +SiS_SetCRT1VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex) +{ + USHORT index=0, clka, clkb; + + if(SiS_Pr->UseCustomMode) { + clka = SiS_Pr->CSR2B; + clkb = SiS_Pr->CSR2C; + } else { + index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A; + clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B; + } else { + clka = SiS_Pr->SiS_VCLKData[index].SR2B; + clkb = SiS_Pr->SiS_VCLKData[index].SR2C; + } + } + + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF); + } else { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00); + } + + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,clka); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,clkb); + + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01); + } else { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80); + } +} + +/*********************************************/ +/* FIFO */ +/*********************************************/ + +#ifdef SIS300 +static USHORT +SiS_DoCalcDelay(SiS_Private *SiS_Pr, USHORT MCLK, USHORT VCLK, USHORT colordepth, USHORT key) +{ + const UCHAR ThLowA[] = { 61, 3,52, 5,68, 7,100,11, + 43, 3,42, 5,54, 7, 78,11, + 34, 3,37, 5,47, 7, 67,11 }; + + const UCHAR ThLowB[] = { 81, 4,72, 6,88, 8,120,12, + 55, 4,54, 6,66, 8, 90,12, + 42, 4,45, 6,55, 8, 75,12 }; + + const UCHAR ThTiming[] = { 1, 2, 2, 3, 0, 1, 1, 2 }; + + USHORT tempah, tempal, tempcl, tempbx, temp; + ULONG longtemp; + + tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18); + tempah &= 0x62; + tempah >>= 1; + tempal = tempah; + tempah >>= 3; + tempal |= tempah; + tempal &= 0x07; + tempcl = ThTiming[tempal]; + tempbx = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16); + tempbx >>= 6; + tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14); + tempah >>= 4; + tempah &= 0x0c; + tempbx |= tempah; + tempbx <<= 1; + if(key == 0) { + tempal = ThLowA[tempbx + 1]; + tempal *= tempcl; + tempal += ThLowA[tempbx]; + } else { + tempal = ThLowB[tempbx + 1]; + tempal *= tempcl; + tempal += ThLowB[tempbx]; + } + longtemp = tempal * VCLK * colordepth; + temp = longtemp % (MCLK * 16); + longtemp /= (MCLK * 16); + if(temp) longtemp++; + return((USHORT)longtemp); +} + +static USHORT +SiS_CalcDelay(SiS_Private *SiS_Pr, USHORT VCLK, USHORT colordepth, USHORT MCLK) +{ + USHORT tempax, tempbx; + + tempbx = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0); + tempax = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1); + if(tempax < 4) tempax = 4; + tempax -= 4; + if(tempbx < tempax) tempbx = tempax; + return(tempbx); +} + +static void +SiS_SetCRT1FIFO_300(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo, + USHORT RefreshRateTableIndex) +{ + USHORT ThresholdLow = 0; + USHORT index, VCLK, MCLK, colorth=0; + USHORT tempah, temp; + + if(ModeNo > 0x13) { + + if(SiS_Pr->UseCustomMode) { + VCLK = SiS_Pr->CSRClock; + } else { + index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + index &= 0x3F; + VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */ + } + + switch (SiS_Pr->SiS_ModeType - ModeEGA) { /* Get half colordepth */ + case 0 : colorth = 1; break; + case 1 : colorth = 1; break; + case 2 : colorth = 2; break; + case 3 : colorth = 2; break; + case 4 : colorth = 3; break; + case 5 : colorth = 4; break; + } + + index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A); + index &= 0x07; + MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */ + + tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + tempah &= 0xc3; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,tempah); + + do { + ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK); + ThresholdLow++; + if(ThresholdLow < 0x13) break; + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc); + ThresholdLow = 0x13; + tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16); + tempah >>= 6; + if(!(tempah)) break; + tempah--; + tempah <<= 6; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,tempah); + } while(0); + + } else ThresholdLow = 2; + + /* Write CRT/CPU threshold low, CRT/Engine threshold high */ + temp = (ThresholdLow << 4) | 0x0f; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp); + + temp = (ThresholdLow & 0x10) << 1; + if(ModeNo > 0x13) temp |= 0x40; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp); + + /* What is this? */ + SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09); + + /* Write CRT/CPU threshold high */ + temp = ThresholdLow + 3; + if(temp > 0x0f) temp = 0x0f; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp); +} + +static USHORT +SiS_CalcDelay2(SiS_Private *SiS_Pr, UCHAR key, PSIS_HW_INFO HwInfo) +{ + USHORT data,index; + const UCHAR LatencyFactor[] = { + 97, 88, 86, 79, 77, 00, /*; 64 bit BQ=2 */ + 00, 87, 85, 78, 76, 54, /*; 64 bit BQ=1 */ + 97, 88, 86, 79, 77, 00, /*; 128 bit BQ=2 */ + 00, 79, 77, 70, 68, 48, /*; 128 bit BQ=1 */ + 80, 72, 69, 63, 61, 00, /*; 64 bit BQ=2 */ + 00, 70, 68, 61, 59, 37, /*; 64 bit BQ=1 */ + 86, 77, 75, 68, 66, 00, /*; 128 bit BQ=2 */ + 00, 68, 66, 59, 57, 37 /*; 128 bit BQ=1 */ + }; + const UCHAR LatencyFactor730[] = { + 69, 63, 61, + 86, 79, 77, + 103, 96, 94, + 120,113,111, + 137,130,128, /* --- Table ends with this entry, data below */ + 137,130,128, /* to avoid using illegal values */ + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + }; + + if(HwInfo->jChipType == SIS_730) { + index = ((key & 0x0f) * 3) + ((key & 0xC0) >> 6); + data = LatencyFactor730[index]; + } else { + index = (key & 0xE0) >> 5; + if(key & 0x10) index +=6; + if(!(key & 0x01)) index += 24; + data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14); + if(data & 0x0080) index += 12; + data = LatencyFactor[index]; + } + return(data); +} + +static void +SiS_SetCRT1FIFO_630(SiS_Private *SiS_Pr, USHORT ModeNo, + PSIS_HW_INFO HwInfo, + USHORT RefreshRateTableIndex) +{ + USHORT i,index,data,VCLK,MCLK,colorth=0; + ULONG B,eax,bl,data2; + USHORT ThresholdLow=0; + UCHAR FQBQData[]= { + 0x01,0x21,0x41,0x61,0x81, + 0x31,0x51,0x71,0x91,0xb1, + 0x00,0x20,0x40,0x60,0x80, + 0x30,0x50,0x70,0x90,0xb0, + 0xFF + }; + UCHAR FQBQData730[]= { + 0x34,0x74,0xb4, + 0x23,0x63,0xa3, + 0x12,0x52,0x92, + 0x01,0x41,0x81, + 0x00,0x40,0x80, + 0xff + }; + + i=0; + if(ModeNo > 0x13) { + if(SiS_Pr->UseCustomMode) { + VCLK = SiS_Pr->CSRClock; + } else { + index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + index &= 0x3F; + VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */ + } + + index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A); + index &= 0x07; + MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */ + + data2 = SiS_Pr->SiS_ModeType - ModeEGA; /* Get half colordepth */ + switch (data2) { + case 0 : colorth = 1; break; + case 1 : colorth = 1; break; + case 2 : colorth = 2; break; + case 3 : colorth = 2; break; + case 4 : colorth = 3; break; + case 5 : colorth = 4; break; + } + + if(HwInfo->jChipType == SIS_730) { + + do { + B = SiS_CalcDelay2(SiS_Pr, FQBQData730[i], HwInfo) * VCLK * colorth; + bl = B / (MCLK * 16); + + if(B == bl * 16 * MCLK) { + bl = bl + 1; + } else { + bl = bl + 2; + } + + if(bl > 0x13) { + if(FQBQData730[i+1] == 0xFF) { + ThresholdLow = 0x13; + break; + } + i++; + } else { + ThresholdLow = bl; + break; + } + } while(FQBQData730[i] != 0xFF); + + } else { + + do { + B = SiS_CalcDelay2(SiS_Pr, FQBQData[i], HwInfo) * VCLK * colorth; + bl = B / (MCLK * 16); + + if(B == bl * 16 * MCLK) { + bl = bl + 1; + } else { + bl = bl + 2; + } + + if(bl > 0x13) { + if(FQBQData[i+1] == 0xFF) { + ThresholdLow = 0x13; + break; + } + i++; + } else { + ThresholdLow = bl; + break; + } + } while(FQBQData[i] != 0xFF); + } + } + else { + if(HwInfo->jChipType == SIS_730) { + } else { + i = 9; + } + ThresholdLow = 0x02; + } + + /* Write foreground and background queue */ + if(HwInfo->jChipType == SIS_730) { + + data2 = FQBQData730[i]; + data2 = (data2 & 0xC0) >> 5; + data2 <<= 8; + +#ifdef LINUX_KERNEL + SiS_SetRegLong(0xcf8,0x80000050); + eax = SiS_GetRegLong(0xcfc); + eax &= 0xfffff9ff; + eax |= data2; + SiS_SetRegLong(0xcfc,eax); +#else + /* We use pci functions X offers. We use pcitag 0, because + * we want to read/write to the host bridge (which is always + * 00:00.0 on 630, 730 and 540), not the VGA device. + */ + eax = pciReadLong(0x00000000, 0x50); + eax &= 0xfffff9ff; + eax |= data2; + pciWriteLong(0x00000000, 0x50, eax); +#endif + + /* Write GUI grant timer (PCI config 0xA3) */ + data2 = FQBQData730[i] << 8; + data2 = (data2 & 0x0f00) | ((data2 & 0x3000) >> 8); + data2 <<= 20; + +#ifdef LINUX_KERNEL + SiS_SetRegLong(0xcf8,0x800000A0); + eax = SiS_GetRegLong(0xcfc); + eax &= 0x00ffffff; + eax |= data2; + SiS_SetRegLong(0xcfc,eax); +#else + eax = pciReadLong(0x00000000, 0xA0); + eax &= 0x00ffffff; + eax |= data2; + pciWriteLong(0x00000000, 0xA0, eax); +#endif + + } else { + + data2 = FQBQData[i]; + data2 = (data2 & 0xf0) >> 4; + data2 <<= 24; + +#ifdef LINUX_KERNEL + SiS_SetRegLong(0xcf8,0x80000050); + eax = SiS_GetRegLong(0xcfc); + eax &= 0xf0ffffff; + eax |= data2; + SiS_SetRegLong(0xcfc,eax); +#else + eax = pciReadLong(0x00000000, 0x50); + eax &= 0xf0ffffff; + eax |= data2; + pciWriteLong(0x00000000, 0x50, eax); +#endif + + /* Write GUI grant timer (PCI config 0xA3) */ + data2 = FQBQData[i]; + data2 &= 0x0f; + data2 <<= 24; + +#ifdef LINUX_KERNEL + SiS_SetRegLong(0xcf8,0x800000A0); + eax = SiS_GetRegLong(0xcfc); + eax &= 0xf0ffffff; + eax |= data2; + SiS_SetRegLong(0xcfc,eax); +#else + eax = pciReadLong(0x00000000, 0xA0); + eax &= 0xf0ffffff; + eax |= data2; + pciWriteLong(0x00000000, 0xA0, eax); +#endif + + } + + /* Write CRT/CPU threshold low, CRT/Engine threshold high */ + data = ((ThresholdLow & 0x0f) << 4) | 0x0f; + SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data); + + data = (ThresholdLow & 0x10) << 1; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data); + + /* What is this? */ + SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09); + + /* Write CRT/CPU threshold high (gap = 3) */ + data = ThresholdLow + 3; + if(data > 0x0f) data = 0x0f; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data); +} +#endif + +#ifdef SIS315H +static void +SiS_SetCRT1FIFO_310(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo) +{ + USHORT modeflag; + + /* disable auto-threshold */ + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE); + + if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } + + SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0); + if(ModeNo > 0x13) { + if(HwInfo->jChipType >= SIS_661) { + if(!(modeflag & HalfDCLK)) { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34); + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01); + } + } else { + if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) { + SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34); + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01); + } + } + } +} +#endif + +/*********************************************/ +/* MODE REGISTERS */ +/*********************************************/ + +static void +SiS_SetVCLKState(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo, USHORT RefreshRateTableIndex, + USHORT ModeIdIndex) +{ + USHORT data=0, VCLK=0, index=0; + + if(ModeNo > 0x13) { + if(SiS_Pr->UseCustomMode) { + VCLK = SiS_Pr->CSRClock; + } else { + index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwInfo); + VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; + } + } + + if(HwInfo->jChipType < SIS_315H) { + + if(VCLK > 150) data |= 0x80; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data); + + data = 0x00; + if(VCLK >= 150) data |= 0x08; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data); + + } else { + + if(VCLK >= 166) data |= 0x0c; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data); + + if(VCLK >= 166) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7); + } + } + + /* DAC speed */ + if(HwInfo->jChipType >= SIS_661) { + + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10); + + } else { + + data = 0x03; + if((VCLK >= 135) && (VCLK < 160)) data = 0x02; + else if((VCLK >= 160) && (VCLK < 260)) data = 0x01; + else if(VCLK >= 260) data = 0x00; + + if(HwInfo->jChipType == SIS_540) { + if((VCLK == 203) || (VCLK < 234)) data = 0x02; + } + + if(HwInfo->jChipType < SIS_315H) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data); + } else { + if(HwInfo->jChipType > SIS_315PRO) { + if(ModeNo > 0x13) data &= 0xfc; + } + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data); + } + + } +} + +static void +SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex) +{ + USHORT data,infoflag=0,modeflag; + USHORT resindex,xres; +#ifdef SIS315H + USHORT data2,data3; + ULONG longdata; + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; +#endif + + if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + infoflag = SiS_Pr->CInfoFlag; + xres = SiS_Pr->CHDisplay; + } else { + resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex); + if(ModeNo > 0x13) { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag; + xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal; + } else { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + xres = SiS_Pr->SiS_StResInfo[resindex].HTotal; + } + } + + /* Disable DPMS */ + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F); + + data = 0; + if(ModeNo > 0x13) { + if(SiS_Pr->SiS_ModeType > ModeEGA) { + data |= 0x02; + data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2); + } + if(infoflag & InterlaceMode) data |= 0x20; + } + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data); + + if(HwInfo->jChipType != SIS_300) { + data = 0; + if(infoflag & InterlaceMode) { + if(xres <= 800) data = 0x0020; + else if(xres <= 1024) data = 0x0035; + else data = 0x0048; + } + SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,(data & 0xFF)); + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,(data >> 8)); + } + + if(modeflag & HalfDCLK) { + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08); + } + + data = 0; + if(modeflag & LineCompareOff) data = 0x08; + if(HwInfo->jChipType == SIS_300) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data); + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data); + if(SiS_Pr->SiS_ModeType == ModeEGA) { + if(ModeNo > 0x13) { + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x40); + } + } + } + + if(HwInfo->jChipType >= SIS_661) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb); + } + +#ifdef SIS315H + if(HwInfo->jChipType == SIS_315PRO) { + + data = SiS_Get310DRAMType(SiS_Pr, HwInfo); + data = SiS_Pr->SiS_SR15[2][data]; + if(SiS_Pr->SiS_ModeType == ModeText) { + data &= 0xc7; + } else { + data2 = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwInfo); + data2 >>= 1; + if(infoflag & InterlaceMode) data2 >>= 1; + data3 = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex) >> 1; + if(!data3) data3++; + data2 /= data3; + if(data2 >= 0x50) { + data &= 0x0f; + data |= 0x50; + } + } + SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data); + + } else if( (HwInfo->jChipType == SIS_330) || + ((HwInfo->jChipType == SIS_760) && (SiS_Pr->SiS_SysFlags & SF_760LFB))) { + + data = SiS_Get310DRAMType(SiS_Pr, HwInfo); + if(HwInfo->jChipType == SIS_330) { + data = SiS_Pr->SiS_SR15[2][data]; + } else { + if(SiS_Pr->SiS_ROMNew) data = ROMAddr[0xf6]; + else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data]; + else data = 0xba; + } + if(SiS_Pr->SiS_ModeType <= ModeEGA) { + data &= 0xc7; + } else { + if(SiS_Pr->UseCustomMode) { + data2 = SiS_Pr->CSRClock; + } else { + data2 = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwInfo); + data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK; + } + + data3 = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex) >> 1; + if(data3) data2 *= data3; + + longdata = SiS_GetMCLK(SiS_Pr, HwInfo) * 1024; + + data2 = longdata / data2; + + if(HwInfo->jChipType == SIS_330) { + if(SiS_Pr->SiS_ModeType != Mode16Bpp) { + if (data2 >= 0x19c) data = 0xba; + else if(data2 >= 0x140) data = 0x7a; + else if(data2 >= 0x101) data = 0x3a; + else if(data2 >= 0xf5) data = 0x32; + else if(data2 >= 0xe2) data = 0x2a; + else if(data2 >= 0xc4) data = 0x22; + else if(data2 >= 0xac) data = 0x1a; + else if(data2 >= 0x9e) data = 0x12; + else if(data2 >= 0x8e) data = 0x0a; + else data = 0x02; + } else { + if(data2 >= 0x127) data = 0xba; + else data = 0x7a; + } + } else { /* 760+LFB */ + if (data2 >= 0x190) data = 0xba; + else if(data2 >= 0xff) data = 0x7a; + else if(data2 >= 0xd3) data = 0x3a; + else if(data2 >= 0xa9) data = 0x1a; + else if(data2 >= 0x93) data = 0x0a; + else data = 0x02; + } + } + SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data); + } else if(HwInfo->jChipType == SIS_340) { + /* TODO */ + } +#endif + + data = 0x60; + if(SiS_Pr->SiS_ModeType != ModeText) { + data ^= 0x60; + if(SiS_Pr->SiS_ModeType != ModeEGA) { + data ^= 0xA0; + } + } + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data); + + SiS_SetVCLKState(SiS_Pr, HwInfo, ModeNo, RefreshRateTableIndex, ModeIdIndex); + +#ifdef SIS315H + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c); + } else { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c); + } + } +#endif +} + +/*********************************************/ +/* LOAD DAC */ +/*********************************************/ + +#if 0 +static void +SiS_ClearDAC(SiS_Private *SiS_Pr, ULONG port) +{ + int i; + + OutPortByte(port, 0); + port++; + for (i=0; i < (256 * 3); i++) { + OutPortByte(port, 0); + } +} +#endif + +static void +SiS_WriteDAC(SiS_Private *SiS_Pr, SISIOADDRESS DACData, USHORT shiftflag, + USHORT dl, USHORT ah, USHORT al, USHORT dh) +{ + USHORT temp,bh,bl; + + bh = ah; + bl = al; + if(dl != 0) { + temp = bh; + bh = dh; + dh = temp; + if(dl == 1) { + temp = bl; + bl = dh; + dh = temp; + } else { + temp = bl; + bl = bh; + bh = temp; + } + } + if(shiftflag) { + dh <<= 2; + bh <<= 2; + bl <<= 2; + } + SiS_SetRegByte(DACData,(USHORT)dh); + SiS_SetRegByte(DACData,(USHORT)bh); + SiS_SetRegByte(DACData,(USHORT)bl); +} + +void +SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo, USHORT ModeIdIndex) +{ + USHORT data,data2; + USHORT time,i,j,k,m,n,o; + USHORT si,di,bx,dl,al,ah,dh; + USHORT shiftflag; + SISIOADDRESS DACAddr, DACData; + const USHORT *table = NULL; + + if(ModeNo <= 0x13) { + data = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } else { + if(SiS_Pr->UseCustomMode) { + data = SiS_Pr->CModeFlag; + } else { + data = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } + } + + data &= DACInfoFlag; + time = 64; + if(data == 0x00) table = SiS_MDA_DAC; + if(data == 0x08) table = SiS_CGA_DAC; + if(data == 0x10) table = SiS_EGA_DAC; + if(data == 0x18) { + time = 256; + table = SiS_VGA_DAC; + } + if(time == 256) j = 16; + else j = time; + + if( ( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && /* 301B-DH LCD */ + (SiS_Pr->SiS_VBType & VB_NoLCD) ) || + (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) || /* LCDA */ + (!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) { /* Programming CRT1 */ + DACAddr = SiS_Pr->SiS_P3c8; + DACData = SiS_Pr->SiS_P3c9; + shiftflag = 0; + SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF); + } else { + shiftflag = 1; + DACAddr = SiS_Pr->SiS_Part5Port; + DACData = SiS_Pr->SiS_Part5Port + 1; + } + + SiS_SetRegByte(DACAddr,0x00); + + for(i=0; i<j; i++) { + data = table[i]; + for(k=0; k<3; k++) { + data2 = 0; + if(data & 0x01) data2 = 0x2A; + if(data & 0x02) data2 += 0x15; + if(shiftflag) data2 <<= 2; + SiS_SetRegByte(DACData, data2); + data >>= 2; + } + } + + if(time == 256) { + for(i = 16; i < 32; i++) { + data = table[i]; + if(shiftflag) data <<= 2; + for(k = 0; k < 3; k++) SiS_SetRegByte(DACData, data); + } + si = 32; + for(m = 0; m < 9; m++) { + di = si; + bx = si + 4; + dl = 0; + for(n = 0; n < 3; n++) { + for(o = 0; o < 5; o++) { + dh = table[si]; + ah = table[di]; + al = table[bx]; + si++; + SiS_WriteDAC(SiS_Pr, DACData, shiftflag, dl, ah, al, dh); + } + si -= 2; + for(o = 0; o < 3; o++) { + dh = table[bx]; + ah = table[di]; + al = table[si]; + si--; + SiS_WriteDAC(SiS_Pr, DACData, shiftflag, dl, ah, al, dh); + } + dl++; + } /* for n < 3 */ + si += 5; + } /* for m < 9 */ + } +} + +/*********************************************/ +/* SET CRT1 REGISTER GROUP */ +/*********************************************/ + +static void +SiS_SetCRT1Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo, USHORT ModeIdIndex) +{ + USHORT StandTableIndex,RefreshRateTableIndex; + + SiS_Pr->SiS_CRT1Mode = ModeNo; + StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex); + if(SiS_Pr->SiS_SetFlag & LowModeTests) { + if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) { + SiS_DisableBridge(SiS_Pr, HwInfo); + } + } + + SiS_ResetSegmentRegisters(SiS_Pr, HwInfo); + + SiS_SetSeqRegs(SiS_Pr, StandTableIndex, HwInfo); + SiS_SetMiscRegs(SiS_Pr, StandTableIndex, HwInfo); + SiS_SetCRTCRegs(SiS_Pr, HwInfo, StandTableIndex); + SiS_SetATTRegs(SiS_Pr, StandTableIndex, HwInfo); + SiS_SetGRCRegs(SiS_Pr, StandTableIndex); + SiS_ClearExt1Regs(SiS_Pr, HwInfo, ModeNo); + SiS_ResetCRT1VCLK(SiS_Pr, HwInfo); + + SiS_Pr->SiS_SelectCRT2Rate = 0; + SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2); + +#ifdef LINUX_XF86 + xf86DrvMsgVerb(0, X_PROBED, 4, "(init: VBType=0x%04x, VBInfo=0x%04x)\n", + SiS_Pr->SiS_VBType, SiS_Pr->SiS_VBInfo); +#endif + + if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; + } + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; + } + + RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2; + } + + if(RefreshRateTableIndex != 0xFFFF) { + SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex); + SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex); + } + +#ifdef SIS300 + if(HwInfo->jChipType == SIS_300) { + SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo,HwInfo,RefreshRateTableIndex); + } else if((HwInfo->jChipType == SIS_630) || + (HwInfo->jChipType == SIS_730) || + (HwInfo->jChipType == SIS_540)) { + SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, HwInfo, RefreshRateTableIndex); + } +#endif +#ifdef SIS315H + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + } +#endif + + SiS_SetCRT1ModeRegs(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex); + + SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex); + +#ifdef LINUX_KERNEL + if(SiS_Pr->SiS_flag_clearbuffer) { + SiS_ClearBuffer(SiS_Pr,HwInfo,ModeNo); + } +#endif + + if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) { + SiS_WaitRetrace1(SiS_Pr); + SiS_DisplayOn(SiS_Pr); + } +} + +/*********************************************/ +/* HELPER: VIDEO BRIDGE PROG CLK */ +/*********************************************/ + +static void +SiS_ResetVB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT temp; + + /* VB programming clock */ + if(SiS_Pr->SiS_UseROM) { + if(HwInfo->jChipType < SIS_330) { + temp = ROMAddr[VB310Data_1_2_Offset] | 0x40; + if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp); + } else if(HwInfo->jChipType >= SIS_661) { + temp = ROMAddr[0x7e] | 0x40; + if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp); + } + } +} + +/*********************************************/ +/* HELPER: SET VIDEO REGISTERS */ +/*********************************************/ + +static void +SiS_StrangeStuff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + if((IS_SIS651) || (IS_SISM650)) { + SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x3f, 0x00); /* Fiddle with capture regs */ + SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x00, 0x00); + SiS_SetReg(SiS_Pr->SiS_VidPlay, 0x00, 0x86); /* (BIOS does NOT unlock) */ + SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x30, 0xfe); /* Fiddle with video regs */ + SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef); + } + /* !!! This does not support modes < 0x13 !!! */ +} + +/*********************************************/ +/* XFree86: SET SCREEN PITCH */ +/*********************************************/ + +#ifdef LINUX_XF86 +static void +SiS_SetPitchCRT1(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + UShort HDisplay = pSiS->scrnPitch >> 3; + + SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,(HDisplay & 0xFF)); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,(HDisplay>>8)); +} + +static void +SiS_SetPitchCRT2(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + UShort HDisplay = pSiS->scrnPitch2 >> 3; + + /* Unlock CRT2 */ + if(pSiS->VGAEngine == SIS_315_VGA) + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2F, 0x01); + else + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24, 0x01); + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(HDisplay & 0xFF)); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0xF0,(HDisplay >> 8)); +} + +static void +SiS_SetPitch(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + BOOLEAN isslavemode = FALSE; + + if( (pSiS->VBFlags & VB_VIDEOBRIDGE) && + ( ((pSiS->VGAEngine == SIS_300_VGA) && + (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) || + ((pSiS->VGAEngine == SIS_315_VGA) && + (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) { + isslavemode = TRUE; + } + + /* We need to set pitch for CRT1 if bridge is in slave mode, too */ + if((pSiS->VBFlags & DISPTYPE_DISP1) || (isslavemode)) { + SiS_SetPitchCRT1(SiS_Pr, pScrn); + } + /* We must not set the pitch for CRT2 if bridge is in slave mode */ + if((pSiS->VBFlags & DISPTYPE_DISP2) && (!isslavemode)) { + SiS_SetPitchCRT2(SiS_Pr, pScrn); + } +} +#endif + +/*********************************************/ +/* SiSSetMode() */ +/*********************************************/ + +#ifdef LINUX_XF86 +/* We need pScrn for setting the pitch correctly */ +BOOLEAN +SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch) +#else +BOOLEAN +SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo) +#endif +{ + USHORT ModeIdIndex; + SISIOADDRESS BaseAddr = HwInfo->ulIOAddress; + unsigned char backupreg=0; +#ifdef LINUX_KERNEL + USHORT KeepLockReg; + ULONG temp; + + SiS_Pr->UseCustomMode = FALSE; + SiS_Pr->CRT1UsesCustomMode = FALSE; +#endif + + if(SiS_Pr->UseCustomMode) { + ModeNo = 0xfe; + } + + SiSInitPtr(SiS_Pr, HwInfo); + SiSRegInit(SiS_Pr, BaseAddr); + SiS_GetSysFlags(SiS_Pr, HwInfo); + +#if defined(LINUX_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__)) + if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff); + else +#endif + SiS_Pr->SiS_VGAINFO = 0x11; + + SiSInitPCIetc(SiS_Pr, HwInfo); + SiSSetLVDSetc(SiS_Pr, HwInfo); + SiSDetermineROMUsage(SiS_Pr, HwInfo); + + SiS_Pr->SiS_flag_clearbuffer = 0; + + if(!SiS_Pr->UseCustomMode) { +#ifdef LINUX_KERNEL + if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1; +#endif + ModeNo &= 0x7f; + } + +#ifdef LINUX_KERNEL + KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05); +#endif + SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86); + + SiS_UnLockCRT2(SiS_Pr, HwInfo); + + if(!SiS_Pr->UseCustomMode) { + if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE; + } else { + ModeIdIndex = 0; + } + + SiS_GetVBType(SiS_Pr, HwInfo); + + /* Init/restore some VB registers */ + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwInfo->jChipType >= SIS_315H) { + SiS_ResetVB(SiS_Pr, HwInfo); + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10); + SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c); + backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + } else { + backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + } + } + + /* Get VB information (connectors, connected devices) */ + SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, (SiS_Pr->UseCustomMode) ? 0 : 1); + SiS_SetYPbPr(SiS_Pr, HwInfo); + SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo); + +#ifdef LINUX_KERNEL + /* 3. Check memory size (Kernel framebuffer driver only) */ + temp = SiS_CheckMemorySize(SiS_Pr, HwInfo, ModeNo, ModeIdIndex); + if(!temp) return(0); +#endif + + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetupCR5x(SiS_Pr, HwInfo); + } + + if(SiS_Pr->UseCustomMode) { + SiS_Pr->CRT1UsesCustomMode = TRUE; + SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock; + SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag; + } else { + SiS_Pr->CRT1UsesCustomMode = FALSE; + } + + /* Set mode on CRT1 */ + if( (SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) || + (!(SiS_Pr->SiS_VBInfo & SwitchCRT2)) ) { + SiS_SetCRT1Group(SiS_Pr, HwInfo, ModeNo, ModeIdIndex); + } + + /* Set mode on CRT2 */ + if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA)) { + if( (SiS_Pr->SiS_VBType & VB_SISVB) || + (SiS_Pr->SiS_IF_DEF_LVDS == 1) || + (SiS_Pr->SiS_IF_DEF_CH70xx != 0) || + (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) { + SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo); + } + } + + SiS_HandleCRT1(SiS_Pr); + + SiS_StrangeStuff(SiS_Pr, HwInfo); + + SiS_DisplayOn(SiS_Pr); + SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF); + + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb); + } + } + } + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwInfo->jChipType >= SIS_315H) { + if(!SiS_Pr->SiS_ROMNew) { + if(SiS_IsVAMode(SiS_Pr,HwInfo)) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01); + } else { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE); + } + } + + SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg); + + if((IS_SIS650) && (SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0xfc)) { + if((ModeNo == 0x03) || (ModeNo == 0x10)) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80); + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x56,0x08); + } + } + + if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc); + } + } else if((HwInfo->jChipType == SIS_630) || + (HwInfo->jChipType == SIS_730)) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg); + } + } + +#ifdef LINUX_XF86 + if(pScrn) { + /* SetPitch: Adapt to virtual size & position */ + if((ModeNo > 0x13) && (dosetpitch)) { + SiS_SetPitch(SiS_Pr, pScrn); + } + + /* Backup/Set ModeNo in BIOS scratch area */ + SiS_GetSetModeID(pScrn, ModeNo); + } +#endif + +#ifdef LINUX_KERNEL /* We never lock registers in XF86 */ + if(KeepLockReg == 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86); + else SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00); +#endif + + return TRUE; +} + +/*********************************************/ +/* XFree86: SiSBIOSSetMode() */ +/* for non-Dual-Head mode */ +/*********************************************/ + +#ifdef LINUX_XF86 +BOOLEAN +SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn, + DisplayModePtr mode, BOOLEAN IsCustom) +{ + SISPtr pSiS = SISPTR(pScrn); + UShort ModeNo = 0; + + SiS_Pr->UseCustomMode = FALSE; + + if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) { + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting custom mode %dx%d\n", + SiS_Pr->CHDisplay, + (mode->Flags & V_INTERLACE ? SiS_Pr->CVDisplay * 2 : + (mode->Flags & V_DBLSCAN ? SiS_Pr->CVDisplay / 2 : + SiS_Pr->CVDisplay))); + + } else { + + /* Don't need vbflags here; checks done earlier */ + ModeNo = SiS_GetModeNumber(pScrn, mode, 0); + if(!ModeNo) return FALSE; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting standard mode 0x%x\n", ModeNo); + + } + + return(SiSSetMode(SiS_Pr, HwInfo, pScrn, ModeNo, TRUE)); +} + +/*********************************************/ +/* XFree86: SiSBIOSSetModeCRT2() */ +/* for Dual-Head modes */ +/*********************************************/ +BOOLEAN +SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn, + DisplayModePtr mode, BOOLEAN IsCustom) +{ + USHORT ModeIdIndex; + SISIOADDRESS BaseAddr = HwInfo->ulIOAddress; + UShort ModeNo = 0; + unsigned char backupreg=0; + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + SiS_Pr->UseCustomMode = FALSE; + + /* Remember: Custom modes for CRT2 are ONLY supported + * -) on the 30x/B/C, and + * -) if CRT2 is LCD or VGA, or CRT1 is LCDA + */ + + if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) { + + ModeNo = 0xfe; + + } else { + + ModeNo = SiS_GetModeNumber(pScrn, mode, 0); + if(!ModeNo) return FALSE; + + } + + SiSRegInit(SiS_Pr, BaseAddr); + SiSInitPtr(SiS_Pr, HwInfo); + SiS_GetSysFlags(SiS_Pr, HwInfo); +#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__)) + SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff); +#else + SiS_Pr->SiS_VGAINFO = 0x11; +#endif + SiSInitPCIetc(SiS_Pr, HwInfo); + SiSSetLVDSetc(SiS_Pr, HwInfo); + SiSDetermineROMUsage(SiS_Pr, HwInfo); + + /* Save mode info so we can set it from within SetMode for CRT1 */ +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + pSiSEnt->CRT2ModeNo = ModeNo; + pSiSEnt->CRT2DMode = mode; + pSiSEnt->CRT2IsCustom = IsCustom; + pSiSEnt->CRT2CR30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + pSiSEnt->CRT2CR31 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31); + pSiSEnt->CRT2CR35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + pSiSEnt->CRT2CR38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); +#if 0 + /* We can't set CRT2 mode before CRT1 mode is set */ + if(pSiSEnt->CRT1ModeNo == -1) { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Setting CRT2 mode delayed until after setting CRT1 mode\n"); + return TRUE; + } +#endif + pSiSEnt->CRT2ModeSet = TRUE; + } +#endif + + /* We don't clear the buffer in X */ + SiS_Pr->SiS_flag_clearbuffer=0; + + if(SiS_Pr->UseCustomMode) { + + USHORT temptemp = SiS_Pr->CVDisplay; + + if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1; + else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Setting custom mode %dx%d on CRT2\n", + SiS_Pr->CHDisplay, temptemp); + + } else { + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Setting standard mode 0x%x on CRT2\n", ModeNo); + + } + + SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86); + + SiS_UnLockCRT2(SiS_Pr, HwInfo); + + if(!SiS_Pr->UseCustomMode) { + if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE; + } else { + ModeIdIndex = 0; + } + + SiS_GetVBType(SiS_Pr, HwInfo); + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwInfo->jChipType >= SIS_315H) { + SiS_ResetVB(SiS_Pr, HwInfo); + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10); + SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c); + backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + } else { + backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + } + } + + /* Get VB information (connectors, connected devices) */ + if(!SiS_Pr->UseCustomMode) { + SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 1); + } else { + /* If this is a custom mode, we don't check the modeflag for CRT2Mode */ + SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 0); + } + SiS_SetYPbPr(SiS_Pr, HwInfo); + SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo); + + /* Set mode on CRT2 */ + if( (SiS_Pr->SiS_VBType & VB_SISVB) || + (SiS_Pr->SiS_IF_DEF_LVDS == 1) || + (SiS_Pr->SiS_IF_DEF_CH70xx != 0) || + (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) { + SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo); + } + + SiS_StrangeStuff(SiS_Pr, HwInfo); + + SiS_DisplayOn(SiS_Pr); + SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF); + + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb); + } + } + } + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwInfo->jChipType >= SIS_315H) { + if(!SiS_Pr->SiS_ROMNew) { + if(SiS_IsVAMode(SiS_Pr,HwInfo)) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01); + } else { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE); + } + } + + SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg); + + if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc); + } + } else if((HwInfo->jChipType == SIS_630) || + (HwInfo->jChipType == SIS_730)) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg); + } + } + + /* SetPitch: Adapt to virtual size & position */ + SiS_SetPitchCRT2(SiS_Pr, pScrn); + + return TRUE; +} + +/*********************************************/ +/* XFree86: SiSBIOSSetModeCRT1() */ +/* for Dual-Head modes */ +/*********************************************/ + +BOOLEAN +SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn, + DisplayModePtr mode, BOOLEAN IsCustom) +{ + SISPtr pSiS = SISPTR(pScrn); + SISIOADDRESS BaseAddr = HwInfo->ulIOAddress; + USHORT ModeIdIndex, ModeNo=0; + UCHAR backupreg=0; +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; + UCHAR backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0; + BOOLEAN backupcustom; +#endif + + SiS_Pr->UseCustomMode = FALSE; + + if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) { + + USHORT temptemp = SiS_Pr->CVDisplay; + + if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1; + else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Setting custom mode %dx%d on CRT1\n", + SiS_Pr->CHDisplay, temptemp); + ModeNo = 0xfe; + + } else { + + ModeNo = SiS_GetModeNumber(pScrn, mode, 0); + if(!ModeNo) return FALSE; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Setting standard mode 0x%x on CRT1\n", ModeNo); + } + + SiSInitPtr(SiS_Pr, HwInfo); + SiSRegInit(SiS_Pr, BaseAddr); + SiS_GetSysFlags(SiS_Pr, HwInfo); +#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__)) + SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff); +#else + SiS_Pr->SiS_VGAINFO = 0x11; +#endif + SiSInitPCIetc(SiS_Pr, HwInfo); + SiSSetLVDSetc(SiS_Pr, HwInfo); + SiSDetermineROMUsage(SiS_Pr, HwInfo); + + /* We don't clear the buffer in X */ + SiS_Pr->SiS_flag_clearbuffer = 0; + + SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86); + + SiS_UnLockCRT2(SiS_Pr, HwInfo); + + if(!SiS_Pr->UseCustomMode) { + if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE; + } else { + ModeIdIndex = 0; + } + + /* Determine VBType */ + SiS_GetVBType(SiS_Pr, HwInfo); + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwInfo->jChipType >= SIS_315H) { + backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + } else { + backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + } + } + + /* Get VB information (connectors, connected devices) */ + /* (We don't care if the current mode is a CRT2 mode) */ + SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 0); + SiS_SetYPbPr(SiS_Pr, HwInfo); + SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo); + + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetupCR5x(SiS_Pr, HwInfo); + } + + /* Set mode on CRT1 */ + SiS_SetCRT1Group(SiS_Pr, HwInfo, ModeNo, ModeIdIndex); + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo); + } + + /* SetPitch: Adapt to virtual size & position */ + SiS_SetPitchCRT1(SiS_Pr, pScrn); + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + pSiSEnt->CRT1ModeNo = ModeNo; + pSiSEnt->CRT1DMode = mode; + } +#endif + + if(SiS_Pr->UseCustomMode) { + SiS_Pr->CRT1UsesCustomMode = TRUE; + SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock; + SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag; + } else { + SiS_Pr->CRT1UsesCustomMode = FALSE; + } + + /* Reset CRT2 if changing mode on CRT1 */ +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(pSiSEnt->CRT2ModeNo != -1) { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "(Re-)Setting mode for CRT2\n"); + backupcustom = SiS_Pr->UseCustomMode; + backupcr30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + backupcr31 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31); + backupcr35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + backupcr38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + if(SiS_Pr->SiS_VBType & VB_SISVB) { + /* Backup LUT-enable */ + if(pSiSEnt->CRT2ModeSet) { + backupp40d = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0d) & 0x08; + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,pSiSEnt->CRT2CR30); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,pSiSEnt->CRT2CR31); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,pSiSEnt->CRT2CR35); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,pSiSEnt->CRT2CR38); + } + SiSBIOSSetModeCRT2(SiS_Pr, HwInfo, pSiSEnt->pScrn_1, + pSiSEnt->CRT2DMode, pSiSEnt->CRT2IsCustom); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,backupcr30); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,backupcr31); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupcr35); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupcr38); + if(SiS_Pr->SiS_VBType & VB_SISVB) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d, ~0x08, backupp40d); + } + SiS_Pr->UseCustomMode = backupcustom; + } + } +#endif + + /* Warning: From here, the custom mode entries in SiS_Pr are + * possibly overwritten + */ + + SiS_HandleCRT1(SiS_Pr); + + SiS_StrangeStuff(SiS_Pr, HwInfo); + + SiS_DisplayOn(SiS_Pr); + SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF); + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg); + } else if((HwInfo->jChipType == SIS_630) || + (HwInfo->jChipType == SIS_730)) { + SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg); + } + } + + /* Backup/Set ModeNo in BIOS scratch area */ + SiS_GetSetModeID(pScrn,ModeNo); + + return TRUE; +} +#endif /* Linux_XF86 */ + + +#ifdef LINUX_XF86 +BOOLEAN +SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + const USHORT PanelTypeTable300[16] = { + 0xc101, 0xc117, 0x0121, 0xc135, 0xc142, 0xc152, 0xc162, 0xc072, + 0xc181, 0xc192, 0xc1a1, 0xc1b6, 0xc1c2, 0xc0d2, 0xc1e2, 0xc1f2 + }; + const USHORT PanelTypeTable31030x[16] = { + 0xc102, 0xc112, 0x0122, 0xc132, 0xc142, 0xc152, 0xc169, 0xc179, + 0x0189, 0xc192, 0xc1a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + }; + const USHORT PanelTypeTable310LVDS[16] = { + 0xc111, 0xc122, 0xc133, 0xc144, 0xc155, 0xc166, 0xc177, 0xc188, + 0xc199, 0xc0aa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + }; + USHORT tempax,tempbx,temp; + + if(HwInfo->jChipType < SIS_315H) { + + tempax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18); + tempbx = tempax & 0x0F; + if(!(tempax & 0x10)){ + if(SiS_Pr->SiS_IF_DEF_LVDS == 1){ + tempbx = 0; + temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x38); + if(temp & 0x40) tempbx |= 0x08; + if(temp & 0x20) tempbx |= 0x02; + if(temp & 0x01) tempbx |= 0x01; + temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x39); + if(temp & 0x80) tempbx |= 0x04; + } else { + return 0; + } + } + tempbx = PanelTypeTable300[tempbx]; + tempbx |= LCDSync; + temp = tempbx & 0x00FF; + SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,temp); + temp = (tempbx & 0xFF00) >> 8; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,~(LCDSyncBit|LCDRGB18Bit),temp); + + } else { + + if(HwInfo->jChipType >= SIS_661) return 0; + + tempax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1a); + tempax &= 0x1e; + tempax >>= 1; + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(tempax == 0) { + /* TODO: Include HUGE detection routine + (Probably not worth bothering) + */ + return 0; + } + temp = tempax & 0xff; + tempax--; + tempbx = PanelTypeTable310LVDS[tempax]; + } else { + tempbx = PanelTypeTable31030x[tempax]; + temp = tempbx & 0xff; + } + SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,temp); + tempbx = (tempbx & 0xff00) >> 8; + temp = tempbx & 0xc1; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,~(LCDSyncBit|LCDRGB18Bit),temp); + if(SiS_Pr->SiS_VBType & VB_SISVB) { + temp = tempbx & 0x04; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x39,0xfb,temp); + } + + } + return 1; +} +#endif + +#ifndef GETBITSTR +#define BITMASK(h,l) (((unsigned)(1U << ((h)-(l)+1))-1)<<(l)) +#define GENMASK(mask) BITMASK(1?mask,0?mask) +#define GETBITS(var,mask) (((var) & GENMASK(mask)) >> (0?mask)) +#define GETBITSTR(val,from,to) ((GETBITS(val,from)) << (0?to)) +#endif + +static void +SiS_CalcCRRegisters(SiS_Private *SiS_Pr, int depth) +{ + SiS_Pr->CCRT1CRTC[0] = ((SiS_Pr->CHTotal >> 3) - 5) & 0xff; /* CR0 */ + SiS_Pr->CCRT1CRTC[1] = (SiS_Pr->CHDisplay >> 3) - 1; /* CR1 */ + SiS_Pr->CCRT1CRTC[2] = (SiS_Pr->CHBlankStart >> 3) - 1; /* CR2 */ + SiS_Pr->CCRT1CRTC[3] = (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80; /* CR3 */ + SiS_Pr->CCRT1CRTC[4] = (SiS_Pr->CHSyncStart >> 3) + 3; /* CR4 */ + SiS_Pr->CCRT1CRTC[5] = ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) | /* CR5 */ + (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F); + + SiS_Pr->CCRT1CRTC[6] = (SiS_Pr->CVTotal - 2) & 0xFF; /* CR6 */ + SiS_Pr->CCRT1CRTC[7] = (((SiS_Pr->CVTotal - 2) & 0x100) >> 8) /* CR7 */ + | (((SiS_Pr->CVDisplay - 1) & 0x100) >> 7) + | ((SiS_Pr->CVSyncStart & 0x100) >> 6) + | (((SiS_Pr->CVBlankStart - 1) & 0x100) >> 5) + | 0x10 + | (((SiS_Pr->CVTotal - 2) & 0x200) >> 4) + | (((SiS_Pr->CVDisplay - 1) & 0x200) >> 3) + | ((SiS_Pr->CVSyncStart & 0x200) >> 2); + + SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); /* CR9 */ + + if(depth != 8) { + if(SiS_Pr->CHDisplay >= 1600) SiS_Pr->CCRT1CRTC[16] |= 0x60; /* SRE */ + else if(SiS_Pr->CHDisplay >= 640) SiS_Pr->CCRT1CRTC[16] |= 0x40; + } + +#if 0 + if (mode->VScan >= 32) + regp->CRTC[9] |= 0x1F; + else if (mode->VScan > 1) + regp->CRTC[9] |= mode->VScan - 1; +#endif + + SiS_Pr->CCRT1CRTC[8] = (SiS_Pr->CVSyncStart ) & 0xFF; /* CR10 */ + SiS_Pr->CCRT1CRTC[9] = ((SiS_Pr->CVSyncEnd ) & 0x0F) | 0x80; /* CR11 */ + SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay - 1) & 0xFF; /* CR12 */ + SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF; /* CR15 */ + SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd - 1) & 0xFF; /* CR16 */ + + SiS_Pr->CCRT1CRTC[13] = /* SRA */ + GETBITSTR((SiS_Pr->CVTotal -2), 10:10, 0:0) | + GETBITSTR((SiS_Pr->CVDisplay -1), 10:10, 1:1) | + GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) | + GETBITSTR((SiS_Pr->CVSyncStart ), 10:10, 3:3) | + GETBITSTR((SiS_Pr->CVBlankEnd -1), 8:8, 4:4) | + GETBITSTR((SiS_Pr->CVSyncEnd ), 4:4, 5:5) ; + + SiS_Pr->CCRT1CRTC[14] = /* SRB */ + GETBITSTR((SiS_Pr->CHTotal >> 3) - 5, 9:8, 1:0) | + GETBITSTR((SiS_Pr->CHDisplay >> 3) - 1, 9:8, 3:2) | + GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) | + GETBITSTR((SiS_Pr->CHSyncStart >> 3) + 3, 9:8, 7:6) ; + + + SiS_Pr->CCRT1CRTC[15] = /* SRC */ + GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) | + GETBITSTR((SiS_Pr->CHSyncEnd >> 3) + 3, 5:5, 2:2) ; +} + +void +SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT modeflag, tempax, tempbx, VGAHDE = SiS_Pr->SiS_VGAHDE; + int i,j; + + /* 1:1 data: use data set by setcrt1crtc() */ + if(SiS_Pr->SiS_LCDInfo & LCDPass11) return; + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } else if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } + + if(modeflag & HalfDCLK) VGAHDE >>= 1; + + SiS_Pr->CHDisplay = VGAHDE; + SiS_Pr->CHBlankStart = VGAHDE; + + SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE; + SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE; + + tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes; + tempax = SiS_Pr->SiS_VGAHDE; /* not /2 ! */ + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + tempax = SiS_Pr->PanelXRes; + } + tempbx += tempax; + if(modeflag & HalfDCLK) tempbx -= VGAHDE; + SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx; + + tempax = VGAHDE; + tempbx = SiS_Pr->CHTotal; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + tempbx = SiS_Pr->PanelXRes; + if(modeflag & HalfDCLK) tempbx >>= 1; + tempax += ((tempbx - tempax) >> 1); + } + + tempax += SiS_Pr->PanelHRS; + SiS_Pr->CHSyncStart = tempax; + tempax += SiS_Pr->PanelHRE; + SiS_Pr->CHSyncEnd = tempax; + + tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes; + tempax = SiS_Pr->SiS_VGAVDE; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + tempax = SiS_Pr->PanelYRes; + } + SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax; + + tempax = SiS_Pr->SiS_VGAVDE; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + tempax += (SiS_Pr->PanelYRes - tempax) >> 1; + } + tempax += SiS_Pr->PanelVRS; + SiS_Pr->CVSyncStart = tempax; + tempax += SiS_Pr->PanelVRE; + SiS_Pr->CVSyncEnd = tempax; + + SiS_CalcCRRegisters(SiS_Pr, 8); + SiS_Pr->CCRT1CRTC[16] &= ~0xE0; + + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); + + for(i=0,j=0;i<=7;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]); + } + for(j=0x10;i<=10;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]); + } + for(j=0x15;i<=12;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]); + } + for(j=0x0A;i<=15;i++,j++) { + SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]); + } + + tempax = SiS_Pr->CCRT1CRTC[16] & 0xE0; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1F,tempax); + + tempax = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5; + if(modeflag & DoubleScanMode) tempax |= 0x80; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax); + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "%d %d %d %d %d %d %d %d (%d %d %d %d)\n", + SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal, + SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal, + SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd); + + xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n", + SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1], + SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3], + SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5], + SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]); + xf86DrvMsg(0, X_INFO, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n", + SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9], + SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11], + SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13], + SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]); + xf86DrvMsg(0, X_INFO, " 0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]); +#endif +} + +#ifdef LINUX_XF86 + +void +SiS_MakeClockRegs(ScrnInfoPtr pScrn, int clock, UCHAR *p2b, UCHAR *p2c) +{ + int out_n, out_dn, out_div, out_sbit, out_scale; + unsigned int vclk[5]; + +#define Midx 0 +#define Nidx 1 +#define VLDidx 2 +#define Pidx 3 +#define PSNidx 4 + + if(SiS_compute_vclk(clock, &out_n, &out_dn, &out_div, &out_sbit, &out_scale)) { + (*p2b) = (out_div == 2) ? 0x80 : 0x00; + (*p2b) |= ((out_n - 1) & 0x7f); + (*p2c) = (out_dn - 1) & 0x1f; + (*p2c) |= (((out_scale - 1) & 3) << 5); + (*p2c) |= ((out_sbit & 0x01) << 7); +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sb %d sc %d\n", + clock, out_n, out_dn, out_div, out_sbit, out_scale); +#endif + } else { + SiSCalcClock(pScrn, clock, 2, vclk); + (*p2b) = (vclk[VLDidx] == 2) ? 0x80 : 0x00; + (*p2b) |= (vclk[Midx] - 1) & 0x7f; + (*p2c) = (vclk[Nidx] - 1) & 0x1f; + if(vclk[Pidx] <= 4) { + /* postscale 1,2,3,4 */ + (*p2c) |= ((vclk[Pidx] - 1) & 3) << 5; + } else { + /* postscale 6,8 */ + (*p2c) |= (((vclk[Pidx] / 2) - 1) & 3) << 5; + (*p2c) |= 0x80; + } +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sc %d\n", + clock, vclk[Midx], vclk[Nidx], vclk[VLDidx], vclk[Pidx]); +#endif + } +} + +#endif + +/* ================ XFREE86/X.ORG ================= */ + +/* Helper functions */ + +#ifdef LINUX_XF86 + +USHORT +SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags) +{ + SISPtr pSiS = SISPTR(pScrn); + int depth = pSiS->CurrentLayout.bitsPerPixel; + + pSiS->SiS_Pr->CModeFlag = 0; + + pSiS->SiS_Pr->CDClock = mode->Clock; + + pSiS->SiS_Pr->CHDisplay = mode->HDisplay; + pSiS->SiS_Pr->CHSyncStart = mode->HSyncStart; + pSiS->SiS_Pr->CHSyncEnd = mode->HSyncEnd; + pSiS->SiS_Pr->CHTotal = mode->HTotal; + + pSiS->SiS_Pr->CVDisplay = mode->VDisplay; + pSiS->SiS_Pr->CVSyncStart = mode->VSyncStart; + pSiS->SiS_Pr->CVSyncEnd = mode->VSyncEnd; + pSiS->SiS_Pr->CVTotal = mode->VTotal; + + pSiS->SiS_Pr->CFlags = mode->Flags; + + if(pSiS->SiS_Pr->CFlags & V_INTERLACE) { + pSiS->SiS_Pr->CVDisplay >>= 1; + pSiS->SiS_Pr->CVSyncStart >>= 1; + pSiS->SiS_Pr->CVSyncEnd >>= 1; + pSiS->SiS_Pr->CVTotal >>= 1; + } + if(pSiS->SiS_Pr->CFlags & V_DBLSCAN) { + /* pSiS->SiS_Pr->CDClock <<= 1; */ + pSiS->SiS_Pr->CVDisplay <<= 1; + pSiS->SiS_Pr->CVSyncStart <<= 1; + pSiS->SiS_Pr->CVSyncEnd <<= 1; + pSiS->SiS_Pr->CVTotal <<= 1; + } + + pSiS->SiS_Pr->CHBlankStart = pSiS->SiS_Pr->CHDisplay; + pSiS->SiS_Pr->CHBlankEnd = pSiS->SiS_Pr->CHTotal; + pSiS->SiS_Pr->CVBlankStart = pSiS->SiS_Pr->CVSyncStart - 1; + pSiS->SiS_Pr->CVBlankEnd = pSiS->SiS_Pr->CVTotal; + + SiS_MakeClockRegs(pScrn, pSiS->SiS_Pr->CDClock, &pSiS->SiS_Pr->CSR2B, &pSiS->SiS_Pr->CSR2C); + + pSiS->SiS_Pr->CSRClock = (pSiS->SiS_Pr->CDClock / 1000) + 1; + + SiS_CalcCRRegisters(pSiS->SiS_Pr, depth); + + switch(depth) { + case 8: pSiS->SiS_Pr->CModeFlag |= 0x223b; break; + case 16: pSiS->SiS_Pr->CModeFlag |= 0x227d; break; + case 32: pSiS->SiS_Pr->CModeFlag |= 0x22ff; break; + default: return 0; + } + + if(pSiS->SiS_Pr->CFlags & V_DBLSCAN) + pSiS->SiS_Pr->CModeFlag |= DoubleScanMode; + + if((pSiS->SiS_Pr->CVDisplay >= 1024) || + (pSiS->SiS_Pr->CVTotal >= 1024) || + (pSiS->SiS_Pr->CHDisplay >= 1024)) + pSiS->SiS_Pr->CModeFlag |= LineCompareOff; + + if(pSiS->SiS_Pr->CFlags & V_CLKDIV2) + pSiS->SiS_Pr->CModeFlag |= HalfDCLK; + + pSiS->SiS_Pr->CInfoFlag = 0x0007; + + if(pSiS->SiS_Pr->CFlags & V_NHSYNC) + pSiS->SiS_Pr->CInfoFlag |= 0x4000; + + if(pSiS->SiS_Pr->CFlags & V_NVSYNC) + pSiS->SiS_Pr->CInfoFlag |= 0x8000; + + if(pSiS->SiS_Pr->CFlags & V_INTERLACE) + pSiS->SiS_Pr->CInfoFlag |= InterlaceMode; + + pSiS->SiS_Pr->UseCustomMode = TRUE; +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "Custom mode %dx%d:\n", + pSiS->SiS_Pr->CHDisplay,pSiS->SiS_Pr->CVDisplay); + xf86DrvMsg(0, X_INFO, "Modeflag %04x, Infoflag %04x\n", + pSiS->SiS_Pr->CModeFlag, pSiS->SiS_Pr->CInfoFlag); + xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n", + pSiS->SiS_Pr->CCRT1CRTC[0], pSiS->SiS_Pr->CCRT1CRTC[1], + pSiS->SiS_Pr->CCRT1CRTC[2], pSiS->SiS_Pr->CCRT1CRTC[3], + pSiS->SiS_Pr->CCRT1CRTC[4], pSiS->SiS_Pr->CCRT1CRTC[5], + pSiS->SiS_Pr->CCRT1CRTC[6], pSiS->SiS_Pr->CCRT1CRTC[7]); + xf86DrvMsg(0, X_INFO, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n", + pSiS->SiS_Pr->CCRT1CRTC[8], pSiS->SiS_Pr->CCRT1CRTC[9], + pSiS->SiS_Pr->CCRT1CRTC[10], pSiS->SiS_Pr->CCRT1CRTC[11], + pSiS->SiS_Pr->CCRT1CRTC[12], pSiS->SiS_Pr->CCRT1CRTC[13], + pSiS->SiS_Pr->CCRT1CRTC[14], pSiS->SiS_Pr->CCRT1CRTC[15]); + xf86DrvMsg(0, X_INFO, " 0x%02x}},\n", pSiS->SiS_Pr->CCRT1CRTC[16]); + xf86DrvMsg(0, X_INFO, "Clock: 0x%02x, 0x%02x, %d\n", + pSiS->SiS_Pr->CSR2B, pSiS->SiS_Pr->CSR2C, pSiS->SiS_Pr->CSRClock); +#endif + return 1; +} + +int +SiS_FindPanelFromDB(SISPtr pSiS, USHORT panelvendor, USHORT panelproduct, int *maxx, int *maxy, int *prefx, int *prefy) +{ + int i, j; + BOOLEAN done = FALSE; + + i = 0; + while((!done) && (SiS_PlasmaTable[i].vendor) && panelvendor) { + if(SiS_PlasmaTable[i].vendor == panelvendor) { + for(j=0; j<SiS_PlasmaTable[i].productnum; j++) { + if(SiS_PlasmaTable[i].product[j] == panelproduct) { + if(SiS_PlasmaTable[i].maxx && SiS_PlasmaTable[i].maxy) { + (*maxx) = (int)SiS_PlasmaTable[i].maxx; + (*maxy) = (int)SiS_PlasmaTable[i].maxy; + (*prefx) = (int)SiS_PlasmaTable[i].prefx; + (*prefy) = (int)SiS_PlasmaTable[i].prefy; + done = TRUE; + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + "Identified %s, correcting max X res %d, max Y res %d\n", + SiS_PlasmaTable[i].plasmaname, + SiS_PlasmaTable[i].maxx, SiS_PlasmaTable[i].maxy); + break; + } + } + } + } + i++; + } + return (done) ? 1 : 0; +} + +/* Build a list of supported modes: + * Built-in modes for which we have all data are M_T_DEFAULT, + * modes derived from DDC or database data are M_T_BUILTIN + */ +DisplayModePtr +SiSBuildBuiltInModeList(ScrnInfoPtr pScrn, BOOLEAN includelcdmodes, BOOLEAN isfordvi) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned short VRE, VBE, VRS, VBS, VDE, VT; + unsigned short HRE, HBE, HRS, HBS, HDE, HT; + unsigned char sr_data, cr_data, cr_data2, cr_data3; + unsigned char sr2b, sr2c; + float num, denum, postscalar, divider; + int A, B, C, D, E, F, temp, i, j, k, l, index, vclkindex; + DisplayModePtr new = NULL, current = NULL, first = NULL; + BOOLEAN done = FALSE; +#if 0 + DisplayModePtr backup = NULL; +#endif + + pSiS->backupmodelist = NULL; + pSiS->AddedPlasmaModes = FALSE; + + /* Initialize our pointers */ + if(pSiS->VGAEngine == SIS_300_VGA) { +#ifdef SIS300 + InitTo300Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext); +#else + return NULL; +#endif + } else if(pSiS->VGAEngine == SIS_315_VGA) { +#ifdef SIS315H + InitTo310Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext); +#else + return NULL; +#endif + } else return NULL; + + i = 0; + while(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag != 0xFFFF) { + + index = pSiS->SiS_Pr->SiS_RefIndex[i].Ext_CRT1CRTC; + + /* 0x5a (320x240) is a pure FTSN mode, not DSTN! */ + if((!pSiS->FSTN) && + (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID == 0x5a)) { + i++; + continue; + } + if((pSiS->FSTN) && + (pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) && + (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 240) && + (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID != 0x5a)) { + i++; + continue; + } + + if(!(new = xalloc(sizeof(DisplayModeRec)))) return first; + memset(new, 0, sizeof(DisplayModeRec)); + if(!(new->name = xalloc(10))) { + xfree(new); + return first; + } + if(!first) first = new; + if(current) { + current->next = new; + new->prev = current; + } + + current = new; + + sprintf(current->name, "%dx%d", pSiS->SiS_Pr->SiS_RefIndex[i].XRes, + pSiS->SiS_Pr->SiS_RefIndex[i].YRes); + + current->status = MODE_OK; + + current->type = M_T_DEFAULT; + + vclkindex = pSiS->SiS_Pr->SiS_RefIndex[i].Ext_CRTVCLK; + if(pSiS->VGAEngine == SIS_300_VGA) vclkindex &= 0x3F; + + sr2b = pSiS->SiS_Pr->SiS_VCLKData[vclkindex].SR2B; + sr2c = pSiS->SiS_Pr->SiS_VCLKData[vclkindex].SR2C; + + divider = (sr2b & 0x80) ? 2.0 : 1.0; + postscalar = (sr2c & 0x80) ? + ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0) : (((sr2c >> 5) & 0x03) + 1.0); + num = (sr2b & 0x7f) + 1.0; + denum = (sr2c & 0x1f) + 1.0; + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "------------\n"); + xf86DrvMsg(0, X_INFO, "sr2b: %x sr2c %x div %f ps %f num %f denum %f\n", + sr2b, sr2c, divider, postscalar, num, denum); +#endif + + current->Clock = (int)(14318 * (divider / postscalar) * (num / denum)); + + sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[14]; + /* inSISIDXREG(SISSR, 0x0b, sr_data); */ + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[0]; + /* inSISIDXREG(SISCR, 0x00, cr_data); */ + + /* Horizontal total */ + HT = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x03) << 8); + A = HT + 5; + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[1]; + /* inSISIDXREG(SISCR, 0x01, cr_data); */ + + /* Horizontal display enable end */ + HDE = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x0C) << 6); + E = HDE + 1; /* 0x80 0x64 */ + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[4]; + /* inSISIDXREG(SISCR, 0x04, cr_data); */ + + /* Horizontal retrace (=sync) start */ + HRS = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0xC0) << 2); + F = HRS - E - 3; /* 0x06 0x06 */ + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[2]; + /* inSISIDXREG(SISCR, 0x02, cr_data); */ + + /* Horizontal blank start */ + HBS = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x30) << 4); + + sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[15]; + /* inSISIDXREG(SISSR, 0x0c, sr_data); */ + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[3]; + /* inSISIDXREG(SISCR, 0x03, cr_data); */ + + cr_data2 = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[5]; + /* inSISIDXREG(SISCR, 0x05, cr_data2); */ + + /* Horizontal blank end */ + HBE = (cr_data & 0x1f) | + ((unsigned short) (cr_data2 & 0x80) >> 2) | + ((unsigned short) (sr_data & 0x03) << 6); + + /* Horizontal retrace (=sync) end */ + HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3); + + temp = HBE - ((E - 1) & 255); + B = (temp > 0) ? temp : (temp + 256); + + temp = HRE - ((E + F + 3) & 63); + C = (temp > 0) ? temp : (temp + 64); /* 0x0b 0x0b */ + + D = B - F - C; + + if((pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) && + ((pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 200) || + (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 240))) { + + /* Terrible hack, but correct CRTC data for + * these modes only produces a black screen... + * (HRE is 0, leading into a too large C and + * a negative D. The CRT controller does not + * seem to like correcting HRE to 50 + */ + current->HDisplay = 320; + current->HSyncStart = 328; + current->HSyncEnd = 376; + current->HTotal = 400; + + } else { + + current->HDisplay = (E * 8); + current->HSyncStart = (E * 8) + (F * 8); + current->HSyncEnd = (E * 8) + (F * 8) + (C * 8); + current->HTotal = (E * 8) + (F * 8) + (C * 8) + (D * 8); + + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, + "H: A %d B %d C %d D %d E %d F %d HT %d HDE %d HRS %d HBS %d HBE %d HRE %d\n", + A, B, C, D, E, F, HT, HDE, HRS, HBS, HBE, HRE); +#endif + + sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[13]; + /* inSISIDXREG(SISSR, 0x0A, sr_data); */ + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[6]; + /* inSISIDXREG(SISCR, 0x06, cr_data); */ + + cr_data2 = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[7]; + /* inSISIDXREG(SISCR, 0x07, cr_data2); */ + + /* Vertical total */ + VT = (cr_data & 0xFF) | + ((unsigned short) (cr_data2 & 0x01) << 8) | + ((unsigned short)(cr_data2 & 0x20) << 4) | + ((unsigned short) (sr_data & 0x01) << 10); + A = VT + 2; + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[10]; + /* inSISIDXREG(SISCR, 0x12, cr_data); */ + + /* Vertical display enable end */ + VDE = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x02) << 7) | + ((unsigned short) (cr_data2 & 0x40) << 3) | + ((unsigned short) (sr_data & 0x02) << 9); + E = VDE + 1; + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[8]; + /* inSISIDXREG(SISCR, 0x10, cr_data); */ + + /* Vertical retrace (=sync) start */ + VRS = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x04) << 6) | + ((unsigned short) (cr_data2 & 0x80) << 2) | + ((unsigned short) (sr_data & 0x08) << 7); + F = VRS + 1 - E; + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[11]; + /* inSISIDXREG(SISCR, 0x15, cr_data); */ + + cr_data3 = (pSiS->SiS_Pr->SiS_CRT1Table[index].CR[16] & 0x01) << 5; + /* inSISIDXREG(SISCR, 0x09, cr_data3); */ + + /* Vertical blank start */ + VBS = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x08) << 5) | + ((unsigned short) (cr_data3 & 0x20) << 4) | + ((unsigned short) (sr_data & 0x04) << 8); + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[12]; + /* inSISIDXREG(SISCR, 0x16, cr_data); */ + + /* Vertical blank end */ + VBE = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x10) << 4); + temp = VBE - ((E - 1) & 511); + B = (temp > 0) ? temp : (temp + 512); + + cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[9]; + /* inSISIDXREG(SISCR, 0x11, cr_data); */ + + /* Vertical retrace (=sync) end */ + VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1); + temp = VRE - ((E + F - 1) & 31); + C = (temp > 0) ? temp : (temp + 32); + + D = B - F - C; + + current->VDisplay = VDE + 1; + current->VSyncStart = VRS + 1; + current->VSyncEnd = ((VRS & ~0x1f) | VRE) + 1; + if(VRE <= (VRS & 0x1f)) current->VSyncEnd += 32; + current->VTotal = E + D + C + F; + +#if 0 + current->VDisplay = E; + current->VSyncStart = E + D; + current->VSyncEnd = E + D + C; + current->VTotal = E + D + C + F; +#endif + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, + "V: A %d B %d C %d D %d E %d F %d VT %d VDE %d VRS %d VBS %d VBE %d VRE %d\n", + A, B, C, D, E, F, VT, VDE, VRS, VBS, VBE, VRE); +#endif + + if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x4000) + current->Flags |= V_NHSYNC; + else + current->Flags |= V_PHSYNC; + + if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x8000) + current->Flags |= V_NVSYNC; + else + current->Flags |= V_PVSYNC; + + if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x0080) + current->Flags |= V_INTERLACE; + + j = 0; + while(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) { + if(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID == + pSiS->SiS_Pr->SiS_RefIndex[i].ModeID) { + if(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) { + current->Flags |= V_DBLSCAN; + } + break; + } + j++; + } + + if(current->Flags & V_INTERLACE) { + current->VDisplay <<= 1; + current->VSyncStart <<= 1; + current->VSyncEnd <<= 1; + current->VTotal <<= 1; + current->VTotal |= 1; + } + if(current->Flags & V_DBLSCAN) { + current->Clock >>= 1; + current->VDisplay >>= 1; + current->VSyncStart >>= 1; + current->VSyncEnd >>= 1; + current->VTotal >>= 1; + } + +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Built-in: %s %.2f %d %d %d %d %d %d %d %d\n", + current->name, (float)current->Clock / 1000, + current->HDisplay, current->HSyncStart, current->HSyncEnd, current->HTotal, + current->VDisplay, current->VSyncStart, current->VSyncEnd, current->VTotal); +#else + (void)VBS; (void)HBS; (void)A; +#endif + + i++; + } + + /* Add non-standard LCD modes for panel's detailed timings */ + + if(!includelcdmodes) return first; + + if(pSiS->SiS_Pr->CP_Vendor) { + xf86DrvMsg(0, X_INFO, "Checking database for vendor %x, product %x\n", + pSiS->SiS_Pr->CP_Vendor, pSiS->SiS_Pr->CP_Product); + } + + i = 0; + while((!done) && (SiS_PlasmaTable[i].vendor) && (pSiS->SiS_Pr->CP_Vendor)) { + + if(SiS_PlasmaTable[i].vendor == pSiS->SiS_Pr->CP_Vendor) { + + for(j=0; j<SiS_PlasmaTable[i].productnum; j++) { + + if(SiS_PlasmaTable[i].product[j] == pSiS->SiS_Pr->CP_Product) { + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Identified %s panel, adding specific modes\n", + SiS_PlasmaTable[i].plasmaname); + + for(k=0; k<SiS_PlasmaTable[i].modenum; k++) { + + if(isfordvi) { + if(!(SiS_PlasmaTable[i].plasmamodes[k] & 0x80)) continue; + } else { + if(!(SiS_PlasmaTable[i].plasmamodes[k] & 0x40)) continue; + } + + l = SiS_PlasmaTable[i].plasmamodes[k] & 0x3f; + + if(pSiS->VBFlags & (VB_301|VB_301B|VB_302B|VB_301LV)) { + if(isfordvi) { + if(SiS_PlasmaMode[l].VDisplay > 1024) continue; + } + } + + if(!(new = xalloc(sizeof(DisplayModeRec)))) return first; + + memset(new, 0, sizeof(DisplayModeRec)); + if(!(new->name = xalloc(12))) { + xfree(new); + return first; + } + if(!first) first = new; + if(current) { + current->next = new; + new->prev = current; + } + + current = new; + + pSiS->AddedPlasmaModes = TRUE; + + strcpy(current->name, SiS_PlasmaMode[l].name); + /* sprintf(current->name, "%dx%d", SiS_PlasmaMode[l].HDisplay, + SiS_PlasmaMode[l].VDisplay); */ + + current->status = MODE_OK; + + current->type = M_T_BUILTIN; + + current->Clock = SiS_PlasmaMode[l].clock; + current->SynthClock = current->Clock; + + current->HDisplay = SiS_PlasmaMode[l].HDisplay; + current->HSyncStart = current->HDisplay + SiS_PlasmaMode[l].HFrontPorch; + current->HSyncEnd = current->HSyncStart + SiS_PlasmaMode[l].HSyncWidth; + current->HTotal = SiS_PlasmaMode[l].HTotal; + + current->VDisplay = SiS_PlasmaMode[l].VDisplay; + current->VSyncStart = current->VDisplay + SiS_PlasmaMode[l].VFrontPorch; + current->VSyncEnd = current->VSyncStart + SiS_PlasmaMode[l].VSyncWidth; + current->VTotal = SiS_PlasmaMode[l].VTotal; + + current->CrtcHDisplay = current->HDisplay; + current->CrtcHBlankStart = current->HSyncStart; + current->CrtcHSyncStart = current->HSyncStart; + current->CrtcHSyncEnd = current->HSyncEnd; + current->CrtcHBlankEnd = current->HSyncEnd; + current->CrtcHTotal = current->HTotal; + + current->CrtcVDisplay = current->VDisplay; + current->CrtcVBlankStart = current->VSyncStart; + current->CrtcVSyncStart = current->VSyncStart; + current->CrtcVSyncEnd = current->VSyncEnd; + current->CrtcVBlankEnd = current->VSyncEnd; + current->CrtcVTotal = current->VTotal; + + if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_HSYNCP) + current->Flags |= V_PHSYNC; + else + current->Flags |= V_NHSYNC; + + if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_VSYNCP) + current->Flags |= V_PVSYNC; + else + current->Flags |= V_NVSYNC; + + if(current->HDisplay > pSiS->LCDwidth) + pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = current->HDisplay; + if(current->VDisplay > pSiS->LCDheight) + pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = current->VDisplay; + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "\tAdding \"%s\" to list of built-in modes\n", current->name); + + } + done = TRUE; + break; + } + } + } + + i++; + + } + + if(pSiS->SiS_Pr->CP_HaveCustomData) { + + for(i=0; i<7; i++) { + + if(pSiS->SiS_Pr->CP_DataValid[i]) { + + if(!(new = xalloc(sizeof(DisplayModeRec)))) return first; + + memset(new, 0, sizeof(DisplayModeRec)); + if(!(new->name = xalloc(10))) { + xfree(new); + return first; + } + if(!first) first = new; + if(current) { + current->next = new; + new->prev = current; + } + + current = new; + + sprintf(current->name, "%dx%d", pSiS->SiS_Pr->CP_HDisplay[i], + pSiS->SiS_Pr->CP_VDisplay[i]); + + current->status = MODE_OK; + + current->type = M_T_BUILTIN; + + current->Clock = pSiS->SiS_Pr->CP_Clock[i]; + current->SynthClock = current->Clock; + + current->HDisplay = pSiS->SiS_Pr->CP_HDisplay[i]; + current->HSyncStart = pSiS->SiS_Pr->CP_HSyncStart[i]; + current->HSyncEnd = pSiS->SiS_Pr->CP_HSyncEnd[i]; + current->HTotal = pSiS->SiS_Pr->CP_HTotal[i]; + + current->VDisplay = pSiS->SiS_Pr->CP_VDisplay[i]; + current->VSyncStart = pSiS->SiS_Pr->CP_VSyncStart[i]; + current->VSyncEnd = pSiS->SiS_Pr->CP_VSyncEnd[i]; + current->VTotal = pSiS->SiS_Pr->CP_VTotal[i]; + + current->CrtcHDisplay = current->HDisplay; + current->CrtcHBlankStart = pSiS->SiS_Pr->CP_HBlankStart[i]; + current->CrtcHSyncStart = current->HSyncStart; + current->CrtcHSyncEnd = current->HSyncEnd; + current->CrtcHBlankEnd = pSiS->SiS_Pr->CP_HBlankEnd[i]; + current->CrtcHTotal = current->HTotal; + + current->CrtcVDisplay = current->VDisplay; + current->CrtcVBlankStart = pSiS->SiS_Pr->CP_VBlankStart[i]; + current->CrtcVSyncStart = current->VSyncStart; + current->CrtcVSyncEnd = current->VSyncEnd; + current->CrtcVBlankEnd = pSiS->SiS_Pr->CP_VBlankEnd[i]; + current->CrtcVTotal = current->VTotal; + + if(pSiS->SiS_Pr->CP_SyncValid[i]) { + if(pSiS->SiS_Pr->CP_HSync_P[i]) + current->Flags |= V_PHSYNC; + else + current->Flags |= V_NHSYNC; + + if(pSiS->SiS_Pr->CP_VSync_P[i]) + current->Flags |= V_PVSYNC; + else + current->Flags |= V_NVSYNC; + } else { + /* No sync data? Use positive sync... */ + current->Flags |= V_PHSYNC; + current->Flags |= V_PVSYNC; + } + } + } + } + + return first; + +} + +/* Translate a mode number into the VESA pendant */ +int +SiSTranslateToVESA(ScrnInfoPtr pScrn, int modenumber) +{ + SISPtr pSiS = SISPTR(pScrn); + int i = 0; + + /* Initialize our pointers */ + if(pSiS->VGAEngine == SIS_300_VGA) { +#ifdef SIS300 + InitTo300Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext); +#else + return -1; +#endif + } else if(pSiS->VGAEngine == SIS_315_VGA) { +#ifdef SIS315H + InitTo310Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext); +#else + return -1; +#endif + } else return -1; + + if(modenumber <= 0x13) return modenumber; + +#ifdef SIS315H + if(pSiS->ROM661New) { + while(SiS_EModeIDTable661[i].Ext_ModeID != 0xff) { + if(SiS_EModeIDTable661[i].Ext_ModeID == modenumber) { + return (int)SiS_EModeIDTable661[i].Ext_VESAID; + } + i++; + } + } else { +#endif + while(pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID != 0xff) { + if(pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID == modenumber) { + return (int)pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID; + } + i++; + } +#ifdef SIS315H + } +#endif + return -1; +} + +/* Translate a new BIOS mode number into the driver's pendant */ +int +SiSTranslateToOldMode(int modenumber) +{ +#ifdef SIS315H + int i = 0; + + while(SiS_EModeIDTable661[i].Ext_ModeID != 0xff) { + if(SiS_EModeIDTable661[i].Ext_ModeID == modenumber) { + if(SiS_EModeIDTable661[i].Ext_MyModeID) + return (int)SiS_EModeIDTable661[i].Ext_MyModeID; + else + return modenumber; + } + i++; + } +#endif + return modenumber; +} + +#endif /* Xfree86 */ + +#ifdef LINUX_KERNEL +int +sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + unsigned char modeno, unsigned char rateindex) +{ + USHORT ModeNo = modeno; + USHORT ModeIdIndex = 0, ClockIndex = 0; + USHORT RefreshRateTableIndex = 0; + int Clock; + + if(HwInfo->jChipType < SIS_315H) { +#ifdef SIS300 + InitTo300Pointer(SiS_Pr, HwInfo); +#else + return 65 * 1000; +#endif + } else { +#ifdef SIS315H + InitTo310Pointer(SiS_Pr, HwInfo); +#else + return 65 * 1000; +#endif + } + + if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {; + printk(KERN_ERR "Could not find mode %x\n", ModeNo); + return 65 * 1000; + } + + RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; + RefreshRateTableIndex += (rateindex - 1); + ClockIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + if(HwInfo->jChipType < SIS_315H) { + ClockIndex &= 0x3F; + } + Clock = SiS_Pr->SiS_VCLKData[ClockIndex].CLOCK * 1000; + + return(Clock); +} + +BOOLEAN +sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex) +{ + USHORT ModeNo = modeno; + USHORT ModeIdIndex = 0, CRT1Index = 0; + USHORT RefreshRateTableIndex = 0; + unsigned char sr_data, cr_data, cr_data2; + + if(HwInfo->jChipType < SIS_315H) { +#ifdef SIS300 + InitTo300Pointer(SiS_Pr, HwInfo); +#else + return FALSE; +#endif + } else { +#ifdef SIS315H + InitTo310Pointer(SiS_Pr, HwInfo); +#else + return FALSE; +#endif + } + + if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE; + + RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; + RefreshRateTableIndex += (rateindex - 1); + CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; + + sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14]; + cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0]; + *htotal = (((cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8)) + 5) * 8; + + sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13]; + cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6]; + cr_data2 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7]; + *vtotal = ((cr_data & 0xFF) | + ((unsigned short)(cr_data2 & 0x01) << 8) | + ((unsigned short)(cr_data2 & 0x20) << 4) | + ((unsigned short)(sr_data & 0x01) << 10)) + 2; + + if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & InterlaceMode) + *vtotal *= 2; + + return TRUE; +} + +int +sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + unsigned char modeno, unsigned char rateindex, + struct fb_var_screeninfo *var) +{ + USHORT ModeNo = modeno; + USHORT ModeIdIndex = 0, index = 0; + USHORT RefreshRateTableIndex = 0; + unsigned short VRE, VBE, VRS, VBS, VDE, VT; + unsigned short HRE, HBE, HRS, HBS, HDE, HT; + unsigned char sr_data, cr_data, cr_data2, cr_data3; + int A, B, C, D, E, F, temp, j; + + if(HwInfo->jChipType < SIS_315H) { +#ifdef SIS300 + InitTo300Pointer(SiS_Pr, HwInfo); +#else + return 0; +#endif + } else { +#ifdef SIS315H + InitTo310Pointer(SiS_Pr, HwInfo); +#else + return 0; +#endif + } + + if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0; + + RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; + RefreshRateTableIndex += (rateindex - 1); + index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; + + sr_data = SiS_Pr->SiS_CRT1Table[index].CR[14]; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[0]; + + /* Horizontal total */ + HT = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x03) << 8); + A = HT + 5; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[1]; + + /* Horizontal display enable end */ + HDE = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x0C) << 6); + E = HDE + 1; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[4]; + + /* Horizontal retrace (=sync) start */ + HRS = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0xC0) << 2); + F = HRS - E - 3; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[2]; + + /* Horizontal blank start */ + HBS = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x30) << 4); + + sr_data = SiS_Pr->SiS_CRT1Table[index].CR[15]; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[3]; + + cr_data2 = SiS_Pr->SiS_CRT1Table[index].CR[5]; + + /* Horizontal blank end */ + HBE = (cr_data & 0x1f) | + ((unsigned short) (cr_data2 & 0x80) >> 2) | + ((unsigned short) (sr_data & 0x03) << 6); + + /* Horizontal retrace (=sync) end */ + HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3); + + temp = HBE - ((E - 1) & 255); + B = (temp > 0) ? temp : (temp + 256); + + temp = HRE - ((E + F + 3) & 63); + C = (temp > 0) ? temp : (temp + 64); + + D = B - F - C; + + if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 320) && + ((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes == 200) || + (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes == 240))) { + + /* Terrible hack, but the correct CRTC data for + * these modes only produces a black screen... + */ + var->left_margin = (400 - 376); + var->right_margin = (328 - 320); + var->hsync_len = (376 - 328); + + } else { + + var->left_margin = D * 8; + var->right_margin = F * 8; + var->hsync_len = C * 8; + + } + + sr_data = SiS_Pr->SiS_CRT1Table[index].CR[13]; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[6]; + + cr_data2 = SiS_Pr->SiS_CRT1Table[index].CR[7]; + + /* Vertical total */ + VT = (cr_data & 0xFF) | + ((unsigned short) (cr_data2 & 0x01) << 8) | + ((unsigned short)(cr_data2 & 0x20) << 4) | + ((unsigned short) (sr_data & 0x01) << 10); + A = VT + 2; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[10]; + + /* Vertical display enable end */ + VDE = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x02) << 7) | + ((unsigned short) (cr_data2 & 0x40) << 3) | + ((unsigned short) (sr_data & 0x02) << 9); + E = VDE + 1; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[8]; + + /* Vertical retrace (=sync) start */ + VRS = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x04) << 6) | + ((unsigned short) (cr_data2 & 0x80) << 2) | + ((unsigned short) (sr_data & 0x08) << 7); + F = VRS + 1 - E; + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[11]; + + cr_data3 = (SiS_Pr->SiS_CRT1Table[index].CR[16] & 0x01) << 5; + + /* Vertical blank start */ + VBS = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x08) << 5) | + ((unsigned short) (cr_data3 & 0x20) << 4) | + ((unsigned short) (sr_data & 0x04) << 8); + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[12]; + + /* Vertical blank end */ + VBE = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x10) << 4); + temp = VBE - ((E - 1) & 511); + B = (temp > 0) ? temp : (temp + 512); + + cr_data = SiS_Pr->SiS_CRT1Table[index].CR[9]; + + /* Vertical retrace (=sync) end */ + VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1); + temp = VRE - ((E + F - 1) & 31); + C = (temp > 0) ? temp : (temp + 32); + + D = B - F - C; + + var->upper_margin = D; + var->lower_margin = F; + var->vsync_len = C; + + if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000) + var->sync &= ~FB_SYNC_VERT_HIGH_ACT; + else + var->sync |= FB_SYNC_VERT_HIGH_ACT; + + if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000) + var->sync &= ~FB_SYNC_HOR_HIGH_ACT; + else + var->sync |= FB_SYNC_HOR_HIGH_ACT; + + var->vmode = FB_VMODE_NONINTERLACED; + if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080) + var->vmode = FB_VMODE_INTERLACED; + else { + j = 0; + while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) { + if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID == + SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].ModeID) { + if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) { + var->vmode = FB_VMODE_DOUBLE; + } + break; + } + j++; + } + } + + if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { +#if 0 /* Do this? */ + var->upper_margin <<= 1; + var->lower_margin <<= 1; + var->vsync_len <<= 1; +#endif + } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { + var->upper_margin >>= 1; + var->lower_margin >>= 1; + var->vsync_len >>= 1; + } + + return 1; +} + +#endif + diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h new file mode 100644 index 000000000000..35030d300431 --- /dev/null +++ b/drivers/video/sis/init.h @@ -0,0 +1,2472 @@ +/* $XFree86$ */ +/* $XdotOrg$ */ +/* + * Data and prototypes for init.c + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the named License, + * * or any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program; if not, write to the Free Software + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Otherwise, the following license terms apply: + * + * * Redistribution and use in source and binary forms, with or without + * * modification, are permitted provided that the following conditions + * * are met: + * * 1) Redistributions of source code must retain the above copyright + * * notice, this list of conditions and the following disclaimer. + * * 2) Redistributions in binary form must reproduce the above copyright + * * notice, this list of conditions and the following disclaimer in the + * * documentation and/or other materials provided with the distribution. + * * 3) The name of the author may not be used to endorse or promote products + * * derived from this software without specific prior written permission. + * * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + */ + +#ifndef _INIT_ +#define _INIT_ + +#include "osdef.h" +#include "initdef.h" + +#ifdef LINUX_XF86 +#include "sis.h" +#include "sis_regs.h" +#endif + +#ifdef LINUX_KERNEL +#include "vgatypes.h" +#include "vstruct.h" +#ifdef SIS_CP +#undef SIS_CP +#endif +#include <linux/config.h> +#include <linux/version.h> +#include <linux/types.h> +#include <asm/io.h> +#include <linux/fb.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include <linux/sisfb.h> +#else +#include <video/sisfb.h> +#endif +#endif + +/* Mode numbers */ +static const USHORT ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f}; +static const USHORT ModeIndex_320x240[] = {0x50, 0x56, 0x00, 0x53}; +static const USHORT ModeIndex_320x240_FSTN[] = {0x5a, 0x5b, 0x00, 0x00}; /* FSTN */ +static const USHORT ModeIndex_400x300[] = {0x51, 0x57, 0x00, 0x54}; +static const USHORT ModeIndex_512x384[] = {0x52, 0x58, 0x00, 0x5c}; +static const USHORT ModeIndex_640x400[] = {0x2f, 0x5d, 0x00, 0x5e}; +static const USHORT ModeIndex_640x480[] = {0x2e, 0x44, 0x00, 0x62}; +static const USHORT ModeIndex_720x480[] = {0x31, 0x33, 0x00, 0x35}; +static const USHORT ModeIndex_720x576[] = {0x32, 0x34, 0x00, 0x36}; +static const USHORT ModeIndex_768x576[] = {0x5f, 0x60, 0x00, 0x61}; +static const USHORT ModeIndex_800x480[] = {0x70, 0x7a, 0x00, 0x76}; +static const USHORT ModeIndex_800x600[] = {0x30, 0x47, 0x00, 0x63}; +static const USHORT ModeIndex_848x480[] = {0x39, 0x3b, 0x00, 0x3e}; +static const USHORT ModeIndex_856x480[] = {0x3f, 0x42, 0x00, 0x45}; +static const USHORT ModeIndex_960x540[] = {0x1d, 0x1e, 0x00, 0x1f}; /* 315 series only */ +static const USHORT ModeIndex_960x600[] = {0x20, 0x21, 0x00, 0x22}; /* 315 series only */ +static const USHORT ModeIndex_1024x768[] = {0x38, 0x4a, 0x00, 0x64}; +static const USHORT ModeIndex_1024x576[] = {0x71, 0x74, 0x00, 0x77}; +static const USHORT ModeIndex_1024x600[] = {0x20, 0x21, 0x00, 0x22}; /* 300 series only */ +static const USHORT ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65}; +static const USHORT ModeIndex_1280x960[] = {0x7c, 0x7d, 0x00, 0x7e}; +static const USHORT ModeIndex_1152x768[] = {0x23, 0x24, 0x00, 0x25}; /* 300 series only */ +static const USHORT ModeIndex_1152x864[] = {0x29, 0x2a, 0x00, 0x2b}; +static const USHORT ModeIndex_300_1280x768[] = {0x55, 0x5a, 0x00, 0x5b}; +static const USHORT ModeIndex_310_1280x768[] = {0x23, 0x24, 0x00, 0x25}; +static const USHORT ModeIndex_1280x720[] = {0x79, 0x75, 0x00, 0x78}; +static const USHORT ModeIndex_1280x800[] = {0x14, 0x15, 0x00, 0x16}; +static const USHORT ModeIndex_1360x768[] = {0x48, 0x4b, 0x00, 0x4e}; +static const USHORT ModeIndex_300_1360x1024[]= {0x67, 0x6f, 0x00, 0x72}; /* 300 series, BARCO only */ +static const USHORT ModeIndex_1400x1050[] = {0x26, 0x27, 0x00, 0x28}; /* 315 series only */ +static const USHORT ModeIndex_1680x1050[] = {0x17, 0x18, 0x00, 0x19}; /* 315 series only */ +static const USHORT ModeIndex_1600x1200[] = {0x3c, 0x3d, 0x00, 0x66}; +static const USHORT ModeIndex_1920x1080[] = {0x2c, 0x2d, 0x00, 0x73}; /* 315 series only */ +static const USHORT ModeIndex_1920x1440[] = {0x68, 0x69, 0x00, 0x6b}; +static const USHORT ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00}; +static const USHORT ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e}; + +static const USHORT SiS_DRAMType[17][5]={ + {0x0C,0x0A,0x02,0x40,0x39}, + {0x0D,0x0A,0x01,0x40,0x48}, + {0x0C,0x09,0x02,0x20,0x35}, + {0x0D,0x09,0x01,0x20,0x44}, + {0x0C,0x08,0x02,0x10,0x31}, + {0x0D,0x08,0x01,0x10,0x40}, + {0x0C,0x0A,0x01,0x20,0x34}, + {0x0C,0x09,0x01,0x08,0x32}, + {0x0B,0x08,0x02,0x08,0x21}, + {0x0C,0x08,0x01,0x08,0x30}, + {0x0A,0x08,0x02,0x04,0x11}, + {0x0B,0x0A,0x01,0x10,0x28}, + {0x09,0x08,0x02,0x02,0x01}, + {0x0B,0x09,0x01,0x08,0x24}, + {0x0B,0x08,0x01,0x04,0x20}, + {0x0A,0x08,0x01,0x02,0x10}, + {0x09,0x08,0x01,0x01,0x00} +}; + +static const USHORT SiS_SDRDRAM_TYPE[13][5] = +{ + { 2,12, 9,64,0x35}, + { 1,13, 9,64,0x44}, + { 2,12, 8,32,0x31}, + { 2,11, 9,32,0x25}, + { 1,12, 9,32,0x34}, + { 1,13, 8,32,0x40}, + { 2,11, 8,16,0x21}, + { 1,12, 8,16,0x30}, + { 1,11, 9,16,0x24}, + { 1,11, 8, 8,0x20}, + { 2, 9, 8, 4,0x01}, + { 1,10, 8, 4,0x10}, + { 1, 9, 8, 2,0x00} +}; + +static const USHORT SiS_DDRDRAM_TYPE[4][5] = +{ + { 2,12, 9,64,0x35}, + { 2,12, 8,32,0x31}, + { 2,11, 8,16,0x21}, + { 2, 9, 8, 4,0x01} +}; + +static const USHORT SiS_MDA_DAC[] = +{ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F +}; + +static const USHORT SiS_CGA_DAC[] = +{ + 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, + 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, + 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, + 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F +}; + +static const USHORT SiS_EGA_DAC[] = +{ + 0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15, + 0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35, + 0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D, + 0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D, + 0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17, + 0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37, + 0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F, + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F +}; + +static const USHORT SiS_VGA_DAC[] = +{ + 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, + 0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18, + 0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F, + 0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F, + 0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00, + 0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18, + 0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04, + 0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10, + 0x0B,0x0C,0x0D,0x0F,0x10 +}; + +static const SiS_StResInfoStruct SiS_StResInfo[]= +{ + { 640,400}, + { 640,350}, + { 720,400}, + { 720,350}, + { 640,480} +}; + +static const SiS_ModeResInfoStruct SiS_ModeResInfo[] = +{ + { 320, 200, 8, 8}, /* 0x00 */ + { 320, 240, 8, 8}, /* 0x01 */ + { 320, 400, 8, 8}, /* 0x02 */ + { 400, 300, 8, 8}, /* 0x03 */ + { 512, 384, 8, 8}, /* 0x04 */ + { 640, 400, 8,16}, /* 0x05 */ + { 640, 480, 8,16}, /* 0x06 */ + { 800, 600, 8,16}, /* 0x07 */ + { 1024, 768, 8,16}, /* 0x08 */ + { 1280,1024, 8,16}, /* 0x09 */ + { 1600,1200, 8,16}, /* 0x0a */ + { 1920,1440, 8,16}, /* 0x0b */ + { 2048,1536, 8,16}, /* 0x0c */ + { 720, 480, 8,16}, /* 0x0d */ + { 720, 576, 8,16}, /* 0x0e */ + { 1280, 960, 8,16}, /* 0x0f */ + { 800, 480, 8,16}, /* 0x10 */ + { 1024, 576, 8,16}, /* 0x11 */ + { 1280, 720, 8,16}, /* 0x12 */ + { 856, 480, 8,16}, /* 0x13 */ + { 1280, 768, 8,16}, /* 0x14 */ + { 1400,1050, 8,16}, /* 0x15 */ + { 1152, 864, 8,16}, /* 0x16 */ + { 848, 480, 8,16}, /* 0x17 */ + { 1360, 768, 8,16}, /* 0x18 */ + { 1024, 600, 8,16}, /* 0x19 */ + { 1152, 768, 8,16}, /* 0x1a */ + { 768, 576, 8,16}, /* 0x1b */ + { 1360,1024, 8,16}, /* 0x1c */ + { 1680,1050, 8,16}, /* 0x1d */ + { 1280, 800, 8,16}, /* 0x1e */ + { 1920,1080, 8,16}, /* 0x1f */ + { 960, 540, 8,16}, /* 0x20 */ + { 960, 600, 8,16} /* 0x21 */ +}; + +#if defined(SIS300) || defined(SIS315H) +static const SiS_StandTableStruct SiS_StandTable[]= +{ +/* 0x00: MD_0_200 */ + { + 0x28,0x18,0x08,0x0800, + {0x09,0x03,0x00,0x02}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, + 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* 0x01: MD_1_200 */ + { + 0x28,0x18,0x08,0x0800, + {0x09,0x03,0x00,0x02}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, + 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* 0x02: MD_2_200 */ + { + 0x50,0x18,0x08,0x1000, + {0x01,0x03,0x00,0x02}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* 0x03: MD_3_200 - mode 0x03 - 0 */ + { + 0x50,0x18,0x08,0x1000, + {0x01,0x03,0x00,0x02}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* 0x04: MD_4 */ + { + 0x28,0x18,0x08,0x4000, + {0x09,0x03,0x00,0x02}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 0x2c is 2b for 300 */ + 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2, + 0xff}, + {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x01,0x00,0x03,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00, + 0xff} + }, +/* 0x05: MD_5 */ + { + 0x28,0x18,0x08,0x4000, + {0x09,0x03,0x00,0x02}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 0x2c is 2b for 300 */ + 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2, + 0xff}, + {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x01,0x00,0x03,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00, + 0xff} + }, +/* 0x06: MD_6 */ + { + 0x50,0x18,0x08,0x4000, + {0x01,0x01,0x00,0x06}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, /* 55,81 is 54,80 for 300 */ + 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2, + 0xff}, + {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x01,0x00,0x01,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00, + 0xff} + }, +/* 0x07: MD_7 */ + { + 0x50,0x18,0x0e,0x1000, + {0x00,0x03,0x00,0x03}, + 0xa6, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, + 0x83,0x85,0x5d,0x28,0x0d,0x63,0xba,0xa3, + 0xff}, + {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08, + 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x0e,0x00,0x0f,0x08}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00, + 0xff} + }, +/* 0x08: MDA_DAC */ + { + 0x00,0x00,0x00,0x0000, + {0x00,0x00,0x00,0x15}, + 0x15, + {0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x15,0x15,0x15,0x15,0x15,0x15,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0x00, + 0x00}, + {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x15, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x15,0x15,0x15,0x15}, + {0x15,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f} + }, +/* 0x09: CGA_DAC */ + { + 0x00,0x10,0x04,0x0114, + {0x11,0x09,0x15,0x00}, + 0x10, + {0x04,0x14,0x01,0x11,0x09,0x15,0x2a,0x3a, + 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x2a,0x3a, + 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x10, + 0x04}, + {0x14,0x01,0x11,0x09,0x15,0x00,0x10,0x04, + 0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,0x2e, + 0x3e,0x2b,0x3b,0x2f}, + {0x3f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f, + 0x3f} + }, +/* 0x0a: EGA_DAC */ + { + 0x00,0x10,0x04,0x0114, + {0x11,0x05,0x15,0x20}, + 0x30, + {0x24,0x34,0x21,0x31,0x25,0x35,0x08,0x18, + 0x0c,0x1c,0x09,0x19,0x0d,0x1d,0x28,0x38, + 0x2c,0x3c,0x29,0x39,0x2d,0x3d,0x02,0x12, + 0x06}, + {0x16,0x03,0x13,0x07,0x17,0x22,0x32,0x26, + 0x36,0x23,0x33,0x27,0x37,0x0a,0x1a,0x0e, + 0x1e,0x0b,0x1b,0x0f}, + {0x1f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f, + 0x3f} + }, +/* 0x0b: VGA_DAC */ + { + 0x00,0x10,0x04,0x0114, + {0x11,0x09,0x15,0x2a}, + 0x3a, + {0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x05, + 0x08,0x0b,0x0e,0x11,0x14,0x18,0x1c,0x20, + 0x24,0x28,0x2d,0x32,0x38,0x3f,0x00,0x10, + 0x1f}, + {0x2f,0x3f,0x1f,0x27,0x2f,0x37,0x3f,0x2d, + 0x31,0x36,0x3a,0x3f,0x00,0x07,0x0e,0x15, + 0x1c,0x0e,0x11,0x15}, + {0x18,0x1c,0x14,0x16,0x18,0x1a,0x1c,0x00, + 0x04} + }, +/* 0x0c */ + { + 0x08,0x0c,0x10,0x0a08, + {0x0c,0x0e,0x10,0x0b}, + 0x0c, + {0x0d,0x0f,0x10,0x10,0x01,0x08,0x00,0x00, + 0x00,0x00,0x01,0x00,0x02,0x02,0x01,0x00, + 0x04,0x04,0x01,0x00,0x05,0x02,0x05,0x00, + 0x06}, + {0x01,0x06,0x05,0x06,0x00,0x08,0x01,0x08, + 0x00,0x07,0x02,0x07,0x06,0x07,0x00,0x00, + 0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00} + }, +/* 0x0d: MD_D */ + { + 0x28,0x18,0x08,0x2000, + {0x09,0x0f,0x00,0x06}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 2c is 2b for 300 */ + 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x01,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, + 0xff} + }, +/* 0x0e: MD_E */ + { + 0x50,0x18,0x08,0x4000, + {0x01,0x0f,0x00,0x06}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, /* 55,81 is 54,80 for 300 */ + 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x01,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, + 0xff} + }, +/* 0x0f: ExtVGATable - modes > 0x13 */ + { + 0x00,0x00,0x00,0x0000, + {0x01,0x0f,0x00,0x0e}, + 0x23, + {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x01,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, + 0xff} + }, +/* 0x10: ROM_SAVEPTR - totally different for 300 */ + { + 0x9f,0x3b,0x00,0x00c0, + {0x00,0x00,0x00,0x00}, + 0x00, + {0x00,0x00,0x00,0x00,0x00,0x00,0xbb,0x3f, + 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1a,0x00,0xac,0x3e,0x00,0xc0, + 0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00} + }, +/* 0x11: MD_F */ + { + 0x50,0x18,0x0e,0x8000, + {0x01,0x0f,0x00,0x06}, + 0xa2, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, /* 55,81 is 54,80 on 300 */ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3, /* 82,84 is 83,85 on 300 */ + 0xff}, + {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00, + 0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00, + 0x0b,0x00,0x05,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05, + 0xff} + }, +/* 0x12: MD_10 */ + { + 0x50,0x18,0x0e,0x8000, + {0x01,0x0f,0x00,0x06}, + 0xa3, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, /* 55,81 is 54,80 on 300 */ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3, /* 82,84 is 83,85 on 300 */ + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x01,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, + 0xff} + }, +/* 0x13: MD_0_350 */ + { + 0x28,0x18,0x0e,0x0800, + {0x09,0x03,0x00,0x02}, + 0xa3, + {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f, /* b1 is a0 on 300 */ + 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, + 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* 0x14: MD_1_350 */ + { + 0x28,0x18,0x0e,0x0800, + {0x09,0x03,0x00,0x02}, + 0xa3, + {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, + 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, + 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* 0x15: MD_2_350 */ + { + 0x50,0x18,0x0e,0x1000, + {0x01,0x03,0x00,0x02}, + 0xa3, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, + 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* 0x16: MD_3_350 - mode 0x03 - 1 */ + { + 0x50,0x18,0x0e,0x1000, + {0x01,0x03,0x00,0x02}, + 0xa3, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, + 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* 0x17: MD_0_1_400 */ + { + 0x28,0x18,0x10,0x0800, + {0x08,0x03,0x00,0x02}, + 0x67, + {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f, /* b1 is a0 on 300 */ + 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x0c,0x00,0x0f,0x08}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* 0x18: MD_2_3_400 - mode 0x03 - 2 */ + { + 0x50,0x18,0x10,0x1000, + {0x00,0x03,0x00,0x02}, + 0x67, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x0c,0x00,0x0f,0x08}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* 0x19: MD_7_400 */ + { + 0x50,0x18,0x10,0x1000, + {0x00,0x03,0x00,0x02}, + 0x66, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08, + 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x0e,0x00,0x0f,0x08}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00, + 0xff} + }, +/* 0x1a: MD_11 */ + { + 0x50,0x1d,0x10,0xa000, + {0x01,0x0f,0x00,0x06}, + 0xe3, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, /* 55,81 is 54,80 on 300 */ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xc3, /* e9,8b is ea,8c on 300 */ + 0xff}, + {0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x01,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01, + 0xff} + }, +/* 0x1b: ExtEGATable - Modes <= 0x02 */ + { + 0x50,0x1d,0x10,0xa000, + {0x01,0x0f,0x00,0x06}, + 0xe3, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, /* 55,81 is 54,80 on 300 */ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3, /* e9,8b is ea,8c on 300 */ + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x01,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, + 0xff} + }, +/* 0x1c: MD_13 */ + { + 0x28,0x18,0x08,0x2000, + {0x01,0x0f,0x00,0x0e}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, /* 55,81 is 54,80 on 300 */ + 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x41,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, + 0xff} + } +}; +#endif + +/**************************************************************/ +/* SIS VIDEO BRIDGE ----------------------------------------- */ +/**************************************************************/ + +static const UCHAR SiS_SoftSetting = 0x30; /* RAM setting */ + +static const UCHAR SiS_OutputSelect = 0x40; + +static const UCHAR SiS_NTSCTiming[] = { + 0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c, + 0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a, + 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b, + 0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17, + 0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02, + 0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40, + 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50, + 0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00 +}; + +static const UCHAR SiS_PALTiming[] = { + 0x19,0x52,0x35,0x6e,0x04,0x38,0x3d,0x70, + 0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d, + 0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b, + 0x70,0x50,0x00,0x9b,0x00,0xd9,0x5d,0x17, + 0x7d,0x05,0x45,0x00,0x00,0xe8,0x00,0x02, + 0x0d,0x00,0x68,0xb0,0x0b,0x92,0x8f,0x40, + 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63, + 0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00 +}; + +static const UCHAR SiS_HiTVExtTiming[] = { + 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64, + 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d, + 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f, + 0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13, + 0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40, + 0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40, + 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d, + 0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00 +}; + +static const UCHAR SiS_HiTVSt1Timing[] = { + 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65, + 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d, + 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f, + 0x65,0x90,0x7b,0xa8,0x03,0xf0,0x87,0x03, + 0x11,0x15,0x11,0xcf,0x10,0x11,0xcf,0x10, + 0x35,0x35,0x3b,0x69,0x1d,0x92,0x0f,0x40, + 0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x86, + 0xaf,0x5d,0x0e,0x00,0xfc,0xff,0x2d,0x00 +}; + +static const UCHAR SiS_HiTVSt2Timing[] = { + 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64, + 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d, + 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f, + 0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13, + 0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40, + 0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40, + 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d, + 0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00 +}; + +#if 0 +static const UCHAR SiS_HiTVTextTiming[] = { + 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65, + 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d, + 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f, + 0x65,0x90,0xe7,0xbc,0x03,0x0c,0x97,0x03, + 0x14,0x78,0x14,0x08,0x20,0x14,0x08,0x20, + 0xc8,0xc8,0x3b,0xd2,0x26,0x92,0x0f,0x40, + 0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x96, + 0x72,0x5c,0x11,0x00,0xfc,0xff,0x32,0x00 +}; +#endif + +static const UCHAR SiS_HiTVGroup3Data[] = { + 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f, + 0x05,0x21,0xb2,0xb2,0x55,0x77,0x2a,0xa6, + 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20, + 0x8c,0x6e,0x60,0x2e,0x58,0x48,0x72,0x44, + 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80, + 0x4f,0x7f,0x03,0xa8,0x7d,0x20,0x1a,0xa9, + 0x14,0x05,0x03,0x7e,0x64,0x31,0x14,0x75, + 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01 +}; + +static const UCHAR SiS_HiTVGroup3Simu[] = { + 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95, + 0xdb,0x20,0xb8,0xb8,0x55,0x47,0x2a,0xa6, + 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20, + 0x8c,0x6e,0x60,0x15,0x26,0xd3,0xe4,0x11, + 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80, + 0x67,0x36,0x01,0x47,0x0e,0x10,0xbe,0xb4, + 0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75, + 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01 +}; + +#if 0 +static const UCHAR SiS_HiTVGroup3Text[] = { + 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7, + 0xf5,0x20,0xce,0xce,0x55,0x47,0x2a,0xa6, + 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20, + 0x8c,0x6e,0x60,0x18,0x2c,0x0c,0x20,0x22, + 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80, + 0x93,0x3c,0x01,0x50,0x2f,0x10,0xf4,0xca, + 0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75, + 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01 +}; +#endif + +static const UCHAR SiS_NTSCPhase[] = {0x21,0xed,0xba,0x08}; +static const UCHAR SiS_PALPhase[] = {0x2a,0x05,0xe3,0x00}; +static const UCHAR SiS_PALMPhase[] = {0x21,0xE4,0x2E,0x9B}; +static const UCHAR SiS_PALNPhase[] = {0x21,0xF4,0x3E,0xBA}; +static const UCHAR SiS_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6}; +static const UCHAR SiS_PALPhase2[] = {0x2a,0x09,0x86,0xe9}; +static const UCHAR SiS_PALMPhase2[] = {0x21,0xE6,0xEF,0xA4}; +static const UCHAR SiS_PALNPhase2[] = {0x21,0xF6,0x94,0x46}; +static const UCHAR SiS_SpecialPhase[] = {0x1e,0x8c,0x5c,0x7a}; +static const UCHAR SiS_SpecialPhaseM[]= {0x1e,0x83,0x0a,0xe0}; +static const UCHAR SiS_SpecialPhaseJ[]= {0x25,0xd4,0xfd,0x5e}; + +static const SiS_TVDataStruct SiS_StPALData[] = +{ + { 1, 1, 864, 525,1270, 400, 100, 0, 760,0xf4,0xff,0x1c,0x22}, + { 1, 1, 864, 525,1270, 350, 100, 0, 760,0xf4,0xff,0x1c,0x22}, + { 1, 1, 864, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18}, + { 1, 1, 864, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a}, + { 1, 1, 864, 525,1270, 480, 50, 0, 760,0xf4,0xff,0x1c,0x22}, + { 1, 1, 864, 525,1270, 600, 50, 0, 0,0xf4,0xff,0x1c,0x22} +}; + +static const SiS_TVDataStruct SiS_ExtPALData[] = +{ + { 27, 10, 848, 448,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22}, /* 640x400, 320x200 */ + { 108, 35, 848, 398,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22}, + { 12, 5, 954, 448,1270, 530, 50, 0, 50,0xf1,0x04,0x1f,0x18}, + { 9, 4, 960, 463,1644, 438, 50, 0, 50,0xf4,0x0b,0x1c,0x0a}, + { 9, 4, 848, 528,1270, 530, 0, 0, 50,0xf5,0xfb,0x1b,0x2a}, /* 640x480, 320x240 */ +/*{ 36, 25,1060, 648,1316, 530, 438, 0, 438,0xeb,0x05,0x25,0x16},*//* 800x600, 400x300 */ + { 36, 25,1060, 648,1270, 530, 438, 0, 438,0xeb,0x05,0x25,0x16}, /* 800x600, 400x300 - better */ + { 3, 2,1080, 619,1270, 540, 438, 0, 438,0xf3,0x00,0x1d,0x20}, /* 720x576 */ + { 1, 1,1170, 821,1270, 520, 686, 0, 686,0xF3,0x00,0x1D,0x20}, /* 1024x768 */ + { 1, 1,1170, 821,1270, 520, 686, 0, 686,0xF3,0x00,0x1D,0x20}, /* 1024x768 (for NTSC equ) */ + { 9, 4, 848, 528,1270, 530, 0, 0, 50,0xf5,0xfb,0x1b,0x2a} /* 720x480 test */ +}; + +static const SiS_TVDataStruct SiS_StNTSCData[] = +{ + { 1, 1, 858, 525,1270, 400, 50, 0, 760,0xf1,0x04,0x1f,0x18}, + { 1, 1, 858, 525,1270, 350, 50, 0, 640,0xf1,0x04,0x1f,0x18}, + { 1, 1, 858, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18}, + { 1, 1, 858, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a}, + { 1, 1, 858, 525,1270, 480, 0, 0, 760,0xf1,0x04,0x1f,0x18} +}; + +static const SiS_TVDataStruct SiS_ExtNTSCData[] = +{ + { 143, 65, 858, 443,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18}, /* 640x400, 320x200 */ + { 88, 35, 858, 393,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18}, + { 143, 70, 924, 443,1270, 440, 92, 0, 92,0xf1,0x04,0x1f,0x18}, + { 143, 70, 924, 393,1270, 440, 92, 0, 92,0xf4,0x0b,0x1c,0x0a}, + { 143, 76, 836, 523,1270, 440, 224, 0, 0,0xf1,0x05,0x1f,0x16}, /* 640x480, 320x240 */ + { 143, 120,1056, 643,1270, 440, 0, 128, 0,0xf4,0x10,0x1c,0x00}, /* 800x600, 400x300 */ +/*{ 2, 1, 858, 503,1270, 480, 0, 128, 0,0xee,0x0c,0x22,0x08},*/ /* 720x480 (old, from 650) */ + { 143, 76, 836, 523,1270, 440, 0, 128, 0,0xee,0x0c,0x22,0x08}, /* 720x480 - BETTER (from 300 series) */ +/*{ 65, 64,1056, 791,1270, 480, 638, 0, 0,0xEE,0x0C,0x22,0x08} */ /* 1024x768 (525i) */ + { 1, 1,1100, 811,1412, 440, 0, 128, 0,0xee,0x0c,0x22,0x08}, /* 1024x768 (525i) CORRECTED */ + { 65, 64,1056, 791,1270, 480, 455, 0, 0,0x00,0x00,0x00,0x00} /* 1024x768 (525p) */ +}; + +static const SiS_TVDataStruct SiS_StHiTVData[] = /* Slave + TVSimu */ +{ + { 1, 1, 0x37c,0x233,0x2b2,0x320, 0, 0, 0, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x37c,0x233,0x2b2,0x320, 0, 0, 0, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x37c,0x233,0x2b2,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00}, + { 8, 5, 0x41a,0x2ab,0x670,0x3c0,0x150,128, 0, 0x00,0x00,0x00,0x00} +}; + +static const SiS_TVDataStruct SiS_St2HiTVData[] = /* Slave */ +{ + { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00}, + { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00}, + { 5, 2, 0x348,0x233,0x670,0x3c0,0x08d,128, 0, 0x00,0x00,0x00,0x00}, + { 8, 5, 0x41a,0x2ab,0x670,0x3c0,0x17c,128, 0, 0x00,0x00,0x00,0x00} +}; + +static const SiS_TVDataStruct SiS_ExtHiTVData[] = +{ + { 6, 1, 0x348,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00}, + { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00}, + { 6, 1, 0x348,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00}, + { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00}, + { 5, 1, 0x348,0x233,0x670,0x3c0,0x166,128, 0, 0x00,0x00,0x00,0x00}, /* 640x480 */ + { 16, 5, 0x41a,0x2ab,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00}, /* 800x600 */ + { 25, 12, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00}, /* 1024x768 */ + { 5, 4, 0x627,0x464,0x670,0x3c0,0x128, 0, 0, 0x00,0x00,0x00,0x00}, /* 1280x1024 */ + { 4, 1, 0x41a,0x233,0x60c,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00}, /* 800x480 */ + { 5, 2, 0x578,0x293,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00}, /* 1024x576 */ + { 8, 5, 0x6d6,0x323,0x670,0x3c0,0x128, 0, 0, 0x00,0x00,0x00,0x00}, /* 1280x720 */ + { 137, 32, 0x3d4,0x233,0x663,0x3bf,0x143, 0, 0, 0x00,0x00,0x00,0x00} /* 960x600 */ +}; + +static const SiS_TVDataStruct SiS_St525pData[] = +{ + { 1, 1, 0x6b4,0x20d,0x4f6,0x190, 50, 0, 0x2f8, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x6b4,0x20d,0x4f6,0x15e, 50, 0, 0x280, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x6b4,0x20d,0x4f6,0x190, 50, 0, 0x2f8, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x6b4,0x20d,0x4f6,0x15e, 50, 0, 0x280, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x6b4,0x20d,0x4f6,0x1e0, 0, 0, 0x2f8, 0x00,0x00,0x00,0x00} +}; + +static const SiS_TVDataStruct SiS_St750pData[] = +{ + { 1, 1, 0x672,0x2ee,0x500,0x190, 50, 0, 0x2f8, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x672,0x2ee,0x500,0x15e, 50, 0, 0x280, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x672,0x2ee,0x500,0x190, 0, 0, 0x2d0, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x672,0x2ee,0x500,0x15e, 0, 0, 0x2d0, 0x00,0x00,0x00,0x00}, + { 1, 1, 0x672,0x2ee,0x500,0x1e0, 0, 0, 0x2f8, 0x00,0x00,0x00,0x00} +}; + +static const SiS_TVDataStruct SiS_Ext750pData[] = +{ + { 143, 65, 0x35a,0x1bb,0x4f6,0x1b8,0x0ab, 0, 0x0ab, 0x00,0x00,0x00,0x00}, + { 88, 35, 0x35a,0x189,0x4f6,0x1b8,0x0ab, 0, 0x0ab, 0x00,0x00,0x00,0x00}, + { 18, 5, 0x339,0x1ae,0x500,0x2d0,0x05c, 0, 0x05c, 0x00,0x00,0x00,0x00}, + { 143, 70, 0x39c,0x189,0x4f6,0x1b8,0x05c, 0, 0x05c, 0x00,0x00,0x00,0x00}, + { 99, 32, 0x320,0x1fe,0x500,0x2d0, 50, 0, 0, 0x00,0x00,0x00,0x00}, /* 640x480 */ + { 5, 4, 0x5d8,0x29e,0x500,0x2a8, 50, 0, 0, 0x00,0x00,0x00,0x00}, /* 800x600 */ + { 99, 32, 0x320,0x1fe,0x500,0x2d0, 50, 0, 0, 0x00,0x00,0x00,0x00}, /* 720x480 test WORKS */ + { 68, 64, 0x55f,0x346,0x500,0x2a8,0x27e, 0, 0, 0x00,0x00,0x00,0x00}, /* 1024x768 */ + { 5, 2, 0x3a7,0x226,0x500,0x2a8, 0,128, 0, 0x00,0x00,0x00,0x00}, /* 720x576 */ + { 25, 24, 0x5d8,0x2f3,0x460,0x2a8, 50, 0, 0, 0x00,0x00,0x00,0x00} /* 1280x720 WORKS */ +}; + +static const SiS_LCDDataStruct SiS_LCD1280x720Data[] = /* 2.03.00 */ +{ + { 44, 15, 864, 430, 1408, 806 }, /* 640x400 */ + { 128, 35, 792, 385, 1408, 806 }, + { 44, 15, 864, 430, 1408, 806 }, + { 128, 35, 792, 385, 1408, 806 }, + { 22, 9, 864, 516, 1408, 806 }, /* 640x480 */ + { 8, 5, 1056, 655, 1408, 806 }, /* 800x600 */ + { 0, 0, 0, 0, 0, 0 }, /* 1024x768 */ + { 0, 0, 0, 0, 0, 0 }, /* 1280x1024 */ + { 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0 }, + { 1, 1, 1408, 806, 1408, 806 } /* 1280x720 */ +}; + +/* About 1280x768: For TMDS, Panel_1280x768 will only be set if + * the panel is a Fujitsu 7911 (VL-17WDX8) (with clock 81, 1688x802) + * Other TMDS panels of this resolution will be treated as custom. + * For LVDS, we know another type (_2). + * (Note: 1280x768_3 is now special for SiS301/NetVista + */ + +static const SiS_LCDDataStruct SiS_StLCD1280x768_2Data[] = /* 2.03.00 */ +{ + { 64, 21, 858, 434, 1408, 806 }, /* 640x400 */ + { 32, 9, 858, 372, 1408, 806 }, + { 64, 21, 858, 434, 1408, 806 }, + { 32, 9, 858, 372, 1408, 806 }, + { 143, 68, 1024, 527, 1408, 806 }, /* 640x480 */ + { 64, 51, 1364, 663, 1408, 806 }, /* 800x600 */ + { 88, 81, 1296, 806, 1408, 806 }, /* 1024x768 */ + { 0, 0, 0, 0, 0, 0 }, + { 1, 1, 1408, 806, 1408, 806 }, /* 1280x768 */ + { 0, 0, 0, 0, 0, 0 }, + { 16, 15, 1600, 750, 1600, 806 } /* 1280x720 - from Ext */ +}; + +static const SiS_LCDDataStruct SiS_ExtLCD1280x768_2Data[] = /* 2.03.00 */ +{ + { 16, 5, 960, 410, 1600, 806 }, /* 640x400 */ + { 64, 21, 1152, 364, 1600, 806 }, + { 16, 5, 960, 410, 1600, 806 }, + { 64, 21, 1152, 364, 1600, 806 }, + { 32, 13, 1040, 493, 1600, 806 }, /* 640x480 */ + { 16, 9, 1152, 618, 1600, 806 }, /* 800x600 */ + { 25, 21, 1344, 796, 1600, 806 }, /* 1024x768 */ + { 0, 0, 0, 0, 0, 0 }, + { 1, 1, 1600, 806, 1600, 806 }, /* 1280x768 */ + { 0, 0, 0, 0, 0, 0 }, + { 16, 15, 1600, 750, 1600, 806 } /* 1280x720 */ +}; + +#if 0 /* Not used; _3 now reserved for NetVista (SiS301) */ +static const SiS_LCDDataStruct SiS_LCD1280x768_3Data[] = +{ + { 64, 25, 1056, 422, 1664, 798 }, /* 640x400 */ + { 128, 39, 884, 396, 1408, 806 }, /* ,640 */ + { 64, 25, 1056, 422, 1664, 798 }, /* 640x400 */ + { 128, 39, 884, 396, 1408, 806 }, /* ,640 */ + { 32, 15, 1056, 513, 1408, 806 }, /* ,664 */ /* 640x480 */ + { 176, 125, 1280, 640, 1408, 806 }, /* ,768 */ /* 800x600 */ + { 64, 61, 1342, 806, 1408, 806 }, /* 1024x768 */ + { 0, 0, 0, 0, 0, 0 }, + { 1, 1, 1408, 806, 1408, 806 }, /* 1280x768 */ + { 0, 0, 0, 0, 0, 0 }, + { 16, 15, 1600, 750, 1600, 806 } /* 1280x720 from above */ +}; +#endif + +static const SiS_LCDDataStruct SiS_LCD1280x800Data[] = /* 0.93.12a (TMDS) */ +{ + { 128, 51, 1122, 412, 1408, 816 }, /* 640x400 */ + { 128, 49, 1232, 361, 1408, 816 }, + { 128, 51, 1122, 412, 1408, 816 }, + { 128, 49, 1232, 361, 1408, 816 }, + { 8, 3, 880, 491, 1408, 816 }, /* 640x480 */ + { 11, 6, 1024, 612, 1408, 816 }, /* 800x600 */ + { 22, 21, 1400, 784, 1408, 816 }, /* 1024x768 */ + { 0, 0, 0, 0, 0, 0 }, /* 1280x1024 */ + { 1, 1, 1408, 816, 1408, 816 }, /* 1280x800 */ + { 0, 0, 0, 0, 0, 0 }, /* 1280x768 (patch index) */ + { 0, 0, 0, 0, 0, 0 } /* 1280x720 */ +}; + +static const SiS_LCDDataStruct SiS_LCD1280x800_2Data[] = /* 2.03.00 (LVDS) */ +{ + { 97, 42, 1344, 409, 1552, 812 }, /* 640x400 */ + { 97, 35, 1280, 358, 1552, 812 }, + { 97, 42, 1344, 409, 1552, 812 }, + { 97, 35, 1280, 358, 1552, 812 }, + { 97, 39, 1040, 488, 1552, 812 }, /* 640x480 */ + { 194, 105, 1120, 608, 1552, 812 }, /* 800x600 */ + { 97, 84, 1400, 780, 1552, 812 }, /* 1024x768 */ + { 0, 0, 0, 0, 0, 0 }, /* 1280x1024 */ + { 1, 1, 1552, 812, 1552, 812 }, /* 1280x800 */ + { 97, 96, 1600, 780, 1552, 812 }, /* 1280x768 - patch index */ + { 97, 90, 1600, 730, 1552, 812 } /* 1280x720 */ +}; + +static const SiS_LCDDataStruct SiS_LCD1280x960Data[] = +{ + { 9, 2, 800, 500, 1800, 1000 }, + { 9, 2, 800, 500, 1800, 1000 }, + { 4, 1, 900, 500, 1800, 1000 }, + { 4, 1, 900, 500, 1800, 1000 }, + { 9, 2, 800, 500, 1800, 1000 }, + { 30, 11, 1056, 625, 1800, 1000 }, + { 5, 3, 1350, 800, 1800, 1000 }, + { 1, 1, 1576, 1050, 1576, 1050 }, + { 1, 1, 1800, 1000, 1800, 1000 } +}; + +static const SiS_LCDDataStruct SiS_StLCD1400x1050Data[] = +{ + { 211, 100, 2100, 408, 1688, 1066 }, + { 211, 64, 1536, 358, 1688, 1066 }, + { 211, 100, 2100, 408, 1688, 1066 }, + { 211, 64, 1536, 358, 1688, 1066 }, + { 211, 48, 840, 488, 1688, 1066 }, + { 211, 72, 1008, 609, 1688, 1066 }, + { 211, 128, 1400, 776, 1688, 1066 }, + { 211, 205, 1680, 1041, 1688, 1066 }, + { 1, 1, 1688, 1066, 1688, 1066 } +}; + +static const SiS_LCDDataStruct SiS_ExtLCD1400x1050Data[] = +{ +/* { 211, 60, 1260, 410, 1688, 1066 }, 640x400 (6330) */ + { 211, 100, 2100, 408, 1688, 1066 }, /* 640x400 (6325) WORKS */ + { 211, 64, 1536, 358, 1688, 1066 }, + { 211, 100, 2100, 408, 1688, 1066 }, + { 211, 64, 1536, 358, 1688, 1066 }, +/* { 211, 80, 1400, 490, 1688, 1066 }, 640x480 (6330) */ + { 211, 48, 840, 488, 1688, 1066 }, /* 640x480 (6325) WORKS */ +/* { 211, 117, 1638, 613, 1688, 1066 }, 800x600 (6330) */ + { 211, 72, 1008, 609, 1688, 1066 }, /* 800x600 (6325) WORKS */ + { 211, 128, 1400, 776, 1688, 1066 }, /* 1024x768 */ + { 211, 205, 1680, 1041, 1688, 1066 }, /* 1280x1024 - not used (always unscaled) */ + { 1, 1, 1688, 1066, 1688, 1066 }, /* 1400x1050 */ + { 0, 0, 0, 0, 0, 0 }, /* kludge */ + { 211, 120, 1400, 730, 1688, 1066 } /* 1280x720 */ +}; + +static const SiS_LCDDataStruct SiS_LCD1680x1050Data[] = +{ + { 95, 24, 1260, 410, 1900, 1066 }, /* 0 640x400 */ + { 10, 3, 1710, 362, 1900, 1066 }, + { 95, 24, 1260, 410, 1900, 1066 }, + { 10, 3, 1710, 362, 1900, 1066 }, + { 95, 32, 1400, 490, 1900, 1066 }, /* 4 640x480 */ + { 95, 42, 1470, 610, 1900, 1066 }, /* 5 800x600 */ + { 95, 64, 1750, 784, 1900, 1066 }, /* 6 1024x768 */ + { 95, 94, 1900, 1055, 1900, 1066 }, /* 7 1280x1024 */ + { 41, 31, 1900, 806, 1900, 1066 }, /* 8 1280x768 */ + { 95, 69, 1800, 817, 1900, 1066 }, /* 9 1280x800 patch index */ + { 13, 9, 1900, 739, 1900, 1066 }, /* 10 1280x720 */ + { 95, 94, 1880, 1066, 1900, 1066 }, /* 11 1400x1050 patch index */ + { 1, 1, 1900, 1066, 1900, 1066 } /* 12 1680x1050 */ +}; + +static const SiS_LCDDataStruct SiS_StLCD1600x1200Data[] = +{ + {27, 4, 800, 500, 2160, 1250 }, + {27, 4, 800, 500, 2160, 1250 }, + { 6, 1, 900, 500, 2160, 1250 }, + { 6, 1, 900, 500, 2160, 1250 }, + {27, 1, 800, 500, 2160, 1250 }, + { 4, 1,1080, 625, 2160, 1250 }, + { 5, 2,1350, 800, 2160, 1250 }, + {135,88,1600,1100, 2160, 1250 }, + {72, 49,1680,1092, 2160, 1250 }, + { 1, 1,2160,1250, 2160, 1250 } +}; + +static const SiS_LCDDataStruct SiS_ExtLCD1600x1200Data[] = +{ + {72,11, 990, 422, 2160, 1250 }, /* 640x400 (6330) WORKS */ +/* {27, 4, 800, 500, 2160, 1250 }, 640x400 (6235) */ + {27, 4, 800, 500, 2160, 1250 }, + { 6, 1, 900, 500, 2160, 1250 }, + { 6, 1, 900, 500, 2160, 1250 }, + {45, 8, 960, 505, 2160, 1250 }, /* 640x480 (6330) WORKS */ +/* {27, 1, 800, 500, 2160, 1250 }, 640x480 (6325) */ + { 4, 1,1080, 625, 2160, 1250 }, + { 5, 2,1350, 800, 2160, 1250 }, + {27,16,1500,1064, 2160, 1250 }, /* 1280x1024 */ + {72,49,1680,1092, 2160, 1250 }, /* 1400x1050 (6330, was not supported on 6325) */ + { 1, 1,2160,1250, 2160, 1250 } +}; + +static const SiS_LCDDataStruct SiS_NoScaleData[] = +{ + { 1, 1, 800, 449, 800, 449 }, /* 0x00: 320x200, 640x400 */ + { 1, 1, 800, 449, 800, 449 }, + { 1, 1, 900, 449, 900, 449 }, + { 1, 1, 900, 449, 900, 449 }, + { 1, 1, 800, 525, 800, 525 }, /* 0x04: 320x240, 640x480 */ + { 1, 1,1056, 628,1056, 628 }, /* 0x05: 400x300, 800x600 */ + { 1, 1,1344, 806,1344, 806 }, /* 0x06: 512x384, 1024x768 */ + { 1, 1,1688,1066,1688,1066 }, /* 0x07: 1280x1024 */ + { 1, 1,1688, 802,1688, 802 }, /* 0x08: 1280x768: Fujitsu, TMDS only */ + { 1, 1,2160,1250,2160,1250 }, /* 0x09: 1600x1200 */ + { 1, 1,1800,1000,1800,1000 }, /* 0x0a: 1280x960 */ + { 1, 1,1688,1066,1688,1066 }, /* 0x0b: 1400x1050 */ + { 1, 1,1650, 750,1650, 750 }, /* 0x0c: 1280x720 (TMDS, projector) */ + { 1, 1,1552, 812,1552, 812 }, /* 0x0d: 1280x800_2 (LVDS) (was: 1408,816/ 1656,841) */ + { 1, 1,1900,1066,1900,1066 }, /* 0x0e: 1680x1050 (LVDS) */ + { 1, 1,1660, 806,1660, 806 }, /* 0x0f: 1280x768_2 (LVDS) */ + { 1, 1,1664, 798,1664, 798 }, /* 0x10: 1280x768_3 (NetVista SiS 301) - TODO */ + { 1, 1,1688, 802,1688, 802 }, /* 0x11: 1280x768 (TMDS Fujitsu) */ + { 1, 1,1408, 806,1408, 806 }, /* 0x12: 1280x720 (LVDS) */ + { 1, 1, 896, 497, 896, 497 }, /* 0x13: 720x480 */ + { 1, 1, 912, 597, 912, 597 }, /* 0x14: 720x576 */ + { 1, 1, 912, 597, 912, 597 }, /* 0x15: 768x576 */ + { 1, 1,1056, 497,1056, 497 }, /* 0x16: 848x480 */ + { 1, 1,1064, 497,1064, 497 }, /* 0x17: 856x480 */ + { 1, 1,1056, 497,1056, 497 }, /* 0x18: 800x480 */ + { 1, 1,1328, 739,1328, 739 }, /* 0x19: 1024x576 */ + { 1, 1,1680, 892,1680, 892 }, /* 0x1a: 1152x864 */ + { 1, 1,1808, 808,1808, 808 }, /* 0x1b: 1360x768 */ + { 1, 1,1104, 563,1104, 563 }, /* 0x1c: 960x540 */ + { 1, 1,1120, 618,1120, 618 }, /* 0x1d: 960x600 */ + { 1, 1,1408, 816,1408, 816 } /* 0x1f: 1280x800 (TMDS special) */ +}; + +/**************************************************************/ +/* LVDS ----------------------------------------------------- */ +/**************************************************************/ + +static const SiS_LVDSDataStruct SiS_LVDS320x480Data_1[]= +{ + { 848, 433, 400, 525}, + { 848, 389, 400, 525}, + { 848, 433, 400, 525}, + { 848, 389, 400, 525}, + { 848, 518, 400, 525}, + {1056, 628, 400, 525}, + { 400, 525, 400, 525}, + { 800, 449,1000, 644}, + { 800, 525,1000, 635} +}; + +static const SiS_LVDSDataStruct SiS_LVDS640x480Data_1[]= +{ + { 800, 445, 800, 525}, /* 800, 449, 800, 449 */ + { 800, 395, 800, 525}, + { 800, 445, 800, 525}, + { 800, 395, 800, 525}, + { 800, 525, 800, 525}, + { 800, 525, 800, 525}, /* pseudo */ + { 800, 525, 800, 525} /* pseudo */ +}; + +/* FSTN 320x240 */ +static const SiS_LVDSDataStruct SiS_LVDS640x480Data_2[]= +{ + { 800, 445, 800, 525}, + { 800, 395, 800, 525}, + { 800, 445, 800, 525}, + { 800, 395, 800, 525}, + { 800, 525, 800, 525}, + { 800, 525, 800, 525}, /* pseudo */ + { 800, 525, 800, 525} /* pseudo */ +}; + +static const SiS_LVDSDataStruct SiS_LVDS800x600Data_1[]= +{ + { 848, 433,1060, 629}, + { 848, 389,1060, 629}, + { 848, 433,1060, 629}, + { 848, 389,1060, 629}, + { 848, 518,1060, 629}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628} +}; + +static const SiS_LVDSDataStruct SiS_LVDS800x600Data_2[]= +{ + {1056, 628,1056, 628} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1024x768Data_1[]= +{ + { 840, 438,1344, 806}, + { 840, 409,1344, 806}, + { 840, 438,1344, 806}, + { 840, 409,1344, 806}, + { 840, 518,1344, 806}, /* 640x480 */ + {1050, 638,1344, 806}, /* 800x600 */ + {1344, 806,1344, 806}, /* 1024x768 */ +}; + +static const SiS_LVDSDataStruct SiS_LVDS1024x768Data_2[]= +{ + {1344, 806,1344, 806} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1280x1024Data_1[]= +{ + {1048, 442,1688,1066}, + {1048, 392,1688,1066}, + {1048, 442,1688,1066}, + {1048, 392,1688,1066}, + {1048, 522,1688,1066}, + {1208, 642,1688,1066}, + {1432, 810,1688,1066}, + {1688,1066,1688,1066} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1280x1024Data_2[]= +{ + {1688,1066,1688,1066} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1400x1050Data_1[]= +{ + { 928, 416, 1688,1066}, + { 928, 366, 1688,1066}, + { 928, 416, 1688,1066}, + { 928, 366, 1688,1066}, + { 928, 496, 1688,1066}, + {1088, 616, 1688,1066}, + {1312, 784, 1688,1066}, + {1568,1040, 1688,1066}, + {1688,1066, 1688,1066} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1400x1050Data_2[]= +{ + {1688,1066, 1688,1066} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1600x1200Data_1[]= +{ + {1088, 520, 2048,1320}, + {1088, 470, 2048,1320}, + {1088, 520, 2048,1320}, + {1088, 470, 2048,1320}, + {1088, 600, 2048,1320}, + {1248, 720, 2048,1320}, + {1472, 888, 2048,1320}, + {1728,1144, 2048,1320}, + {1848,1170, 2048,1320}, + {2048,1320, 2048,1320} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1600x1200Data_2[]= +{ + {2048,1320, 2048,1320} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1280x960Data_1[]= +{ + { 840, 438,1344, 806}, + { 840, 409,1344, 806}, + { 840, 438,1344, 806}, + { 840, 409,1344, 806}, + { 840, 518,1344, 806}, + {1050, 638,1344, 806}, + {1344, 806,1344, 806}, + { 800, 449,1280, 801}, + { 800, 525,1280, 813} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1280x960Data_2[]= +{ + {1344, 806,1344, 806} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1280x768Data_1[]= +{ + { 768, 438, 1408, 806}, + { 768, 388, 1408, 806}, + { 768, 438, 1408, 806}, + { 768, 388, 1408, 806}, + { 768, 518, 1408, 806}, + { 928, 638, 1408, 806}, + {1152, 806, 1408, 806}, + {1408, 806, 1408, 806}, + {1408, 806, 1408, 806} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1280x768Data_2[]= +{ + {1408, 806, 1408, 806} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1024x600Data_1[] = +{ + { 840, 604,1344, 800}, + { 840, 560,1344, 800}, + { 840, 604,1344, 800}, + { 840, 560,1344, 800}, + { 840, 689,1344, 800}, + {1050, 800,1344, 800}, + {1344, 800,1344, 800} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1024x600Data_2[] = +{ + {1344, 800,1344, 800} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1152x768Data_1[] = +{ + { 840, 438,1344, 806}, + { 840, 409,1344, 806}, + { 840, 438,1344, 806}, + { 840, 409,1344, 806}, + { 840, 518,1344, 806}, + {1050, 638,1344, 806}, + {1344, 806,1344, 806} +}; + +static const SiS_LVDSDataStruct SiS_LVDS1152x768Data_2[] = +{ + {1344, 806,1344, 806} +}; + +/* Pass 1:1 data */ +static const SiS_LVDSDataStruct SiS_LVDSXXXxXXXData_1[]= +{ + { 800, 449, 800, 449}, + { 800, 449, 800, 449}, + { 900, 449, 900, 449}, + { 900, 449, 900, 449}, + { 800, 525, 800, 525}, /* 640x480 */ + {1056, 628, 1056, 628}, /* 800x600 */ + {1344, 806, 1344, 806}, /* 1024x768 */ + {1688,1066, 1688,1066}, /* 1280x1024 */ /* INSERTED */ + {1688, 806, 1688, 806}, /* 1280x768 */ +}; + +/* Custom data for Barco iQ R series */ +static const SiS_LVDSDataStruct SiS_LVDSBARCO1366Data_1[]= +{ + { 832, 438,1331, 806}, + { 832, 388,1331, 806}, + { 832, 438,1331, 806}, + { 832, 388,1331, 806}, + { 832, 518,1331, 806}, + {1050, 638,1344, 806}, + {1344, 806,1344, 806}, + {1688,1066,1688,1066}, + {1688,1066,1688,1066} /* 1360x1024 */ +}; + +/* Custom data for Barco iQ R series */ +static const SiS_LVDSDataStruct SiS_LVDSBARCO1366Data_2[]= +{ + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1688,1066,1688,1066}, + {1688,1066,1688,1066} /* 1360x1024 */ +}; + +/* Custom data for Barco iQ G series */ +static const SiS_LVDSDataStruct SiS_LVDSBARCO1024Data_1[]= +{ + { 832, 438,1331, 806}, + { 832, 409,1331, 806}, + { 832, 438,1331, 806}, + { 832, 409,1331, 806}, + { 832, 518,1331, 806}, /* 640x480 */ + {1050, 638,1344, 806}, /* 800x600 */ + {1344, 806,1344, 806}, /* 1024x768 */ +}; + +/* Custom data for Barco iQ G series */ +static const SiS_LVDSDataStruct SiS_LVDSBARCO1024Data_2[]= +{ + {1344, 806,1344, 806} +}; + +/* Custom data for 848x480 parallel panel */ +static const SiS_LVDSDataStruct SiS_LVDS848x480Data_1[]= +{ + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + {1088, 525,1088, 525}, /* 640x480 TODO */ + {1088, 525,1088, 525}, /* 800x600 TODO */ + {1088, 525,1088, 525}, /* 1024x768 TODO */ + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + {1088, 525,1088, 525}, /* 848x480 */ + {1088, 525,1088, 525} /* 1360x768 TODO */ +}; + +/* Custom data for 848x480 parallel panel */ +static const SiS_LVDSDataStruct SiS_LVDS848x480Data_2[]= +{ + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + {1088, 525,1088, 525}, /* 640x480 */ + {1088, 525,1088, 525}, /* 800x600 */ + {1088, 525,1088, 525}, /* 1024x768 */ + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + {1088, 525,1088, 525}, /* 848x480 */ + {1088, 525,1088, 525} /* 1360x768 TODO */ +}; + +static const SiS_LVDSDataStruct SiS_CHTVUNTSCData[]= +{ + { 840, 600, 840, 600}, + { 840, 600, 840, 600}, + { 840, 600, 840, 600}, + { 840, 600, 840, 600}, + { 784, 600, 784, 600}, + {1064, 750,1064, 750}, + {1160, 945,1160, 945} +}; + +static const SiS_LVDSDataStruct SiS_CHTVONTSCData[]= +{ + { 840, 525, 840, 525}, + { 840, 525, 840, 525}, + { 840, 525, 840, 525}, + { 840, 525, 840, 525}, + { 784, 525, 784, 525}, + {1040, 700,1040, 700}, + {1160, 840,1160, 840} +}; + +/* Chrontel TV Skew */ + +static const SiS_LVDSDesStruct SiS_CHTVUNTSCDesData[]= +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS_CHTVONTSCDesData[]= +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS_CHTVUPALDesData[]= +{ + {256, 0}, + {256, 0}, + {256, 0}, + {256, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS_LVDSDesStruct SiS_CHTVOPALDesData[]= +{ + {256, 0}, + {256, 0}, + {256, 0}, + {256, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +/* CRT1 CRTC data for slave modes */ + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1320x480_1[] = +{ + {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f, + 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, + 0x00 }}, + {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, + 0x00 }}, + {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, + 0x00 }}, + {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, + 0x00 }}, + {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e, + 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05, + 0x00 }}, + {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, + 0x01 }}, + {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e, + 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00, + 0x00 }} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_1[] = +{ + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05, + 0x00}}, + {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_1_H[] = +{ + {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00, + 0x00}}, + {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f, + 0x83,0x85,0x63,0xba,0x00,0x00,0x00, + 0x00}}, + {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f, + 0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00, + 0x00}}, + {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f, + 0x83,0x85,0x63,0xba,0x00,0x00,0x00, + 0x00}}, + {{0x2d,0x28,0x90,0x2c,0x80,0x0b,0x3e, + 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00, + 0x00}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_2[] = +{ + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05, + 0x00}}, + {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, + 0x01}}, + {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e, + 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00, + 0x00}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_2_H[] = +{ + {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f, + 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, + 0x00}}, + {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, + 0x00}}, + {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, + 0x00}}, + {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, + 0x00}}, + {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e, + 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05, + 0x00}}, + {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, + 0x01}}, + {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e, + 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00, + 0x00}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_3[] = +{ + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05, + 0x00}}, + {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e, + 0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05, + 0x00}}, + {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, + 0x01}}, + {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e, + 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00, + 0x00}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_3_H[] = +{ + {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f, + 0x90,0x85,0x8f,0xab,0x30,0x00,0x05, + 0x00}}, + {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, + 0x00}}, + {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, + 0x00}}, + {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f, + 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05, + 0x00}}, + {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e, + 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05, + 0x00}}, + {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0, + 0x58,0x8c,0x57,0x73,0x20,0x00,0x06, + 0x01}}, + {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e, + 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00, + 0x00}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_1[] = +{ + {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e, + 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e, + 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e, + 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e, + 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x88,0x54,0x9f,0xaf,0xba, + 0x3b,0x82,0xdf,0xb0,0x00,0x00,0x01, + 0x00}}, + {{0x7e,0x63,0x82,0x68,0x15,0x1e,0xf1, + 0xae,0x85,0x57,0x1f,0x30,0x00,0x26, + 0x01}}, + {{0xa3,0x7f,0x87,0x86,0x97,0x1e,0xf1, + 0xae,0x85,0x57,0x1f,0x30,0x00,0x02, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_1_H[] = +{ + {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e, + 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44, + 0x00}}, + {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0, + 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55, + 0x01}}, + {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x01, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_2[] = +{ + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x72,0x88,0xdf,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1, + 0xae,0x84,0x57,0x25,0x30,0x00,0x02, + 0x01}}, + {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x02, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_2_H[] = +{ + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, + 0x00}}, + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, + 0x00}}, + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, + 0x00}}, + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, + 0x00}}, + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x72,0x88,0xdf,0x25,0x30,0x00,0x01, + 0x00}}, + {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1, + 0xae,0x84,0x57,0x25,0x30,0x00,0x01, + 0x01}}, + {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x01, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_1[] = +{ + {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x01, + 0x00}}, + {{0x64,0x4f,0x88,0x54,0x9f,0x04,0x3e, + 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01, + 0x00}}, + {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0, + 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26, + 0x01}}, + {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x02, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_1_H[] = +{ + {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f, + 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f, + 0x60,0x87,0x5d,0x83,0x10,0x00,0x44, + 0x00}}, + {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e, + 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44, + 0x00}}, + {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0, + 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55, + 0x01}}, + {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x01, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_2[] = +{ + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x72,0x88,0xdf,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1, + 0xae,0x84,0x57,0x25,0x30,0x00,0x02, + 0x01}}, + {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x02, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_2_H[] = +{ + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, + 0x00}}, + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, + 0x00}}, + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01, + 0x00}}, + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x31,0x87,0x5d,0x25,0x30,0x00,0x01, + 0x00}}, + {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x72,0x88,0xdf,0x25,0x30,0x00,0x01, + 0x00}}, + {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1, + 0xae,0x84,0x57,0x25,0x30,0x00,0x01, + 0x01}}, + {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x01, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_1[] = +{ + {{0x5b,0x4f,0x9f,0x55,0x19,0xb4,0x1f, + 0x9c,0x8e,0x8f,0xb5,0x10,0x00,0x01, + 0x00}}, + {{0x5b,0x4f,0x9f,0x55,0x19,0x82,0x1f, + 0x6a,0x8c,0x5d,0x83,0x30,0x00,0x01, + 0x00}}, + {{0x5b,0x4f,0x9f,0x55,0x19,0xb4,0x1f, + 0x9c,0x8e,0x8f,0xb5,0x10,0x00,0x01, + 0x00}}, + {{0x5b,0x4f,0x9f,0x55,0x19,0x82,0x1f, + 0x6a,0x8c,0x5d,0x83,0x30,0x00,0x01, + 0x00}}, + {{0x5b,0x4f,0x9f,0x55,0x19,0x04,0x3e, + 0xec,0x8e,0xdf,0x05,0x20,0x00,0x01, + 0x00}}, + {{0x6f,0x63,0x93,0x69,0x8d,0x7c,0xf0, + 0x64,0x86,0x57,0x7d,0x20,0x00,0x05, + 0x01}}, + {{0x8b,0x7f,0x8f,0x85,0x09,0x24,0xf5, + 0x0c,0x8e,0xff,0x25,0x30,0x00,0x02, + 0x01}}, + {{0xab,0x9f,0x8f,0xa5,0x89,0x24,0xf5, + 0x0c,0x8e,0xff,0x25,0x30,0x00,0x06, + 0x01}}, + {{0xab,0x9f,0x8f,0xa5,0x89,0x24,0xf5, + 0x0c,0x8e,0xff,0x25,0x30,0x00,0x06, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_1_H[] = +{ + {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f, + 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, + 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f, + 0x92,0x86,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, + 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f, + 0xe2,0x86,0xdf,0xef,0x10,0x00,0x05, + 0x00}}, + {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0, + 0x5a,0x8e,0x57,0x67,0x20,0x00,0x01, + 0x01}}, + {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf5, + 0x02,0x86,0xff,0x0f,0x10,0x00,0x01, + 0x01}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a, + 0x02,0x86,0xff,0x0f,0x09,0x00,0x05, + 0x01}}, + {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a, + 0x02,0x86,0xff,0x0f,0x09,0x00,0x05, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_2[] = +{ + {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb, + 0x54,0x86,0xdb,0xda,0x00,0x00,0x02, + 0x00}}, + {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb, + 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x02, + 0x00}}, + {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb, + 0x54,0x86,0xdb,0xda,0x00,0x00,0x02, + 0x00}}, + {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb, + 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x02, + 0x00}}, + {{0xab,0x60,0x9f,0x80,0x04,0x24,0xb3, + 0x7c,0x8e,0x03,0x02,0x10,0x00,0x02, + 0x01}}, + {{0xab,0x63,0x8f,0x8a,0x8e,0x24,0xf1, + 0xb6,0x88,0x57,0x25,0x10,0x00,0x02, + 0x01}}, + {{0xab,0x7f,0x8f,0x98,0x9c,0x24,0xf5, + 0x0a,0x8c,0xff,0x25,0x30,0x00,0x02, + 0x01}}, + {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5, + 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06, + 0x01}}, + {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5, + 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06, + 0x01}} +}; + +static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_2_H[] = +{ + {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb, + 0x54,0x86,0xdb,0xda,0x00,0x00,0x01, + 0x00}}, + {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb, + 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x01, + 0x00}}, + {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb, + 0x54,0x86,0xdb,0xda,0x00,0x00,0x01, + 0x00}}, + {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb, + 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x01, + 0x00}}, + {{0x83,0x38,0x97,0x58,0x9c,0x24,0xb3, + 0x7c,0x8e,0x03,0x02,0x10,0x00,0x01, + 0x01}}, + {{0x79,0x31,0x9d,0x58,0x9c,0x24,0xf1, + 0xb6,0x88,0x57,0x25,0x10,0x00,0x01, + 0x01}}, + {{0x6b,0x3f,0x8f,0x58,0x9c,0x24,0xf5, + 0x0a,0x8c,0xff,0x25,0x30,0x00,0x01, + 0x01}}, + {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5, + 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06, + 0x01}}, + {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5, + 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06, + 0x01}} +}; + +/**************************************************************/ +/* COMMON --------------------------------------------------- */ +/**************************************************************/ + +#ifdef LINUX_XF86 + +#define SIS_PL_HSYNCP 0x01 +#define SIS_PL_HSYNCN 0x02 +#define SIS_PL_VSYNCP 0x04 +#define SIS_PL_VSYNCN 0x08 +#define SIS_PL_DVI 0x80 + +typedef struct _SiS_PlasmaModes +{ + const char *name; + ULONG clock; + USHORT HDisplay, HTotal, HFrontPorch, HSyncWidth; + USHORT VDisplay, VTotal, VFrontPorch, VSyncWidth; + UCHAR SyncFlags; +} SiS_PlasmaModes; + +typedef struct _SiS_PlasmaTables +{ + USHORT vendor; + UCHAR productnum; + USHORT product[5]; + const char *DDCnames[5]; + const char *plasmaname; + USHORT maxx,maxy; + USHORT prefx, prefy; + UCHAR modenum; + UCHAR plasmamodes[20]; /* | 0x80 = DVI-capable, | 0x40 = analog */ +} SiS_PlasmaTables; + +static const SiS_PlasmaModes SiS_PlasmaMode[] = { + { "640x400", /* 00: IBM 400@70 */ + 25175, + 640, 800, 17, 64, + 400, 449, 13, 2, + SIS_PL_HSYNCN | SIS_PL_VSYNCN }, + { "640x480", /* 01: VESA 480@72 */ + 31500, + 640, 832, 24, 40, + 480, 520, 9, 3, + SIS_PL_HSYNCN | SIS_PL_VSYNCN }, + { "800x600", /* 02: VESA 600@72 */ + 50000, + 800, 1040, 56, 120, + 600, 666, 37, 6, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "864x480", /* 03: Cereb wide 1 */ + 42526, + 864, 1134, 22, 86, + 480, 500, 1, 3, + SIS_PL_HSYNCP | SIS_PL_VSYNCN }, + { "848x480", /* 04: VESA wide (NEC1) */ + 33750, + 848, 1088, 16, 112, + 480, 517, 6, 8, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "1024x576", /* 05: VESA wide (NEC2) */ + 47250, + 1024, 1320, 16, 144, + 576, 596, 2, 4, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "1280x720", /* 06: VESA wide (NEC3) */ + 76500, + 1280, 1696, 48, 176, + 720, 750, 4, 8, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "1360x765", /* 07: VESA wide (NEC4) */ + 85500, + 1360, 1792, 64, 176, + 765, 795, 4, 8, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "1024x600", /* 08: CEREB wide 2 */ + 51200, + 1024, 1352, 51, 164, + 600, 628, 1, 4, + SIS_PL_HSYNCN | SIS_PL_VSYNCP }, + { "1024x768", /* 09: VESA 768@75 */ + 78750, + 1024, 1312, 16, 96, + 768, 800, 1, 3, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "1152x864", /* 10: VESA 1152x864@75 */ + 108000, + 1152, 1600, 64, 128, + 864, 900, 1, 3, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "1280x1024", /* 11: VESA 1024@60 */ + 108000, + 1280, 1688, 48, 112, + 1024, 1066, 1, 3, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "1280x768", /* 12: W_XGA */ + 81000, + 1280, 1688, 48, 112, + 768, 802, 3, 6, + SIS_PL_HSYNCP | SIS_PL_VSYNCN }, + { "1280x768", /* 13: I/O Data W_XGA@56Hz */ + 76064, + 1280, 1688, 48, 112, + 768, 802, 2, 3, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "1376x768", /* 14: I/O Wide XGA */ + 87340, + 1376, 1808, 32, 128, + 768, 806, 3, 6, + SIS_PL_HSYNCN | SIS_PL_VSYNCP }, + { "1280x960", /* 15: VESA 960@60 */ + 108000, + 1280, 1800, 96, 112, + 960, 1000, 1, 3, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "1400x1050", /* 16: VESA 1050@60Hz */ + 108000, + 1400, 1688, 48, 112, + 1050, 1066, 1, 3, + SIS_PL_HSYNCN | SIS_PL_VSYNCN }, + { "1360x768", /* 17: VESA wide (NEC4/2) */ + 85500, + 1360, 1792, 64, 112, + 765, 795, 3, 6, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "800x600", /* 18: VESA 600@56 */ + 36000, + 800, 1024, 24, 2, + 600, 625, 1, 2, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "1072x600", /* 19: Panasonic 1072x600 (sync?) */ + 54100, + 1072, 1424, 48, 176, + 600, 628, 16, 1, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "848x480", /* 20: Panasonic 848x480 (sync?) */ + 33070, /* is 852x480, but we can't use 852 */ + 848, 1068, 20, 40, /* differs from DDC data, better centered */ + 480, 516, 3, 5, /* won't work assumingly, because data is % 8 */ + SIS_PL_HSYNCN | SIS_PL_VSYNCN }, + { "1280x720", /* 21: WIDE720(60) (aka "750p") (Panasonic) */ + 74300, + 1280, 1650,110, 40, + 720, 750, 5, 5, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "1280x768", /* 22: 1280x768@56.5 (Panasonic) */ + 76200, /* (According to manual not supported for HDMI; but works) */ + 1280, 1680, 16, 24, + 768, 802, 2, 5, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "1280x720@50", /* 23: WIDE720(50) (aka "750p") (Panasonic) */ + 74300, /* Panasonic states 45.0kHz. Not possible. This one works (with some overscan) */ + 1280, 1980,400, 80, + 720, 750, 1, 2, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "720x480", /* 24: 720x480 (aka "525p" and "480p") (Panasonic) */ + 27000, + 720, 856, 40, 32, + 480, 525, 1, 3, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "720x576", /* 25: 720x576 (aka "625p"and "576p") (Panasonic) */ + 27500, + 720, 864, 16, 64, + 576, 625, 5, 6, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, + { "1280x720@50", /* 26: WIDE720(50) (aka "750p") (Generic) */ + 74300, + 1280, 1980,400, 80, + 720, 750, 5, 5, + SIS_PL_HSYNCP | SIS_PL_VSYNCP }, +}; + +/* +27.00 720 755 791 858 480 480 484 525 +27.50 720 732 795 864 576 581 587 625 +*/ + +static const SiS_PlasmaTables SiS_PlasmaTable[] = { +#if 0 /* Product IDs missing */ + { 0x38a3, 4, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "", "", "", "", "" }, + "NEC PlasmaSync 42VP4/42VP4D/42VP4G/42VP4DG", + 0, 0, + 0, 0, + 11, /* All DVI, except 0, 7, 13 */ + { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0, + 17|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, +#endif +#if 0 /* Product IDs missing */ + { 0x38a3, 3, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "", "", "", "", "" }, + "NEC PlasmaSync 42PD1/50PD1/50PD2", + 0, 0, + 0, 0, + 5, /* DVI entirely unknown */ + { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0, 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, + { 0x38a3, 1, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "", "", "", "", "" }, + "NEC PlasmaSync 42PD3", + 0, 0, + 0, 0, + 10, /* DVI entirely unknown */ + { 0|0x40, 1|0xc0, 2|0xc0, 3|0xc0, 4|0xc0, 5|0xc0, 6|0xc0, 7|0x40, 8|0xc0, 9|0xc0, + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, + { 0x38a3, 2, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "", "", "", "", "" }, + "NEC PlasmaSync 42VM3/61XM1", + 0, 0, + 0, 0, + 11, /* DVI entirely unknown */ + { 0|0x40, 1|0xc0, 2|0xc0, 3|0xc0, 4|0xc0, 5|0xc0, 6|0xc0, 8|0xc0, 9|0xc0,11|0xc0, + 17|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, + { 0x38a3, 2, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "", "", "", "", "" }, + "NEC PlasmaSync 42MP1/42MP2", + 0, 0, + 0, 0, + 6, /* DVI entirely unknown */ + { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0,11|0xc0, 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, + { 0x38a3, 1, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "", "", "", "", "" }, + "NEC PlasmaSync 50MP1", + 0, 0, + 0, 0, + 10, /* DVI entirely unknown */ + { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0, + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, +#endif + { 0x38a3, 4, + { 0xa482, 0xa483, 0x0000, 0x0000, 0x0000 }, + { "PX-42VM", "", "", "", "" }, + "NEC PlasmaSync 42MP3/42MP4/50MP2/61MP1", + 0, 0, + 0, 0, + 11, /* All DVI except 0, 7, 13, 17 */ + { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0, + 17|0x40, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, +#if 0 /* Product IDs missing */ + { 0x38a3, 1, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "", "", "", "", "" }, + "NEC PlasmaSync 3300W", + 0, 0, + 0, 0, + 3, + { 0|0x40, 1|0xc0,18|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, + { 0x38a3, 1, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "", "", "", "", "" }, + "NEC PlasmaSync 4200W", + 4, /* DVI entirely unknown */ + { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, + { 0x38a3, 1, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "", "", "", "", "" }, + "NEC PlasmaSync 4210W", + 0, 0, + 0, 0, + 6, /* DVI entirely unknown */ + { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0,11|0xc0, 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, + { 0x38a3, 1, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "", "", "", "", "" }, + "NEC PlasmaSync 5000W", + 0, 0, + 0, 0, + 7, /* DVI entirely unknown */ + { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,11|0xc0, 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, +#endif + { 0x412f, 2, + { 0x000c, 0x000b, 0x0000, 0x0000, 0x0000 }, + { "", "", "", "", "" }, + "Pioneer 503CMX/PDA-5002", + 0, 0, + 0, 0, + 6, /* DVI unknown */ + { 1|0xc0, 2|0xc0, 9|0xc0,11|0xc0,12|0xc0,15|0xc0, 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, + { 0x34a9, 1, + { 0xa00e, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "", "", "", "", "" }, + "Panasonic TH-42", + 0, 0, + 0, 0, + 5, /* No DVI output */ + { 1|0x40, 2|0x40, 4|0x40, 9|0x40,15|0x40, 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, + { 0x34a9, 1, + { 0xa005, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "TH-42PW*4", "", "", "", "" }, + "Panasonic TH-42PW5", + 0, 0, + 0, 0, + 1, /* No special modes otherwise; no DVI. */ + {20|0x40,19|0x40, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, + { 0x4c2e, 1, + { 0x9b05, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "PLV-Z2", "", "", "", "" }, + "Sanyo PLV-Z2 (non HDCP-mode)", /* HDCP mode would be id 9b06, but not needed */ + 1280, 768, /* as it then advertises correct size */ + 1280, 720, + 1, /* 1280x720, no special modes otherwise */ + {21|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, + { 0x34a9, 1, + { 0xd034, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "AE500U (DVI-D)", "", "", "", "" }, + "Panasonic AE500U", + 1280, 768, + 1280, 720, + 1, /* 1280x720, no special modes otherwise */ + {21|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, + { 0x34a9, 1, + { 0xd043, 0x0000, 0x0000, 0x0000, 0x0000 }, + { "AE700U (HDMI)", "", "", "", "" }, + "Panasonic AE700U", + 1360, 768, + 1280, 720, + 6, /* 1280x720/60, 1280x720/50, 1280x768@56(digital/analog), 720x480, 720x576 */ + {21|0xc0,23|0xc0,22|0x80,13|0x40,24|0x80,25|0x80, 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } + }, + { 0x0000 } +}; +#endif + +#ifdef LINUX_XF86 +USHORT SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, + int Depth, BOOLEAN FSTN, int LCDwith, int LCDheight); +#endif +USHORT SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN, + USHORT CustomT, int LCDwith, int LCDheight); +USHORT SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth); +USHORT SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth); + +void SiS_SetReg(SISIOADDRESS port, USHORT index, USHORT data); +void SiS_SetRegByte(SISIOADDRESS port, USHORT data); +void SiS_SetRegShort(SISIOADDRESS port, USHORT data); +void SiS_SetRegLong(SISIOADDRESS port, ULONG data); +UCHAR SiS_GetReg(SISIOADDRESS port, USHORT index); +UCHAR SiS_GetRegByte(SISIOADDRESS port); +USHORT SiS_GetRegShort(SISIOADDRESS port); +ULONG SiS_GetRegLong(SISIOADDRESS port); +void SiS_SetRegANDOR(SISIOADDRESS Port, USHORT Index, USHORT DataAND, USHORT DataOR); +void SiS_SetRegAND(SISIOADDRESS Port,USHORT Index, USHORT DataAND); +void SiS_SetRegOR(SISIOADDRESS Port,USHORT Index, USHORT DataOR); +void SiS_DisplayOn(SiS_Private *SiS_Pr); +void SiS_DisplayOff(SiS_Private *SiS_Pr); +void SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr); +void SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +BOOLEAN SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +void SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable); +void SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable); +void SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +BOOLEAN SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex); +UCHAR SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex); +USHORT SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex); +USHORT SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo); +void SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT ModeIdIndex); +void SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex); + +#ifdef LINUX_XF86 +BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch); +BOOLEAN SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn, + DisplayModePtr mode, BOOLEAN IsCustom); +BOOLEAN SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn, + DisplayModePtr mode, BOOLEAN IsCustom); +BOOLEAN SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn, + DisplayModePtr mode, BOOLEAN IsCustom); +int SiSTranslateToVESA(ScrnInfoPtr pScrn, int modenumber); +int SiSTranslateToOldMode(int modenumber); +BOOLEAN SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_INFO); +USHORT SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags); +DisplayModePtr SiSBuildBuiltInModeList(ScrnInfoPtr pScrn, BOOLEAN includelcdmodes, BOOLEAN isfordvi); +int SiS_FindPanelFromDB(SISPtr pSiS, USHORT panelvendor, USHORT panelproduct, int *maxx, int *maxy, int *prefx, int *prefy); +void SiS_MakeClockRegs(ScrnInfoPtr pScrn, int clock, UCHAR *p2b, UCHAR *p2c); +#else +BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo); +#endif + +#ifdef LINUX_KERNEL +int sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + UCHAR modeno, UCHAR rateindex); +int sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + UCHAR modeno, UCHAR rateindex, + struct fb_var_screeninfo *var); +BOOLEAN sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + UCHAR modeno, int *htotal, int *vtotal, UCHAR rateindex); +#endif + +/* init301.c: */ +extern void SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo, int chkcrt2mode); +extern void SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo); +extern void SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +extern void SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo); +extern void SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +extern void SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +extern void SiS_DisableBridge(SiS_Private *, PSIS_HW_INFO); +extern BOOLEAN SiS_SetCRT2Group(SiS_Private *, PSIS_HW_INFO, USHORT); +extern USHORT SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo); +extern void SiS_WaitRetrace1(SiS_Private *SiS_Pr); +extern USHORT SiS_GetResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex); +extern USHORT SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempax); +extern USHORT SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo); +extern BOOLEAN SiS_IsVAMode(SiS_Private *, PSIS_HW_INFO); +extern BOOLEAN SiS_IsDualEdge(SiS_Private *, PSIS_HW_INFO); + +#ifdef LINUX_XF86 +/* From other sis driver modules: */ +extern int SiS_compute_vclk(int Clock, int *out_n, int *out_dn, int *out_div, + int *out_sbit, int *out_scale); +extern void SiSCalcClock(ScrnInfoPtr pScrn, int clock, int max_VLD, unsigned int *vclk); + +extern UCHAR SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, USHORT offset, UCHAR value); +extern UCHAR SiS_GetSetModeID(ScrnInfoPtr pScrn, UCHAR id); +extern USHORT SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode, ULONG VBFlags); +#endif + +#endif + diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c new file mode 100644 index 000000000000..2bc5b8097910 --- /dev/null +++ b/drivers/video/sis/init301.c @@ -0,0 +1,12239 @@ +/* $XFree86$ */ +/* $XdotOrg$ */ +/* + * Mode initializing code (CRT2 section) + * for SiS 300/305/540/630/730 and + * SiS 315/550/650/M650/651/661FX/M661xX/740/741(GX)/M741/330/660/M660/760/M760 + * (Universal module for Linux kernel framebuffer and XFree86/X.org 4.x) + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the named License, + * * or any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program; if not, write to the Free Software + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Otherwise, the following license terms apply: + * + * * Redistribution and use in source and binary forms, with or without + * * modification, are permitted provided that the following conditions + * * are met: + * * 1) Redistributions of source code must retain the above copyright + * * notice, this list of conditions and the following disclaimer. + * * 2) Redistributions in binary form must reproduce the above copyright + * * notice, this list of conditions and the following disclaimer in the + * * documentation and/or other materials provided with the distribution. + * * 3) The name of the author may not be used to endorse or promote products + * * derived from this software without specific prior written permission. + * * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + * Formerly based on non-functional code-fragements for 300 series by SiS, Inc. + * Used by permission. + * + * TW says: This code looks awful, I know. But please don't do anything about + * this otherwise debugging will be hell. + * The code is extremely fragile as regards the different chipsets, different + * video bridges and combinations thereof. If anything is changed, extreme + * care has to be taken that that change doesn't break it for other chipsets, + * bridges or combinations thereof. + * All comments in this file are by me, regardless if marked TW or not. + * + */ + +#if 1 +#define SET_EMI /* 302LV/ELV: Set EMI values */ +#endif + +#define COMPAL_HACK /* Needed for Compal 1400x1050 (EMI) */ +#define COMPAQ_HACK /* Needed for Inventec/Compaq 1280x1024 (EMI) */ +#define ASUS_HACK /* Needed for Asus A2H 1024x768 (EMI) */ + +#include "init301.h" + +#ifdef SIS300 +#include "oem300.h" +#endif + +#ifdef SIS315H +#include "oem310.h" +#endif + +#define SiS_I2CDELAY 1000 +#define SiS_I2CDELAYSHORT 150 + +static USHORT SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr); + +/*********************************************/ +/* HELPER: Lock/Unlock CRT2 */ +/*********************************************/ + +void +SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + if(HwInfo->jChipType >= SIS_315H) + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01); + else + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01); +} + +void +SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + if(HwInfo->jChipType >= SIS_315H) + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE); + else + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE); +} + +/*********************************************/ +/* HELPER: Write SR11 */ +/*********************************************/ + +static void +SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, USHORT DataOR) +{ + if(HwInfo->jChipType >= SIS_661) { + DataAND &= 0x0f; + DataOR &= 0x0f; + } + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR); +} + +/*********************************************/ +/* HELPER: Get Pointer to LCD structure */ +/*********************************************/ + +#ifdef SIS315H +static UCHAR * +GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + UCHAR *myptr = NULL; + USHORT romindex = 0, reg = 0, idx = 0; + + /* Use the BIOS tables only for LVDS panels; TMDS is unreliable + * due to the variaty of panels the BIOS doesn't know about. + * Exception: If the BIOS has better knowledge (such as in case + * of machines with a 301C and a panel that does not support DDC) + * use the BIOS data as well. + */ + + if((SiS_Pr->SiS_ROMNew) && + ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) || (!SiS_Pr->PanelSelfDetected))) { + + if(HwInfo->jChipType < SIS_661) reg = 0x3c; + else reg = 0x7d; + + idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26; + + if(idx < (8*26)) { + myptr = (UCHAR *)&SiS_LCDStruct661[idx]; + } + romindex = SISGETROMW(0x100); + if(romindex) { + romindex += idx; + myptr = &ROMAddr[romindex]; + } + } + return myptr; +} + +static USHORT +GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT romptr = 0; + + /* Use the BIOS tables only for LVDS panels; TMDS is unreliable + * due to the variaty of panels the BIOS doesn't know about. + * Exception: If the BIOS has better knowledge (such as in case + * of machines with a 301C and a panel that does not support DDC) + * use the BIOS data as well. + */ + + if((SiS_Pr->SiS_ROMNew) && + ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) || (!SiS_Pr->PanelSelfDetected))) { + romptr = SISGETROMW(0x102); + romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize); + } + + return(romptr); +} +#endif + +/*********************************************/ +/* Adjust Rate for CRT2 */ +/*********************************************/ + +static BOOLEAN +SiS_AdjustCRT2Rate(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RRTI, USHORT *i, PSIS_HW_INFO HwInfo) +{ + USHORT checkmask=0,modeid,infoflag; + + modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID; + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { + + checkmask |= SupportRAMDAC2; + if(HwInfo->jChipType >= SIS_315H) { + checkmask |= SupportRAMDAC2_135; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + checkmask |= SupportRAMDAC2_162; + if(SiS_Pr->SiS_VBType & VB_SIS301C) { + checkmask |= SupportRAMDAC2_202; + } + } + } + + } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + + checkmask |= SupportLCD; + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VBType & VB_SISVB) { + if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) { + if(modeid == 0x2e) checkmask |= Support64048060Hz; + } + } + } + + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + + checkmask |= SupportHiVision; + + } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) { + + checkmask |= SupportTV; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + checkmask |= SupportTV1024; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { + if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) { + checkmask |= SupportYPbPr750p; + } + } + } + + } + + } else { /* LVDS */ + + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + checkmask |= SupportCHTV; + } + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + checkmask |= SupportLCD; + } + + } + + /* Look backwards in table for matching CRT2 mode */ + for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) { + infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag; + if(infoflag & checkmask) return TRUE; + if((*i) == 0) break; + } + + /* Look through the whole mode-section of the table from the beginning + * for a matching CRT2 mode if no mode was found yet. + */ + for((*i) = 0; ; (*i)++) { + if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break; + infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag; + if(infoflag & checkmask) return TRUE; + } + return FALSE; +} + +/*********************************************/ +/* Get rate index */ +/*********************************************/ + +USHORT +SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo) +{ + SHORT LCDRefreshIndex[] = { 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00 }; + USHORT RRTI,i,backup_i; + USHORT modeflag,index,temp,backupindex; + + /* Do NOT check for UseCustomMode here, will skrew up FIFO */ + if(ModeNo == 0xfe) return 0; + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(modeflag & HalfDCLK) return 0; + } + } + + if(ModeNo < 0x14) return 0xFFFF; + + index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F; + backupindex = index; + + if(index > 0) index--; + + if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) { + if(SiS_Pr->SiS_VBType & VB_SISVB) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->SiS_VBType & VB_NoLCD) index = 0; + else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0; + } + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) { + temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)]; + if(index > temp) index = temp; + } + } + } else { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0; + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0; + } + } + } + + RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; + ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID; + + if(HwInfo->jChipType >= SIS_315H) { + if(!(SiS_Pr->SiS_VBInfo & DriverMode)) { + if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) || + (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) { + if(backupindex <= 1) RRTI++; + } + } + } + + i = 0; + do { + if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break; + temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag; + temp &= ModeTypeMask; + if(temp < SiS_Pr->SiS_ModeType) break; + i++; + index--; + } while(index != 0xFFFF); + + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag; + if(temp & InterlaceMode) i++; + } + } + + i--; + + if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) { + backup_i = i; + if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i, HwInfo))) { + i = backup_i; + } + } + + return(RRTI + i); +} + +/*********************************************/ +/* STORE CRT2 INFO in CR34 */ +/*********************************************/ + +static void +SiS_SaveCRT2Info(SiS_Private *SiS_Pr, USHORT ModeNo) +{ + USHORT temp1,temp2; + + /* Store CRT1 ModeNo in CR34 */ + SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo); + temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8; + temp2 = ~(SetInSlaveMode >> 8); + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1); +} + +/*********************************************/ +/* HELPER: GET SOME DATA FROM BIOS ROM */ +/*********************************************/ + +#ifdef SIS300 +static BOOLEAN +SiS_CR36BIOSWord23b(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT temp,temp1; + + if(SiS_Pr->SiS_UseROM) { + if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) { + temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f); + temp1 = SISGETROMW(0x23b); + if(temp1 & temp) return TRUE; + } + } + return FALSE; +} + +static BOOLEAN +SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT temp,temp1; + + if(SiS_Pr->SiS_UseROM) { + if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) { + temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f); + temp1 = SISGETROMW(0x23d); + if(temp1 & temp) return TRUE; + } + } + return FALSE; +} +#endif + +/*********************************************/ +/* HELPER: DELAY FUNCTIONS */ +/*********************************************/ + +void +SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime) +{ + USHORT i, j; + + for(i=0; i<delaytime; i++) { + j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05); + } +} + +#if defined(SIS300) || defined(SIS315H) +static void +SiS_GenericDelay(SiS_Private *SiS_Pr, USHORT delay) +{ + USHORT temp,flag; + + flag = SiS_GetRegByte(0x61) & 0x10; + + while(delay) { + temp = SiS_GetRegByte(0x61) & 0x10; + if(temp == flag) continue; + flag = temp; + delay--; + } +} +#endif + +#ifdef SIS315H +static void +SiS_LongDelay(SiS_Private *SiS_Pr, USHORT delay) +{ + while(delay--) { + SiS_GenericDelay(SiS_Pr,0x19df); + } +} +#endif + +#if defined(SIS300) || defined(SIS315H) +static void +SiS_ShortDelay(SiS_Private *SiS_Pr, USHORT delay) +{ + while(delay--) { + SiS_GenericDelay(SiS_Pr,0x42); + } +} +#endif + +static void +SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime) +{ +#if defined(SIS300) || defined(SIS315H) + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT PanelID, DelayIndex, Delay=0; +#endif + + if(HwInfo->jChipType < SIS_315H) { + +#ifdef SIS300 + + PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36); + if(SiS_Pr->SiS_VBType & VB_SISVB) { + if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7; + if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12; + } + DelayIndex = PanelID >> 4; + if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) { + Delay = 3; + } else { + if(DelayTime >= 2) DelayTime -= 2; + if(!(DelayTime & 0x01)) { + Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0]; + } else { + Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1]; + } + if(SiS_Pr->SiS_UseROM) { + if(ROMAddr[0x220] & 0x40) { + if(!(DelayTime & 0x01)) Delay = (USHORT)ROMAddr[0x225]; + else Delay = (USHORT)ROMAddr[0x226]; + } + } + } + SiS_ShortDelay(SiS_Pr, Delay); + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H + + if((HwInfo->jChipType >= SIS_661) || + (HwInfo->jChipType <= SIS_315PRO) || + (HwInfo->jChipType == SIS_330) || + (SiS_Pr->SiS_ROMNew)) { + + if(!(DelayTime & 0x01)) { + SiS_DDC2Delay(SiS_Pr, 0x1000); + } else { + SiS_DDC2Delay(SiS_Pr, 0x4000); + } + + } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* || + (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) || + (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) { /* 315 series, LVDS; Special */ + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36); + if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) { + if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12; + } + if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) { + DelayIndex = PanelID & 0x0f; + } else { + DelayIndex = PanelID >> 4; + } + if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) { + Delay = 3; + } else { + if(DelayTime >= 2) DelayTime -= 2; + if(!(DelayTime & 0x01)) { + Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0]; + } else { + Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1]; + } + if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) { + if(ROMAddr[0x13c] & 0x40) { + if(!(DelayTime & 0x01)) { + Delay = (USHORT)ROMAddr[0x17e]; + } else { + Delay = (USHORT)ROMAddr[0x17f]; + } + } + } + } + SiS_ShortDelay(SiS_Pr, Delay); + } + + } else if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 315 series, all bridges */ + + DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4; + if(!(DelayTime & 0x01)) { + Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0]; + } else { + Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1]; + } + Delay <<= 8; + SiS_DDC2Delay(SiS_Pr, Delay); + + } + +#endif /* SIS315H */ + + } +} + +#ifdef SIS315H +static void +SiS_PanelDelayLoop(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT DelayTime, USHORT DelayLoop) +{ + int i; + for(i=0; i<DelayLoop; i++) { + SiS_PanelDelay(SiS_Pr, HwInfo, DelayTime); + } +} +#endif + +/*********************************************/ +/* HELPER: WAIT-FOR-RETRACE FUNCTIONS */ +/*********************************************/ + +void +SiS_WaitRetrace1(SiS_Private *SiS_Pr) +{ + USHORT watchdog; + + if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return; + if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return; + + watchdog = 65535; + while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog); + watchdog = 65535; + while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog); +} + +#if defined(SIS300) || defined(SIS315H) +static void +SiS_WaitRetrace2(SiS_Private *SiS_Pr, USHORT reg) +{ + USHORT watchdog; + + watchdog = 65535; + while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog); + watchdog = 65535; + while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog); +} +#endif + +static void +SiS_WaitVBRetrace(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + if(HwInfo->jChipType < SIS_315H) { +#ifdef SIS300 + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return; + } + if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) { + SiS_WaitRetrace1(SiS_Pr); + } else { + SiS_WaitRetrace2(SiS_Pr, 0x25); + } +#endif + } else { +#ifdef SIS315H + if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) { + SiS_WaitRetrace1(SiS_Pr); + } else { + SiS_WaitRetrace2(SiS_Pr, 0x30); + } +#endif + } +} + +static void +SiS_VBWait(SiS_Private *SiS_Pr) +{ + USHORT tempal,temp,i,j; + + temp = 0; + for(i=0; i<3; i++) { + for(j=0; j<100; j++) { + tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da); + if(temp & 0x01) { + if((tempal & 0x08)) continue; + else break; + } else { + if(!(tempal & 0x08)) continue; + else break; + } + } + temp ^= 0x01; + } +} + +static void +SiS_VBLongWait(SiS_Private *SiS_Pr) +{ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + SiS_VBWait(SiS_Pr); + } else { + SiS_WaitRetrace1(SiS_Pr); + } +} + +/*********************************************/ +/* HELPER: MISC */ +/*********************************************/ + +#ifdef SIS300 +static BOOLEAN +SiS_Is301B(SiS_Private *SiS_Pr) +{ + if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE; + return FALSE; +} +#endif + +static BOOLEAN +SiS_CRT2IsLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT flag; + + if(HwInfo->jChipType == SIS_730) { + flag = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13); + if(flag & 0x20) return TRUE; + } + flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + if(flag & 0x20) return TRUE; + return FALSE; +} + +BOOLEAN +SiS_IsDualEdge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ +#ifdef SIS315H + USHORT flag; + + if(HwInfo->jChipType >= SIS_315H) { + if((HwInfo->jChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) { + flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + if(flag & EnableDualEdge) return TRUE; + } + } +#endif + return FALSE; +} + +BOOLEAN +SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ +#ifdef SIS315H + USHORT flag; + + if(HwInfo->jChipType >= SIS_315H) { + flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + if((flag & EnableDualEdge) && (flag & SetToLCDA)) return TRUE; + } +#endif + return FALSE; +} + +#ifdef SIS315H +static BOOLEAN +SiS_IsVAorLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + if(SiS_IsVAMode(SiS_Pr,HwInfo)) return TRUE; + if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) return TRUE; + return FALSE; +} +#endif + +static BOOLEAN +SiS_IsDualLink(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ +#ifdef SIS315H + if(HwInfo->jChipType >= SIS_315H) { + if((SiS_CRT2IsLCD(SiS_Pr, HwInfo)) || + (SiS_IsVAMode(SiS_Pr, HwInfo))) { + if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return TRUE; + } + } +#endif + return FALSE; +} + +#ifdef SIS315H +static BOOLEAN +SiS_TVEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE; + if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV302LV)) { + if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE; + } + return FALSE; +} +#endif + +#ifdef SIS315H +static BOOLEAN +SiS_LCDAEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE; + return FALSE; +} +#endif + +#ifdef SIS315H +static BOOLEAN +SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) { + if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE; + } + return FALSE; +} +#endif + +#ifdef SIS315H +static BOOLEAN +SiS_IsNotM650orLater(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT flag; + + if(HwInfo->jChipType == SIS_650) { + flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f); + flag &= 0xF0; + /* Check for revision != A0 only */ + if((flag == 0xe0) || (flag == 0xc0) || + (flag == 0xb0) || (flag == 0x90)) return FALSE; + } else if(HwInfo->jChipType >= SIS_661) return FALSE; + return TRUE; +} +#endif + +#ifdef SIS315H +static BOOLEAN +SiS_IsYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT flag; + + if(HwInfo->jChipType >= SIS_315H) { + flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + if(flag & EnableCHYPbPr) return TRUE; /* = YPrPb = 0x08 */ + } + return FALSE; +} +#endif + +#ifdef SIS315H +static BOOLEAN +SiS_IsChScart(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT flag; + + if(HwInfo->jChipType >= SIS_315H) { + flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + if(flag & EnableCHScart) return TRUE; /* = Scart = 0x04 */ + } + return FALSE; +} +#endif + +#ifdef SIS315H +static BOOLEAN +SiS_IsTVOrYPbPrOrScart(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT flag; + + if(HwInfo->jChipType >= SIS_315H) { + flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + if(flag & SetCRT2ToTV) return TRUE; + flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + if(flag & EnableCHYPbPr) return TRUE; /* = YPrPb = 0x08 */ + if(flag & EnableCHScart) return TRUE; /* = Scart = 0x04 - TW */ + } else { + flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + if(flag & SetCRT2ToTV) return TRUE; + } + return FALSE; +} +#endif + +#ifdef SIS315H +static BOOLEAN +SiS_IsLCDOrLCDA(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT flag; + + if(HwInfo->jChipType >= SIS_315H) { + flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + if(flag & SetCRT2ToLCD) return TRUE; + flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + if(flag & SetToLCDA) return TRUE; + } else { + flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + if(flag & SetCRT2ToLCD) return TRUE; + } + return FALSE; +} +#endif + +static BOOLEAN +SiS_BridgeIsOn(SiS_Private *SiS_Pr) +{ + USHORT flag; + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + return TRUE; + } else if(SiS_Pr->SiS_VBType & VB_SISVB) { + flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00); + if((flag == 1) || (flag == 2)) return TRUE; + } + return FALSE; +} + +static BOOLEAN +SiS_BridgeIsEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT flag; + + if(SiS_BridgeIsOn(SiS_Pr)) { + flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00); + if(HwInfo->jChipType < SIS_315H) { + flag &= 0xa0; + if((flag == 0x80) || (flag == 0x20)) return TRUE; + } else { + flag &= 0x50; + if((flag == 0x40) || (flag == 0x10)) return TRUE; + } + } + return FALSE; +} + +static BOOLEAN +SiS_BridgeInSlavemode(SiS_Private *SiS_Pr) +{ + USHORT flag1; + + flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31); + if(flag1 & (SetInSlaveMode >> 8)) return TRUE; + return FALSE; +} + +/*********************************************/ +/* GET VIDEO BRIDGE CONFIG INFO */ +/*********************************************/ + +/* Setup general purpose IO for Chrontel communication */ +void +SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo) +{ + unsigned long acpibase; + unsigned short temp; + + if(!(SiS_Pr->SiS_ChSW)) return; + +#ifdef LINUX_KERNEL + SiS_SetRegLong(0xcf8,0x80000874); /* get ACPI base */ + acpibase = SiS_GetRegLong(0xcfc); +#else + acpibase = pciReadLong(0x00000800, 0x74); +#endif + acpibase &= 0xFFFF; + temp = SiS_GetRegShort((USHORT)(acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */ + temp &= 0xFEFF; + SiS_SetRegShort((USHORT)(acpibase + 0x3c), temp); + temp = SiS_GetRegShort((USHORT)(acpibase + 0x3c)); + temp = SiS_GetRegShort((USHORT)(acpibase + 0x3a)); /* ACPI register 0x3a: GP Pin Level (low/high) */ + temp &= 0xFEFF; + if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100; + SiS_SetRegShort((USHORT)(acpibase + 0x3a), temp); + temp = SiS_GetRegShort((USHORT)(acpibase + 0x3a)); +} + +void +SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo, int checkcrt2mode) +{ + USHORT tempax,tempbx,temp; + USHORT modeflag, resinfo=0; + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } else if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + } + + SiS_Pr->SiS_SetFlag = 0; + + SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask; + + tempbx = 0; + if(SiS_BridgeIsOn(SiS_Pr)) { + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); +#if 0 + if(HwInfo->jChipType < SIS_661) { + /* NO - YPbPr not set yet ! */ + if(SiS_Pr->SiS_YPbPr & <all ypbpr except 525i>) { + temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode); /* 0x83 */ + temp |= SetCRT2ToHiVision; /* 0x80 */ + } + if(SiS_Pr->SiS_YPbPr & <ypbpr525i>) { + temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode); /* 0x83 */ + temp |= SetCRT2ToSVIDEO; /* 0x08 */ + } + } +#endif + tempbx |= temp; + tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8; + tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV); + tempbx |= tempax; + +#ifdef SIS315H + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VBType & VB_SISLCDA) { + if(ModeNo == 0x03) { + /* Mode 0x03 is never in driver mode */ + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf); + } + if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) { + /* Reset LCDA setting if not driver mode */ + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc); + } + if(IS_SIS650) { + if(SiS_Pr->SiS_UseLCDA) { + if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) { + if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA)); + } + } + } + } + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) { + tempbx |= SetCRT2ToLCDA; + } + } + + if(SiS_Pr->SiS_VBType & (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)) { + tempbx &= ~(SetCRT2ToRAMDAC); + } + + if(HwInfo->jChipType >= SIS_661) { + tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision); + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + if(SiS_Pr->SiS_VBType & VB_SISYPBPR) { + if(temp & 0x04) { + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0; + if(temp == 0x60) tempbx |= SetCRT2ToHiVision; + else tempbx |= SetCRT2ToYPbPr525750; + } + } else if(SiS_Pr->SiS_VBType & VB_SISHIVISION) { + if(temp & 0x04) { + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0; + if(temp == 0x60) tempbx |= SetCRT2ToHiVision; + } + } + } + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + if(temp & SetToLCDA) { + tempbx |= SetCRT2ToLCDA; + } + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(temp & EnableCHYPbPr) { + tempbx |= SetCRT2ToCHYPbPr; + } + } + } + } + +#endif /* SIS315H */ + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + temp = SetCRT2ToSVIDEO | + SetCRT2ToAVIDEO | + SetCRT2ToSCART | + SetCRT2ToLCDA | + SetCRT2ToLCD | + SetCRT2ToRAMDAC | + SetCRT2ToHiVision | + SetCRT2ToYPbPr525750; + } else { + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + temp = SetCRT2ToAVIDEO | + SetCRT2ToSVIDEO | + SetCRT2ToSCART | + SetCRT2ToLCDA | + SetCRT2ToLCD | + SetCRT2ToCHYPbPr; + } else { + temp = SetCRT2ToLCDA | + SetCRT2ToLCD; + } + } else { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + temp = SetCRT2ToTV | SetCRT2ToLCD; + } else { + temp = SetCRT2ToLCD; + } + } + } + + if(!(tempbx & temp)) { + tempax = DisableCRT2Display; + tempbx = 0; + } + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + USHORT clearmask = ( DriverMode | + DisableCRT2Display | + LoadDACFlag | + SetNotSimuMode | + SetInSlaveMode | + SetPALTV | + SwitchCRT2 | + SetSimuScanMode ); + if(tempbx & SetCRT2ToLCDA) tempbx &= (clearmask | SetCRT2ToLCDA); + if(tempbx & SetCRT2ToRAMDAC) tempbx &= (clearmask | SetCRT2ToRAMDAC); + if(tempbx & SetCRT2ToLCD) tempbx &= (clearmask | SetCRT2ToLCD); + if(tempbx & SetCRT2ToSCART) tempbx &= (clearmask | SetCRT2ToSCART); + if(tempbx & SetCRT2ToHiVision) tempbx &= (clearmask | SetCRT2ToHiVision); + if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750); + } else { + if(HwInfo->jChipType >= SIS_315H) { + if(tempbx & SetCRT2ToLCDA) { + tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode); + } + } + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(tempbx & SetCRT2ToTV) { + tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode); + } + } + if(tempbx & SetCRT2ToLCD) { + tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode); + } + if(HwInfo->jChipType >= SIS_315H) { + if(tempbx & SetCRT2ToLCDA) { + tempbx |= SetCRT2ToLCD; + } + } + } + + if(tempax & DisableCRT2Display) { + if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) { + tempbx = SetSimuScanMode | DisableCRT2Display; + } + } + + if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode; + + /* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */ + if(SiS_Pr->SiS_ModeType <= ModeVGA) { + if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) || + ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) { + modeflag &= (~CRT2Mode); + } + } + + if(!(tempbx & SetSimuScanMode)) { + if(tempbx & SwitchCRT2) { + if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) { + if( (HwInfo->jChipType >= SIS_315H) && + (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) { + if(resinfo != SIS_RI_1600x1200) { + tempbx |= SetSimuScanMode; + } + } else { + tempbx |= SetSimuScanMode; + } + } + } else { + if(SiS_BridgeIsEnabled(SiS_Pr,HwInfo)) { + if(!(tempbx & DriverMode)) { + if(SiS_BridgeInSlavemode(SiS_Pr)) { + tempbx |= SetSimuScanMode; + } + } + } + } + } + + if(!(tempbx & DisableCRT2Display)) { + if(tempbx & DriverMode) { + if(tempbx & SetSimuScanMode) { + if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) { + if( (HwInfo->jChipType >= SIS_315H) && + (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) { + if(resinfo != SIS_RI_1600x1200) { + tempbx |= SetInSlaveMode; + } + } else { + tempbx |= SetInSlaveMode; + } + } + } + } else { + tempbx |= SetInSlaveMode; + } + } + + } + + SiS_Pr->SiS_VBInfo = tempbx; + + if(HwInfo->jChipType == SIS_630) { + SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo); + } + +#ifdef TWDEBUG +#ifdef LINUX_KERNEL + printk(KERN_DEBUG "sisfb: (VBInfo= 0x%04x, SetFlag=0x%04x)\n", + SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag); +#endif +#ifdef LINUX_XF86 + xf86DrvMsgVerb(0, X_PROBED, 3, "(init301: VBInfo=0x%04x, SetFlag=0x%04x)\n", + SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag); +#endif +#endif +} + +/*********************************************/ +/* DETERMINE YPbPr MODE */ +/*********************************************/ + +void +SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + + UCHAR temp; + + /* Note: This variable is only used on 30xLV systems. + * CR38 has a different meaning on LVDS/CH7019 systems. + * On 661 and later, these bits moved to CR35. + * + * On 301, 301B, only HiVision 1080i is supported. + * On 30xLV, 301C, only YPbPr 1080i is supported. + */ + + SiS_Pr->SiS_YPbPr = 0; + if(HwInfo->jChipType >= SIS_661) return; + + if(SiS_Pr->SiS_VBType) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + SiS_Pr->SiS_YPbPr = YPbPrHiVision; + } + } + + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_SIS301C)) { + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + if(temp & 0x08) { + switch((temp >> 4)) { + case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i; break; + case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p; break; + case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p; break; + case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break; + } + } + } + } + +} + +/*********************************************/ +/* DETERMINE TVMode flag */ +/*********************************************/ + +void +SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT temp, temp1, resinfo = 0, romindex = 0; + UCHAR OutputSelect = *SiS_Pr->pSiS_OutputSelect; + + SiS_Pr->SiS_TVMode = 0; + + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return; + if(SiS_Pr->UseCustomMode) return; + + if(ModeNo > 0x13) { + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + } + + if(HwInfo->jChipType < SIS_661) { + + if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL; + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + temp = 0; + if((HwInfo->jChipType == SIS_630) || + (HwInfo->jChipType == SIS_730)) { + temp = 0x35; + romindex = 0xfe; + } else if(HwInfo->jChipType >= SIS_315H) { + temp = 0x38; + romindex = 0xf3; + if(HwInfo->jChipType >= SIS_330) romindex = 0x11b; + } + if(temp) { + if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) { + OutputSelect = ROMAddr[romindex]; + if(!(OutputSelect & EnablePALMN)) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F); + } + } + temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp); + if(SiS_Pr->SiS_TVMode & TVSetPAL) { + if(temp1 & EnablePALM) { /* 0x40 */ + SiS_Pr->SiS_TVMode |= TVSetPALM; + SiS_Pr->SiS_TVMode &= ~TVSetPAL; + } else if(temp1 & EnablePALN) { /* 0x80 */ + SiS_Pr->SiS_TVMode |= TVSetPALN; + } + } else { + if(temp1 & EnableNTSCJ) { /* 0x40 */ + SiS_Pr->SiS_TVMode |= TVSetNTSCJ; + } + } + } + /* Translate HiVision/YPbPr to our new flags */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + if(SiS_Pr->SiS_YPbPr == YPbPr750p) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p; + else if(SiS_Pr->SiS_YPbPr == YPbPr525p) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p; + else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision; + else SiS_Pr->SiS_TVMode |= TVSetYPbPr525i; + if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) { + SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision; + SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750; + } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) { + SiS_Pr->SiS_TVMode |= TVSetPAL; + } + } + } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_CHOverScan) { + if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) { + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) { + SiS_Pr->SiS_TVMode |= TVSetCHOverScan; + } + } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79); + if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) { + SiS_Pr->SiS_TVMode |= TVSetCHOverScan; + } + } + if(SiS_Pr->SiS_CHSOverScan) { + SiS_Pr->SiS_TVMode |= TVSetCHOverScan; + } + } + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38); + if(SiS_Pr->SiS_TVMode & TVSetPAL) { + if(temp & EnablePALM) SiS_Pr->SiS_TVMode |= TVSetPALM; + else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN; + } else { + if(temp & EnableNTSCJ) { + SiS_Pr->SiS_TVMode |= TVSetNTSCJ; + } + } + } + } + + } else { /* 661 and later */ + + temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + if(temp1 & 0x01) { + SiS_Pr->SiS_TVMode |= TVSetPAL; + if(temp1 & 0x08) { + SiS_Pr->SiS_TVMode |= TVSetPALN; + } else if(temp1 & 0x04) { + if(SiS_Pr->SiS_VBType & VB_SISVB) { + SiS_Pr->SiS_TVMode &= ~TVSetPAL; + } + SiS_Pr->SiS_TVMode |= TVSetPALM; + } + } else { + if(temp1 & 0x02) { + SiS_Pr->SiS_TVMode |= TVSetNTSCJ; + } + } + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + if(SiS_Pr->SiS_CHOverScan) { + if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) { + SiS_Pr->SiS_TVMode |= TVSetCHOverScan; + } + } + } + if(SiS_Pr->SiS_VBType & VB_SISVB) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { + temp1 &= 0xe0; + if(temp1 == 0x00) SiS_Pr->SiS_TVMode |= TVSetYPbPr525i; + else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p; + else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p; + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL); + } + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) { + if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) { + SiS_Pr->SiS_TVMode |= TVAspect169; + } else { + temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39); + if(temp1 & 0x02) { + if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) { + SiS_Pr->SiS_TVMode |= TVAspect169; + } else { + SiS_Pr->SiS_TVMode |= TVAspect43LB; + } + } else { + SiS_Pr->SiS_TVMode |= TVAspect43; + } + } + } + } + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL; + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + SiS_Pr->SiS_TVMode |= TVSetPAL; + SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ); + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { + if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) { + SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN); + } + } + + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) { + SiS_Pr->SiS_TVMode |= TVSetTVSimuMode; + } + } + + if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { + /* BIOS sets TVNTSC1024 without checking 525p here. Wrong? */ + if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr525p | TVSetYPbPr750p))) { + if(resinfo == SIS_RI_1024x768) { + SiS_Pr->SiS_TVMode |= TVSetNTSC1024; + } + } + } + + SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO; + if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && + (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO; + } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) { + SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO; + } else if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) { + if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) { + SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO; + } + } + + } + + SiS_Pr->SiS_VBInfo &= ~SetPALTV; + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo); +#endif +} + +/*********************************************/ +/* GET LCD INFO */ +/*********************************************/ + +static USHORT +SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr) +{ + USHORT temp = SiS_Pr->SiS_LCDResInfo; + /* Translate my LCDResInfo to BIOS value */ + if(temp == Panel_1280x768_2) temp = Panel_1280x768; + if(temp == Panel_1280x800_2) temp = Panel_1280x800; + return temp; +} + +static void +SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ +#ifdef SIS315H + UCHAR *ROMAddr; + USHORT temp; + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "Paneldata driver: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n", + SiS_Pr->PanelHT, SiS_Pr->PanelVT, + SiS_Pr->PanelHRS, SiS_Pr->PanelHRE, + SiS_Pr->PanelVRS, SiS_Pr->PanelVRE, + SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK, + SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A, + SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B); +#endif + + if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) { + if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) { + SiS_Pr->SiS_NeedRomModeData = TRUE; + SiS_Pr->PanelHT = temp; + } + if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) { + SiS_Pr->SiS_NeedRomModeData = TRUE; + SiS_Pr->PanelVT = temp; + } + SiS_Pr->PanelHRS = SISGETROMW(10); + SiS_Pr->PanelHRE = SISGETROMW(12); + SiS_Pr->PanelVRS = SISGETROMW(14); + SiS_Pr->PanelVRE = SISGETROMW(16); + SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315; + SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK = + SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (USHORT)((UCHAR)ROMAddr[18]); + SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B = + SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19]; + SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C = + SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20]; + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "Paneldata BIOS: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n", + SiS_Pr->PanelHT, SiS_Pr->PanelVT, + SiS_Pr->PanelHRS, SiS_Pr->PanelHRE, + SiS_Pr->PanelVRS, SiS_Pr->PanelVRE, + SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK, + SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A, + SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B); +#endif + + } +#endif +} + +static void +SiS_CheckScaling(SiS_Private *SiS_Pr, USHORT resinfo, const UCHAR *nonscalingmodes) +{ + int i = 0; + while(nonscalingmodes[i] != 0xff) { + if(nonscalingmodes[i++] == resinfo) { + if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) || + (SiS_Pr->UsePanelScaler == -1)) { + SiS_Pr->SiS_LCDInfo |= DontExpandLCD; + } + break; + } + } +} + +void +SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo) +{ +#ifdef SIS300 + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + const unsigned char SiS300SeriesLCDRes[] = + { 0, 1, 2, 3, 7, 4, 5, 8, + 0, 0, 10, 0, 0, 0, 0, 15 }; +#endif +#ifdef SIS315H + UCHAR *myptr = NULL; +#endif + USHORT temp,modeflag,resinfo=0,modexres=0,modeyres=0; + BOOLEAN panelcanscale = FALSE; + + SiS_Pr->SiS_LCDResInfo = 0; + SiS_Pr->SiS_LCDTypeInfo = 0; + SiS_Pr->SiS_LCDInfo = 0; + SiS_Pr->PanelHRS = 999; /* HSync start */ + SiS_Pr->PanelHRE = 999; /* HSync end */ + SiS_Pr->PanelVRS = 999; /* VSync start */ + SiS_Pr->PanelVRE = 999; /* VSync end */ + SiS_Pr->SiS_NeedRomModeData = FALSE; + + if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return; + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } else if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal; + modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal; + } + + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36); + + /* For broken BIOSes: Assume 1024x768 */ + if(temp == 0) temp = 0x02; + + if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) { + SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2; + } else if((HwInfo->jChipType < SIS_315H) || (HwInfo->jChipType >= SIS_661)) { + SiS_Pr->SiS_LCDTypeInfo = temp >> 4; + } else { + SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1; + } + temp &= 0x0f; +#ifdef SIS300 + if(HwInfo->jChipType < SIS_315H) { + /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */ + if(SiS_Pr->SiS_VBType & VB_SIS301) { + if(temp < 0x0f) temp &= 0x07; + } + /* Translate 300 series LCDRes to 315 series for unified usage */ + temp = SiS300SeriesLCDRes[temp]; + } +#endif + + /* Translate to our internal types */ + if(HwInfo->jChipType == SIS_550) { + if(temp == Panel310_640x480_2) temp = Panel_640x480_2; + if(temp == Panel310_640x480_3) temp = Panel_640x480_3; + } + + if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* SiS LVDS */ + if(temp == Panel310_1280x768) { + temp = Panel_1280x768_2; + } + if(SiS_Pr->SiS_ROMNew) { + if(temp == Panel661_1280x800) { + temp = Panel_1280x800_2; + } + } + } + + SiS_Pr->SiS_LCDResInfo = temp; + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) { + SiS_Pr->SiS_LCDResInfo = Panel_Barco1366; + } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) { + SiS_Pr->SiS_LCDResInfo = Panel_848x480; + } + } + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301) + SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301; + } else { + if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS) + SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS; + } + + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); + SiS_Pr->SiS_LCDInfo = temp & ~0x000e; + /* Need temp below! */ + + /* These can't scale no matter what */ + switch(SiS_Pr->SiS_LCDResInfo) { + case Panel_1280x960: + SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD; + } + + panelcanscale = (SiS_Pr->SiS_LCDInfo & DontExpandLCD) ? TRUE : FALSE; + + if(!SiS_Pr->UsePanelScaler) SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD; + else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD; + + /* Dual link, Pass 1:1 BIOS default, etc. */ +#ifdef SIS315H + if(HwInfo->jChipType >= SIS_661) { + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11; + } + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) { + if(SiS_Pr->SiS_ROMNew) { + if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink; + } else if((myptr = GetLCDStructPtr661(SiS_Pr, HwInfo))) { + if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink; + } + } + } else if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11; + } + if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) { + SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit); + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35); + if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit; + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) { + if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink; + } + } else if(!(SiS_Pr->SiS_ROMNew)) { + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) { + if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) && + (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) { + SiS_Pr->SiS_LCDInfo |= LCDDualLink; + } + if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) || + (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) || + (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) || + (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) { + SiS_Pr->SiS_LCDInfo |= LCDDualLink; + } + } + } + } +#endif + + /* Pass 1:1 */ + if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) { + /* Always center screen on LVDS (if scaling is disabled) */ + SiS_Pr->SiS_LCDInfo &= ~LCDPass11; + } else if(SiS_Pr->SiS_VBType & VB_SISVB) { + if(SiS_Pr->SiS_VBType & VB_SISLVDS) { + /* Always center screen on SiS LVDS (if scaling is disabled) */ + SiS_Pr->SiS_LCDInfo &= ~LCDPass11; + } else { + /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */ + if(panelcanscale) SiS_Pr->SiS_LCDInfo |= LCDPass11; + if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11; + } + } + + SiS_Pr->PanelVCLKIdx300 = VCLK65_300; + SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315; + + switch(SiS_Pr->SiS_LCDResInfo) { + case Panel_320x480: SiS_Pr->PanelXRes = 320; SiS_Pr->PanelYRes = 480; + SiS_Pr->PanelHT = 400; SiS_Pr->PanelVT = 525; + SiS_Pr->PanelVCLKIdx300 = VCLK28; + SiS_Pr->PanelVCLKIdx315 = VCLK28; + break; + case Panel_640x480_2: + case Panel_640x480_3: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480; + SiS_Pr->PanelVRS = 24; SiS_Pr->PanelVRE = 3; + SiS_Pr->PanelVCLKIdx300 = VCLK28; + SiS_Pr->PanelVCLKIdx315 = VCLK28; + break; + case Panel_640x480: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480; + SiS_Pr->PanelVRE = 3; + SiS_Pr->PanelVCLKIdx300 = VCLK28; + SiS_Pr->PanelVCLKIdx315 = VCLK28; + break; + case Panel_800x600: SiS_Pr->PanelXRes = 800; SiS_Pr->PanelYRes = 600; + SiS_Pr->PanelHT = 1056; SiS_Pr->PanelVT = 628; + SiS_Pr->PanelHRS = 40; SiS_Pr->PanelHRE = 128; + SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 4; + SiS_Pr->PanelVCLKIdx300 = VCLK40; + SiS_Pr->PanelVCLKIdx315 = VCLK40; + break; + case Panel_1024x600: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 600; + SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 800; + SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136; + SiS_Pr->PanelVRS = 2 /* 88 */ ; SiS_Pr->PanelVRE = 6; + SiS_Pr->PanelVCLKIdx300 = VCLK65_300; + SiS_Pr->PanelVCLKIdx315 = VCLK65_315; + break; + case Panel_1024x768: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768; + SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806; + SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136; + SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6; + if(HwInfo->jChipType < SIS_315H) { + SiS_Pr->PanelHRS = 23; + SiS_Pr->PanelVRE = 5; + } + SiS_Pr->PanelVCLKIdx300 = VCLK65_300; + SiS_Pr->PanelVCLKIdx315 = VCLK65_315; + SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo); + break; + case Panel_1152x768: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 768; + SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806; + SiS_Pr->PanelHRS = 24; + SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6; + if(HwInfo->jChipType < SIS_315H) { + SiS_Pr->PanelHRS = 23; + SiS_Pr->PanelVRE = 5; + } + SiS_Pr->PanelVCLKIdx300 = VCLK65_300; + SiS_Pr->PanelVCLKIdx315 = VCLK65_315; + break; + case Panel_1152x864: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 864; + break; + case Panel_1280x720: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 720; + SiS_Pr->PanelHT = 1650; SiS_Pr->PanelVT = 750; + SiS_Pr->PanelHRS = 110; SiS_Pr->PanelHRE = 40; + SiS_Pr->PanelVRS = 5; SiS_Pr->PanelVRE = 5; + SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720; + /* Data above for TMDS (projector); get from BIOS for LVDS */ + SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo); + break; + case Panel_1280x768: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768; + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 806; + SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */ + SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */ + } else { + SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 802; + SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRS = 112; + SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6; + SiS_Pr->PanelVCLKIdx300 = VCLK81_300; + SiS_Pr->PanelVCLKIdx315 = VCLK81_315; + } + break; + case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768; + SiS_Pr->PanelHT = 1660; SiS_Pr->PanelVT = 806; + SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112; + SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6; + SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2; + SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo); + break; + case Panel_1280x800: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800; + SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 816; + SiS_Pr->PanelHRS = 21; SiS_Pr->PanelHRE = 24; + SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3; + SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315; + SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo); + break; + case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800; + SiS_Pr->PanelHT = 1552; SiS_Pr->PanelVT = 812; + SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112; + SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3; + SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2; + SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo); + break; + case Panel_1280x960: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 960; + SiS_Pr->PanelHT = 1800; SiS_Pr->PanelVT = 1000; + SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300; + SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315; + if(resinfo == SIS_RI_1280x1024) { + SiS_Pr->PanelVCLKIdx300 = VCLK100_300; + SiS_Pr->PanelVCLKIdx315 = VCLK100_315; + } + break; + case Panel_1280x1024: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024; + SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066; + SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112; + SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3; + SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300; + SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315; + SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo); + break; + case Panel_1400x1050: SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050; + SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066; + SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112; /* HRE OK for LVDS, not for LCDA */ + SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3; + SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315; + SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo); + break; + case Panel_1600x1200: SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200; + SiS_Pr->PanelHT = 2160; SiS_Pr->PanelVT = 1250; + SiS_Pr->PanelHRS = 64; SiS_Pr->PanelHRE = 192; + SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3; + SiS_Pr->PanelVCLKIdx315 = VCLK162_315; + SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo); + break; + case Panel_1680x1050: SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050; + SiS_Pr->PanelHT = 1900; SiS_Pr->PanelVT = 1066; + SiS_Pr->PanelHRS = 26; SiS_Pr->PanelHRE = 76; + SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6; + SiS_Pr->PanelVCLKIdx315 = VCLK121_315; + SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo); + break; + case Panel_Barco1366: SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024; + SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066; + break; + case Panel_848x480: SiS_Pr->PanelXRes = 848; SiS_Pr->PanelYRes = 480; + SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525; + break; + case Panel_Custom: SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX; + SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY; + SiS_Pr->PanelHT = SiS_Pr->CHTotal; + SiS_Pr->PanelVT = SiS_Pr->CVTotal; + if(SiS_Pr->CP_PreferredIndex != -1) { + SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex]; + SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex]; + SiS_Pr->PanelHT = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex]; + SiS_Pr->PanelVT = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex]; + SiS_Pr->PanelHRS = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex]; + SiS_Pr->PanelHRE = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex]; + SiS_Pr->PanelVRS = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex]; + SiS_Pr->PanelVRE = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex]; + SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes; + SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS; + SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes; + SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS; + if(SiS_Pr->CP_PrefClock) { + int idx; + SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315; + SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300; + if(HwInfo->jChipType < SIS_315H) idx = VCLK_CUSTOM_300; + else idx = VCLK_CUSTOM_315; + SiS_Pr->SiS_VCLKData[idx].CLOCK = + SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock; + SiS_Pr->SiS_VCLKData[idx].SR2B = + SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B; + SiS_Pr->SiS_VCLKData[idx].SR2C = + SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C; + } + } + break; + default: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768; + SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806; + break; + } + + /* Special cases */ + if( (SiS_Pr->SiS_IF_DEF_FSTN) || + (SiS_Pr->SiS_IF_DEF_DSTN) || + (SiS_Pr->SiS_CustomT == CUT_BARCO1366) || + (SiS_Pr->SiS_CustomT == CUT_BARCO1024) || + (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) { + SiS_Pr->PanelHRS = 999; + SiS_Pr->PanelHRE = 999; + } + + if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) || + (SiS_Pr->SiS_CustomT == CUT_BARCO1024) || + (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) { + SiS_Pr->PanelVRS = 999; + SiS_Pr->PanelVRE = 999; + } + + /* DontExpand overrule */ + if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) { + + if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (modeflag & NoSupportLCDScale)) { + /* No scaling for this mode on any panel (LCD=CRT2)*/ + SiS_Pr->SiS_LCDInfo |= DontExpandLCD; + } + + switch(SiS_Pr->SiS_LCDResInfo) { + + case Panel_Custom: + case Panel_1152x864: + case Panel_1280x768: /* TMDS only */ + SiS_Pr->SiS_LCDInfo |= DontExpandLCD; + break; + + case Panel_800x600: { + static const UCHAR nonscalingmodes[] = { + SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff + }; + SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); + break; + } + case Panel_1024x768: { + static const UCHAR nonscalingmodes[] = { + SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, + SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, + 0xff + }; + SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); + break; + } + case Panel_1280x720: { + static const UCHAR nonscalingmodes[] = { + SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, + SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, + 0xff + }; + SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); + if(SiS_Pr->PanelHT == 1650) { + SiS_Pr->SiS_LCDInfo |= DontExpandLCD; + } + break; + } + case Panel_1280x768_2: { /* LVDS only */ + static const UCHAR nonscalingmodes[] = { + SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, + SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, + SIS_RI_1152x768,0xff + }; + SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); + switch(resinfo) { + case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) { + SiS_Pr->SiS_LCDInfo |= DontExpandLCD; + } + break; + } + break; + } + case Panel_1280x800: { /* SiS TMDS special (Averatec 6200 series) */ + static const UCHAR nonscalingmodes[] = { + SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, + SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, + SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff + }; + SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); + break; + } + case Panel_1280x800_2: { /* SiS LVDS */ + static const UCHAR nonscalingmodes[] = { + SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, + SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, + SIS_RI_1152x768,0xff + }; + SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); + switch(resinfo) { + case SIS_RI_1280x720: + case SIS_RI_1280x768: if(SiS_Pr->UsePanelScaler == -1) { + SiS_Pr->SiS_LCDInfo |= DontExpandLCD; + } + break; + } + break; + } + case Panel_1280x960: { + static const UCHAR nonscalingmodes[] = { + SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, + SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, + SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800, + 0xff + }; + SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); + break; + } + case Panel_1280x1024: { + static const UCHAR nonscalingmodes[] = { + SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, + SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, + SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800, + SIS_RI_1280x960,0xff + }; + SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); + break; + } + case Panel_1400x1050: { + static const UCHAR nonscalingmodes[] = { + SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, + SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, + SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x960, + 0xff + }; + SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); + switch(resinfo) { + case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) { + SiS_Pr->SiS_LCDInfo |= DontExpandLCD; + } + break; + case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD; + break; + } + break; + } + case Panel_1600x1200: { + static const UCHAR nonscalingmodes[] = { + SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, + SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, + SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800, + SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff + }; + SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); + break; + } + case Panel_1680x1050: { + static const UCHAR nonscalingmodes[] = { + SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480, + SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600, + SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024, + 0xff + }; + SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes); + break; + } + } + } + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(SiS_Pr->SiS_CustomT == CUT_PANEL848) { + SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20; /* neg h/v sync, RGB24(D0 = 0) */ + } + } + +#ifdef SIS300 + if(HwInfo->jChipType < SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(SiS_Pr->SiS_UseROM) { + if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) { + if(!(ROMAddr[0x235] & 0x02)) { + SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD); + } + } + } + } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) { + SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD); + } + } + } +#endif + + /* Special cases */ + + if(modexres == SiS_Pr->PanelXRes && modeyres == SiS_Pr->PanelYRes) { + SiS_Pr->SiS_LCDInfo &= ~LCDPass11; + } + + if(SiS_Pr->SiS_IF_DEF_TRUMPION) { + SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11); + } + + switch(SiS_Pr->SiS_LCDResInfo) { + case Panel_640x480: + SiS_Pr->SiS_LCDInfo |= LCDPass11; + break; + case Panel_1280x800: + /* Don't pass 1:1 by default (TMDS special) */ + if(SiS_Pr->CenterScreen == -1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11; + break; + case Panel_1280x960: + SiS_Pr->SiS_LCDInfo &= ~LCDPass11; + break; + case Panel_Custom: + if((!SiS_Pr->CP_PrefClock) || + (modexres > SiS_Pr->PanelXRes) || (modeyres > SiS_Pr->PanelYRes)) { + SiS_Pr->SiS_LCDInfo |= LCDPass11; + } + break; + } + + if(SiS_Pr->UseCustomMode) { + SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11); + } + + /* (In)validate LCDPass11 flag */ + if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) { + SiS_Pr->SiS_LCDInfo &= ~LCDPass11; + } + + /* LVDS DDA */ + if(!((HwInfo->jChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) { + + if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) { + if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) { + if(ModeNo == 0x12) { + if(SiS_Pr->SiS_LCDInfo & LCDPass11) { + SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; + } + } else if(ModeNo > 0x13) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) { + if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) { + if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) { + SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; + } + } + } + } + } + } + + if(modeflag & HalfDCLK) { + if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) { + SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; + } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; + } else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) { + SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; + } else if(ModeNo > 0x13) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; + } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) { + if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; + } + } + } + + } + + /* VESA timing */ + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) { + SiS_Pr->SiS_SetFlag |= LCDVESATiming; + } + } else { + SiS_Pr->SiS_SetFlag |= LCDVESATiming; + } + +#ifdef LINUX_KERNEL +#ifdef TWDEBUG + printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n", + SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo); +#endif +#endif +#ifdef LINUX_XF86 + xf86DrvMsgVerb(0, X_PROBED, 4, + "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x SetFlag=0x%04x)\n", + SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo, SiS_Pr->SiS_SetFlag); +#endif +} + +/*********************************************/ +/* GET VCLK */ +/*********************************************/ + +USHORT +SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo) +{ + USHORT CRT2Index,VCLKIndex=0,VCLKIndexGEN=0; + USHORT modeflag,resinfo,tempbx; + const UCHAR *CHTVVCLKPtr = NULL; + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; + CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + if(HwInfo->jChipType < SIS_315H) VCLKIndexGEN &= 0x3f; + } + + if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 30x/B/LV */ + + if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) { + + CRT2Index >>= 6; + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /* LCD */ + + if(HwInfo->jChipType < SIS_315H) { + VCLKIndex = SiS_Pr->PanelVCLKIdx300; + if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) { + VCLKIndex = VCLKIndexGEN; + } + } else { + VCLKIndex = SiS_Pr->PanelVCLKIdx315; + if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) { + switch(resinfo) { + /* Only those whose IndexGEN doesn't match VBVCLK array */ + case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break; + case SIS_RI_720x480: VCLKIndex = VCLK_720x480; break; + case SIS_RI_720x576: VCLKIndex = VCLK_720x576; break; + case SIS_RI_768x576: VCLKIndex = VCLK_768x576; break; + case SIS_RI_848x480: VCLKIndex = VCLK_848x480; break; + case SIS_RI_856x480: VCLKIndex = VCLK_856x480; break; + case SIS_RI_800x480: VCLKIndex = VCLK_800x480; break; + case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break; + case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break; + case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break; + default: VCLKIndex = VCLKIndexGEN; + } + + if(ModeNo <= 0x13) { + if(HwInfo->jChipType <= SIS_315PRO) { + if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42; + } else { + if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00; + } + } + if(HwInfo->jChipType <= SIS_315PRO) { + if(VCLKIndex == 0) VCLKIndex = 0x41; + if(VCLKIndex == 1) VCLKIndex = 0x43; + if(VCLKIndex == 4) VCLKIndex = 0x44; + } + } + } + + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* TV */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2; + else VCLKIndex = HiTVVCLK; + if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) { + if(modeflag & Charx8Dot) VCLKIndex = HiTVSimuVCLK; + else VCLKIndex = HiTVTextVCLK; + } + } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) VCLKIndex = YPbPr750pVCLK; + else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) VCLKIndex = TVVCLKDIV2; + else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = TVVCLKDIV2; + else VCLKIndex = TVVCLK; + + if(HwInfo->jChipType < SIS_315H) VCLKIndex += TVCLKBASE_300; + else VCLKIndex += TVCLKBASE_315; + + } else { /* VGA2 */ + + VCLKIndex = VCLKIndexGEN; + if(HwInfo->jChipType < SIS_315H) { + if(ModeNo > 0x13) { + if( (HwInfo->jChipType == SIS_630) && + (HwInfo->jChipRevision >= 0x30)) { + if(VCLKIndex == 0x14) VCLKIndex = 0x34; + } + /* Better VGA2 clock for 1280x1024@75 */ + if(VCLKIndex == 0x17) VCLKIndex = 0x45; + } + } + } + + } else { /* If not programming CRT2 */ + + VCLKIndex = VCLKIndexGEN; + if(HwInfo->jChipType < SIS_315H) { + if(ModeNo > 0x13) { + if( (HwInfo->jChipType != SIS_630) && + (HwInfo->jChipType != SIS_300) ) { + if(VCLKIndex == 0x1b) VCLKIndex = 0x48; + } + } + } + } + + } else { /* LVDS */ + + VCLKIndex = CRT2Index; + + if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) { + + if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) { + + VCLKIndex &= 0x1f; + tempbx = 0; + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1; + if(SiS_Pr->SiS_TVMode & TVSetPAL) { + tempbx += 2; + if(SiS_Pr->SiS_ModeType > ModeVGA) { + if(SiS_Pr->SiS_CHSOverScan) tempbx = 8; + } + if(SiS_Pr->SiS_TVMode & TVSetPALM) { + tempbx = 4; + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1; + } else if(SiS_Pr->SiS_TVMode & TVSetPALN) { + tempbx = 6; + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1; + } + } + switch(tempbx) { + case 0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC; break; + case 1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC; break; + case 2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL; break; + case 3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break; + case 4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM; break; + case 5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM; break; + case 6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN; break; + case 7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN; break; + case 8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL; break; + default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break; + } + VCLKIndex = CHTVVCLKPtr[VCLKIndex]; + + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + + if(HwInfo->jChipType < SIS_315H) { + VCLKIndex = SiS_Pr->PanelVCLKIdx300; + } else { + VCLKIndex = SiS_Pr->PanelVCLKIdx315; + } + + /* Special Timing: Barco iQ Pro R series */ + if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44; + + /* Special Timing: 848x480 parallel lvds */ + if(SiS_Pr->SiS_CustomT == CUT_PANEL848) { + if(HwInfo->jChipType < SIS_315H) { + VCLKIndex = VCLK34_300; + /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */ + } else { + VCLKIndex = VCLK34_315; + /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */ + } + } + + } else { + + VCLKIndex = VCLKIndexGEN; + if(HwInfo->jChipType < SIS_315H) { + if(ModeNo > 0x13) { + if( (HwInfo->jChipType == SIS_630) && + (HwInfo->jChipRevision >= 0x30) ) { + if(VCLKIndex == 0x14) VCLKIndex = 0x2e; + } + } + } + } + + } else { /* if not programming CRT2 */ + + VCLKIndex = VCLKIndexGEN; + if(HwInfo->jChipType < SIS_315H) { + if(ModeNo > 0x13) { + if( (HwInfo->jChipType != SIS_630) && + (HwInfo->jChipType != SIS_300) ) { + if(VCLKIndex == 0x1b) VCLKIndex = 0x48; + } +#if 0 + if(HwInfo->jChipType == SIS_730) { + if(VCLKIndex == 0x0b) VCLKIndex = 0x40; /* 1024x768-70 */ + if(VCLKIndex == 0x0d) VCLKIndex = 0x41; /* 1024x768-75 */ + } +#endif + } + } + + } + + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "VCLKIndex %d (0x%x)\n", VCLKIndex, VCLKIndex); +#endif + + return(VCLKIndex); +} + +/*********************************************/ +/* SET CRT2 MODE TYPE REGISTERS */ +/*********************************************/ + +static void +SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo) +{ + USHORT i,j,modeflag; + USHORT tempcl,tempah=0; +#if defined(SIS300) || defined(SIS315H) + USHORT tempbl; +#endif +#ifdef SIS315H + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT tempah2, tempbl2; +#endif + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } else if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40); + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7); + + } else { + + for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0); + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F); + } + + tempcl = SiS_Pr->SiS_ModeType; + + if(HwInfo->jChipType < SIS_315H) { + +#ifdef SIS300 /* ---- 300 series ---- */ + + /* For 301BDH: (with LCD via LVDS) */ + if(SiS_Pr->SiS_VBType & VB_NoLCD) { + tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32); + tempbl &= 0xef; + tempbl |= 0x02; + if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) { + tempbl |= 0x10; + tempbl &= 0xfd; + } + SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl); + } + + if(ModeNo > 0x13) { + tempcl -= ModeVGA; + if((tempcl > 0) || (tempcl == 0)) { /* tempcl is USHORT -> always true! */ + tempah = ((0x10 >> tempcl) | 0x80); + } + } else tempah = 0x80; + + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0xA0; + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* ------- 315/330 series ------ */ + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x08); + } + } + + if(ModeNo > 0x13) { + tempcl -= ModeVGA; + if((tempcl > 0) || (tempcl == 0)) { /* tempcl is USHORT -> always true! */ + tempah = (0x08 >> tempcl); + if (tempah == 0) tempah = 1; + tempah |= 0x40; + } + } else tempah = 0x40; + + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50; + +#endif /* SIS315H */ + + } + + if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0; + + if(HwInfo->jChipType < SIS_315H) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah); + } else { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah); + } else if(SiS_Pr->SiS_VBType & VB_SISVB) { + if(IS_SIS740) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah); + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah); + } + } + } + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + + tempah = 0x01; + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + tempah |= 0x02; + } + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) { + tempah ^= 0x05; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) { + tempah ^= 0x01; + } + } + + if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0; + + if(HwInfo->jChipType < SIS_315H) { + + tempah = (tempah << 5) & 0xFF; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah); + tempah = (tempah >> 5) & 0xFF; + + } else { + + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF8,tempah); + + } + + if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) { + tempah |= 0x10; + } + + tempah |= 0x80; + if(SiS_Pr->SiS_VBType & VB_SIS301) { + if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80; + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + tempah |= 0x20; + } + } + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah); + + tempah = 0x80; + if(SiS_Pr->SiS_VBType & VB_SIS301) { + if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0; + } + + if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempah |= 0x40; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) { + tempah |= 0x40; + } + } + + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah); + + } else { /* LVDS */ + + if(HwInfo->jChipType >= SIS_315H) { + +#ifdef SIS315H + /* LVDS can only be slave in 8bpp modes */ + tempah = 0x80; + if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) { + if(SiS_Pr->SiS_VBInfo & DriverMode) { + tempah |= 0x02; + } + } + + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + tempah |= 0x02; + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + tempah ^= 0x01; + } + + if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) { + tempah = 1; + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah); +#endif + + } else { + +#ifdef SIS300 + tempah = 0; + if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) { + tempah |= 0x02; + } + tempah <<= 5; + + if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0; + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah); +#endif + + } + + } + + } /* LCDA */ + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + + if(HwInfo->jChipType >= SIS_315H) { + +#ifdef SIS315H + unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); + + /* The following is nearly unpreditable and varies from machine + * to machine. Especially the 301DH seems to be a real trouble + * maker. Some BIOSes simply set the registers (like in the + * NoLCD-if-statements here), some set them according to the + * LCDA stuff. It is very likely that some machines are not + * treated correctly in the following, very case-orientated + * code. What do I do then...? + */ + + /* 740 variants match for 30xB, 301B-DH, 30xLV */ + + if(!(IS_SIS740)) { + tempah = 0x04; /* For all bridges */ + tempbl = 0xfb; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + tempah = 0x00; + if(SiS_IsDualEdge(SiS_Pr, HwInfo)) { + tempbl = 0xff; + } + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah); + } + + /* The following two are responsible for eventually wrong colors + * in TV output. The DH (VB_NoLCD) conditions are unknown; the + * b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version + * in a 650 box (Jake). What is the criteria? + */ + + if((IS_SIS740) || (HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) { + tempah = 0x30; + tempbl = 0xc0; + if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) || + ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) { + tempah = 0x00; + tempbl = 0x00; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,tempah); + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl); + } else if(SiS_Pr->SiS_VBType & VB_SIS301) { + /* Fixes "TV-blue-bug" on 315+301 */ + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf); /* For 301 */ + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f); + } else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); /* For 30xLV */ + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0); + } else if((SiS_Pr->SiS_VBType & VB_NoLCD) && (bridgerev == 0xb0)) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); /* For 30xB-DH rev b0 (or "DH on 651"?) */ + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0); + } else { + tempah = 0x30; tempah2 = 0xc0; /* For 30xB (and 301BDH rev b1) */ + tempbl = 0xcf; tempbl2 = 0x3f; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + tempah = tempah2 = 0x00; + if(SiS_IsDualEdge(SiS_Pr, HwInfo)) { + tempbl = tempbl2 = 0xff; + } + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah); + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2); + } + + if(IS_SIS740) { + tempah = 0x80; + if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00; + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah); + } else { + tempah = 0x00; + tempbl = 0x7f; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + tempbl = 0xff; + if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) tempah = 0x80; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah); + } + +#endif /* SIS315H */ + + } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + +#ifdef SIS300 + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f); + + if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) || + ((SiS_Pr->SiS_VBType & VB_NoLCD) && + (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F); + } else { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x23,0x80); + } +#endif + + } + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80); + if(SiS_Pr->SiS_VBType & VB_SIS301C) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0); + } + } + + } else { /* LVDS */ + +#ifdef SIS315H + if(HwInfo->jChipType >= SIS_315H) { + + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + + tempah = 0x04; + tempbl = 0xfb; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + tempah = 0x00; + if(SiS_IsDualEdge(SiS_Pr, HwInfo)) tempbl = 0xff; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah); + + if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb); + } + + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); + + } else if(HwInfo->jChipType == SIS_550) { + + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); + + } + + } +#endif + + } + +} + +/*********************************************/ +/* GET RESOLUTION DATA */ +/*********************************************/ + +USHORT +SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex) +{ + if(ModeNo <= 0x13) return((USHORT)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo); + else return((USHORT)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO); +} + +static void +SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo) +{ + USHORT xres,yres,modeflag=0,resindex; + + if(SiS_Pr->UseCustomMode) { + xres = SiS_Pr->CHDisplay; + if(SiS_Pr->CModeFlag & HalfDCLK) xres *= 2; + SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres; + yres = SiS_Pr->CVDisplay; + if(SiS_Pr->CModeFlag & DoubleScanMode) yres *= 2; + SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres; + return; + } + + resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex); + + if(ModeNo <= 0x13) { + xres = SiS_Pr->SiS_StResInfo[resindex].HTotal; + yres = SiS_Pr->SiS_StResInfo[resindex].VTotal; + } else { + xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal; + yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal; + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } + + if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) { + + if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) { + if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) { + if(yres == 350) yres = 400; + } + if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) { + if(ModeNo == 0x12) yres = 400; + } + } + + if(modeflag & HalfDCLK) xres *= 2; + if(modeflag & DoubleScanMode) yres *= 2; + + } + + if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) { + +#if 0 + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCDA | SetCRT2ToLCD | SetCRT2ToHiVision)) { + if(xres == 720) xres = 640; + } +#endif + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + switch(SiS_Pr->SiS_LCDResInfo) { + case Panel_1024x768: + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) { + if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) { + if(yres == 350) yres = 357; + if(yres == 400) yres = 420; + if(yres == 480) yres = 525; + } + } + break; + case Panel_1280x1024: + if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) { + /* BIOS bug - does this regardless of scaling */ + if(yres == 400) yres = 405; + } + if(yres == 350) yres = 360; + if(SiS_Pr->SiS_SetFlag & LCDVESATiming) { + if(yres == 360) yres = 375; + } + break; + case Panel_1600x1200: + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) { + if(yres == 1024) yres = 1056; + } + break; + } + } + + } else { + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) { + if(xres == 720) xres = 640; + } + } else if(xres == 720) xres = 640; + + if(SiS_Pr->SiS_SetFlag & SetDOSMode) { + yres = 400; + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480; + } else { + if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480; + } + if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480; + } + + } + SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres; + SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres; +} + +/*********************************************/ +/* GET CRT2 TIMING DATA */ +/*********************************************/ + +static BOOLEAN +SiS_GetLVDSCRT1Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, USHORT *ResIndex, + USHORT *DisplayType) + { + USHORT modeflag=0; + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE; + } + } else if(SiS_Pr->SiS_VBType & VB_SISVB) { + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE; + } else + return FALSE; + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + } + + (*ResIndex) &= 0x3F; + + if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) { + (*DisplayType) = 18; + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++; + if(SiS_Pr->SiS_TVMode & TVSetPAL) { + (*DisplayType) += 2; + if(SiS_Pr->SiS_ModeType > ModeVGA) { + if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 99; + } + if(SiS_Pr->SiS_TVMode & TVSetPALM) { + (*DisplayType) = 18; /* PALM uses NTSC data */ + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++; + } else if(SiS_Pr->SiS_TVMode & TVSetPALN) { + (*DisplayType) = 20; /* PALN uses PAL data */ + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++; + } + } + } else { + switch(SiS_Pr->SiS_LCDResInfo) { + case Panel_640x480: (*DisplayType) = 50; break; + case Panel_640x480_2: (*DisplayType) = 52; break; + case Panel_640x480_3: (*DisplayType) = 54; break; + case Panel_800x600: (*DisplayType) = 0; break; + case Panel_1024x600: (*DisplayType) = 23; break; + case Panel_1024x768: (*DisplayType) = 4; break; + case Panel_1152x768: (*DisplayType) = 27; break; + case Panel_1280x768: (*DisplayType) = 40; break; + case Panel_1280x1024: (*DisplayType) = 8; break; + case Panel_1400x1050: (*DisplayType) = 14; break; + case Panel_1600x1200: (*DisplayType) = 36; break; + default: return FALSE; + } + + if(modeflag & HalfDCLK) (*DisplayType)++; + + switch(SiS_Pr->SiS_LCDResInfo) { + case Panel_640x480: + case Panel_640x480_2: + case Panel_640x480_3: + break; + default: + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2; + } + + if(SiS_Pr->SiS_LCDInfo & LCDPass11) { + (*DisplayType) = 12; + if(modeflag & HalfDCLK) (*DisplayType)++; + } + } + +#if 0 + if(SiS_Pr->SiS_IF_DEF_FSTN) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480){ + (*DisplayType) = 22; + } + } +#endif + + return TRUE; +} + +static void +SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *CRT2Index,USHORT *ResIndex, + PSIS_HW_INFO HwInfo) +{ + USHORT tempbx=0,tempal=0,resinfo=0; + + if(ModeNo <= 0x13) { + tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + } else { + tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + } + + if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) { + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { /* LCD */ + + tempbx = SiS_Pr->SiS_LCDResInfo; + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32; + + if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) { + if (resinfo == SIS_RI_1280x800) tempal = 9; + else if(resinfo == SIS_RI_1400x1050) tempal = 11; + } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) || + (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2)) { + if (resinfo == SIS_RI_1280x768) tempal = 9; + } + + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + /* Pass 1:1 only (center-screen handled outside) */ + /* This is never called for the panel's native resolution */ + /* since Pass1:1 will not be set in this case */ + tempbx = 100; + if(ModeNo >= 0x13) { + tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS; + } + } + +#ifdef SIS315H + if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) { + if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) { + tempbx = 200; + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++; + } + } + } +#endif + + } else { /* TV */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */ + tempbx = 2; + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + tempbx = 13; + if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14; + } + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { + if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempbx = 7; + else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6; + else tempbx = 5; + if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5; + } else { + if(SiS_Pr->SiS_TVMode & TVSetPAL) tempbx = 3; + else tempbx = 4; + if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5; + } + + } + + tempal &= 0x3F; + + if(ModeNo > 0x13) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) { + if(tempal == 6) tempal = 7; + if((resinfo == SIS_RI_720x480) || + (resinfo == SIS_RI_720x576) || + (resinfo == SIS_RI_768x576)) { + tempal = 6; + if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) { + if(resinfo == SIS_RI_720x480) tempal = 9; + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { + if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) { + if(resinfo == SIS_RI_1024x768) tempal = 8; + } + if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) { + if((resinfo == SIS_RI_720x576) || + (resinfo == SIS_RI_768x576)) { + tempal = 8; + } + if(resinfo == SIS_RI_1280x720) tempal = 9; + } + } + } + } + + *CRT2Index = tempbx; + *ResIndex = tempal; + + } else { /* LVDS, 301B-DH (if running on LCD) */ + + tempbx = 0; + if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) { + + tempbx = 10; + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1; + if(SiS_Pr->SiS_TVMode & TVSetPAL) { + tempbx += 2; + if(SiS_Pr->SiS_ModeType > ModeVGA) { + if(SiS_Pr->SiS_CHSOverScan) tempbx = 99; + } + if(SiS_Pr->SiS_TVMode & TVSetPALM) { + tempbx = 90; + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1; + } else if(SiS_Pr->SiS_TVMode & TVSetPALN) { + tempbx = 92; + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1; + } + } + + } else { + + switch(SiS_Pr->SiS_LCDResInfo) { + case Panel_640x480: tempbx = 6; break; + case Panel_640x480_2: + case Panel_640x480_3: tempbx = 30; break; + case Panel_800x600: tempbx = 0; break; + case Panel_1024x600: tempbx = 15; break; + case Panel_1024x768: tempbx = 2; break; + case Panel_1152x768: tempbx = 17; break; + case Panel_1280x768: tempbx = 18; break; + case Panel_1280x1024: tempbx = 4; break; + case Panel_1400x1050: tempbx = 8; break; + case Panel_1600x1200: tempbx = 21; break; + case Panel_Barco1366: tempbx = 80; break; + } + + switch(SiS_Pr->SiS_LCDResInfo) { + case Panel_640x480: + case Panel_640x480_2: + case Panel_640x480_3: + break; + default: + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++; + } + + if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 7; + + if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) { + tempbx = 82; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++; + } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) { + tempbx = 84; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++; + } + + if((SiS_Pr->SiS_CustomT != CUT_BARCO1366) && + (SiS_Pr->SiS_CustomT != CUT_PANEL848)) { + if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && + (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) { + tempal = 0; + } + } + + } + + (*CRT2Index) = tempbx; + (*ResIndex) = tempal & 0x1F; + } +} + +static void +SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo) +{ + USHORT tempax=0,tempbx=0; + USHORT temp1=0,modeflag=0,tempcx=0; + USHORT index; + + SiS_Pr->SiS_RVBHCMAX = 1; + SiS_Pr->SiS_RVBHCFACT = 1; + + if(ModeNo <= 0x13) { + + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + index = SiS_GetModePtr(SiS_Pr,ModeNo,ModeIdIndex); + + tempax = SiS_Pr->SiS_StandTable[index].CRTC[0]; + tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6]; + temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7]; + + } else { + + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; + + tempax = SiS_Pr->SiS_CRT1Table[index].CR[0]; + tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8); + tempax &= 0x03FF; + tempbx = SiS_Pr->SiS_CRT1Table[index].CR[6]; + tempcx = SiS_Pr->SiS_CRT1Table[index].CR[13] << 8; + tempcx &= 0x0100; + tempcx <<= 2; + tempbx |= tempcx; + temp1 = SiS_Pr->SiS_CRT1Table[index].CR[7]; + + } + + if(temp1 & 0x01) tempbx |= 0x0100; + if(temp1 & 0x20) tempbx |= 0x0200; + + tempax += 5; + + /* Charx8Dot is no more used (and assumed), so we set it */ + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + modeflag |= Charx8Dot; + } + + if(modeflag & Charx8Dot) tempax *= 8; + else tempax *= 9; + + if(modeflag & HalfDCLK) tempax <<= 1; + + tempbx++; + + SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax; + SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx; +} + +static void +SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo) +{ + USHORT CRT2Index, ResIndex; + const SiS_LVDSDataStruct *LVDSData = NULL; + + SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + SiS_Pr->SiS_RVBHCMAX = 1; + SiS_Pr->SiS_RVBHCFACT = 1; + SiS_Pr->SiS_NewFlickerMode = 0; + SiS_Pr->SiS_RVBHRS = 50; + SiS_Pr->SiS_RY1COE = 0; + SiS_Pr->SiS_RY2COE = 0; + SiS_Pr->SiS_RY3COE = 0; + SiS_Pr->SiS_RY4COE = 0; + } + + if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + +#ifdef SIS315H + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + if(SiS_Pr->SiS_LCDInfo & LCDPass11) { + if(SiS_Pr->UseCustomMode) { + SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->CHTotal; + SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal; + } else { + if(ModeNo < 0x13) { + ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + } else { + ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS; + } + SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT; + SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT; + SiS_Pr->SiS_HT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT; + SiS_Pr->SiS_VT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT; + } + } else { + SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT; + SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT; + } + } else { + /* This handles custom modes and custom panels */ + SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes; + SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes; + SiS_Pr->SiS_HT = SiS_Pr->PanelHT; + SiS_Pr->SiS_VT = SiS_Pr->PanelVT; + SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE); + SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE); + } + + SiS_CalcLCDACRT1Timing(SiS_Pr,ModeNo,ModeIdIndex); + +#endif + + } else { + + /* 301BDH needs LVDS Data */ + if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) { + SiS_Pr->SiS_IF_DEF_LVDS = 1; + } + + SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, + &CRT2Index, &ResIndex, HwInfo); + + /* 301BDH needs LVDS Data */ + if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) { + SiS_Pr->SiS_IF_DEF_LVDS = 0; + } + + switch (CRT2Index) { + case 0: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1; break; + case 1: LVDSData = SiS_Pr->SiS_LVDS800x600Data_2; break; + case 2: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break; + case 3: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2; break; + case 4: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1; break; + case 5: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_2; break; + case 6: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1; break; + case 7: LVDSData = SiS_Pr->SiS_LVDSXXXxXXXData_1; break; + case 8: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_1; break; + case 9: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_2; break; + case 10: LVDSData = SiS_Pr->SiS_CHTVUNTSCData; break; + case 11: LVDSData = SiS_Pr->SiS_CHTVONTSCData; break; + case 12: LVDSData = SiS_Pr->SiS_CHTVUPALData; break; + case 13: LVDSData = SiS_Pr->SiS_CHTVOPALData; break; + case 14: LVDSData = SiS_Pr->SiS_LVDS320x480Data_1; break; + case 15: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1; break; + case 16: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_2; break; + case 17: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_1; break; + case 18: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_2; break; + case 19: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_1; break; + case 20: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2; break; + case 21: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_1; break; + case 22: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_2; break; + case 30: LVDSData = SiS_Pr->SiS_LVDS640x480Data_2; break; + case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1; break; + case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2; break; + case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1; break; + case 83: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_2; break; + case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1; break; + case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2; break; + case 90: LVDSData = SiS_Pr->SiS_CHTVUPALMData; break; + case 91: LVDSData = SiS_Pr->SiS_CHTVOPALMData; break; + case 92: LVDSData = SiS_Pr->SiS_CHTVUPALNData; break; + case 93: LVDSData = SiS_Pr->SiS_CHTVOPALNData; break; + case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData; break; /* Super Overscan */ + default: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break; + } + + SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT; + SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT; + SiS_Pr->SiS_HT = (LVDSData+ResIndex)->LCDHT; + SiS_Pr->SiS_VT = (LVDSData+ResIndex)->LCDVT; + + if(!(SiS_Pr->SiS_VBType & VB_SISVB)) { + if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) { + if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) { + SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes; + SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes; + if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) { + if(ResIndex < 0x08) { + SiS_Pr->SiS_HDE = 1280; + SiS_Pr->SiS_VDE = 1024; + } + } + } + } + } + } +} + +static void +SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = NULL; + USHORT tempax,tempbx,modeflag,romptr=0; + USHORT resinfo,CRT2Index,ResIndex; + const SiS_LCDDataStruct *LCDPtr = NULL; + const SiS_TVDataStruct *TVPtr = NULL; +#ifdef SIS315H + SHORT resinfo661; +#endif + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; + } else if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + resinfo = 0; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; +#ifdef SIS315H + resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661; + if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && + (SiS_Pr->SiS_SetFlag & LCDVESATiming) && + (resinfo661 >= 0) && + (SiS_Pr->SiS_NeedRomModeData) ) { + if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) { + if((romptr = (SISGETROMW(21)))) { + romptr += (resinfo661 * 10); + ROMAddr = HwInfo->pjVirtualRomBase; + } + } + } +#endif + } + + SiS_Pr->SiS_NewFlickerMode = 0; + SiS_Pr->SiS_RVBHRS = 50; + SiS_Pr->SiS_RY1COE = 0; + SiS_Pr->SiS_RY2COE = 0; + SiS_Pr->SiS_RY3COE = 0; + SiS_Pr->SiS_RY4COE = 0; + + SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex,HwInfo); + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC){ + + if(SiS_Pr->UseCustomMode) { + + SiS_Pr->SiS_RVBHCMAX = 1; + SiS_Pr->SiS_RVBHCFACT = 1; + SiS_Pr->SiS_VGAHT = SiS_Pr->CHTotal; + SiS_Pr->SiS_VGAVT = SiS_Pr->CVTotal; + SiS_Pr->SiS_HT = SiS_Pr->CHTotal; + SiS_Pr->SiS_VT = SiS_Pr->CVTotal; + SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE; + SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE; + + } else { + + SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + + } + + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + + SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + &CRT2Index,&ResIndex,HwInfo); + + switch(CRT2Index) { + case 2: TVPtr = SiS_Pr->SiS_ExtHiTVData; break; + case 3: TVPtr = SiS_Pr->SiS_ExtPALData; break; + case 4: TVPtr = SiS_Pr->SiS_ExtNTSCData; break; + case 5: TVPtr = SiS_Pr->SiS_Ext525iData; break; + case 6: TVPtr = SiS_Pr->SiS_Ext525pData; break; + case 7: TVPtr = SiS_Pr->SiS_Ext750pData; break; + case 8: TVPtr = SiS_Pr->SiS_StPALData; break; + case 9: TVPtr = SiS_Pr->SiS_StNTSCData; break; + case 10: TVPtr = SiS_Pr->SiS_St525iData; break; + case 11: TVPtr = SiS_Pr->SiS_St525pData; break; + case 12: TVPtr = SiS_Pr->SiS_St750pData; break; + case 13: TVPtr = SiS_Pr->SiS_St1HiTVData; break; + case 14: TVPtr = SiS_Pr->SiS_St2HiTVData; break; + default: TVPtr = SiS_Pr->SiS_StPALData; break; + } + + SiS_Pr->SiS_RVBHCMAX = (TVPtr+ResIndex)->RVBHCMAX; + SiS_Pr->SiS_RVBHCFACT = (TVPtr+ResIndex)->RVBHCFACT; + SiS_Pr->SiS_VGAHT = (TVPtr+ResIndex)->VGAHT; + SiS_Pr->SiS_VGAVT = (TVPtr+ResIndex)->VGAVT; + SiS_Pr->SiS_HDE = (TVPtr+ResIndex)->TVHDE; + SiS_Pr->SiS_VDE = (TVPtr+ResIndex)->TVVDE; + SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->RVBHRS; + SiS_Pr->SiS_NewFlickerMode = (TVPtr+ResIndex)->FlickerMode; + if(modeflag & HalfDCLK) { + SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS; + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + + if((resinfo == SIS_RI_1024x768) || + (resinfo == SIS_RI_1280x1024) || + (resinfo == SIS_RI_1280x720)) { + SiS_Pr->SiS_NewFlickerMode = 0x40; + } + + if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode; + + SiS_Pr->SiS_HT = ExtHiTVHT; + SiS_Pr->SiS_VT = ExtHiTVVT; + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) { + SiS_Pr->SiS_HT = StHiTVHT; + SiS_Pr->SiS_VT = StHiTVVT; +#if 0 + if(!(modeflag & Charx8Dot)) { + SiS_Pr->SiS_HT = StHiTextTVHT; + SiS_Pr->SiS_VT = StHiTextTVVT; + } +#endif + } + } + + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { + + if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) { + SiS_Pr->SiS_HT = 1650; + SiS_Pr->SiS_VT = 750; + } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) { + SiS_Pr->SiS_HT = NTSCHT; + SiS_Pr->SiS_VT = NTSCVT; + } else { + SiS_Pr->SiS_HT = NTSCHT; + if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT; + SiS_Pr->SiS_VT = NTSCVT; + } + + } else { + + SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE; + SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE; + SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE; + SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE; + + if(modeflag & HalfDCLK) { + SiS_Pr->SiS_RY1COE = 0x00; + SiS_Pr->SiS_RY2COE = 0xf4; + SiS_Pr->SiS_RY3COE = 0x10; + SiS_Pr->SiS_RY4COE = 0x38; + } + + if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { + SiS_Pr->SiS_HT = NTSCHT; + if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT; + SiS_Pr->SiS_VT = NTSCVT; + } else { + SiS_Pr->SiS_HT = PALHT; + SiS_Pr->SiS_VT = PALVT; + } + + } + + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + + SiS_Pr->SiS_RVBHCMAX = 1; + SiS_Pr->SiS_RVBHCFACT = 1; + + if(SiS_Pr->UseCustomMode) { + + SiS_Pr->SiS_VGAHT = SiS_Pr->CHTotal; + SiS_Pr->SiS_VGAVT = SiS_Pr->CVTotal; + SiS_Pr->SiS_HT = SiS_Pr->CHTotal; + SiS_Pr->SiS_VT = SiS_Pr->CVTotal; + SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE; + SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE; + + } else { + + BOOLEAN gotit = FALSE; + + if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) { + + SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT; + SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT; + SiS_Pr->SiS_HT = SiS_Pr->PanelHT; + SiS_Pr->SiS_VT = SiS_Pr->PanelVT; + gotit = TRUE; + + } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) { + +#ifdef SIS315H + SiS_Pr->SiS_RVBHCMAX = ROMAddr[romptr]; + SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1]; + SiS_Pr->SiS_VGAHT = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8); + SiS_Pr->SiS_VGAVT = ROMAddr[romptr+4] | ((ROMAddr[romptr+3] & 0xf0) << 4); + SiS_Pr->SiS_HT = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8); + SiS_Pr->SiS_VT = ROMAddr[romptr+7] | ((ROMAddr[romptr+6] & 0xf0) << 4); + if(SiS_Pr->SiS_VGAHT) gotit = TRUE; + else { + SiS_Pr->SiS_LCDInfo |= DontExpandLCD; + SiS_Pr->SiS_LCDInfo &= ~LCDPass11; + SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT; + SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT; + SiS_Pr->SiS_HT = SiS_Pr->PanelHT; + SiS_Pr->SiS_VT = SiS_Pr->PanelVT; + gotit = TRUE; + } +#endif + + } + + if(!gotit) { + + SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + &CRT2Index,&ResIndex,HwInfo); + + switch(CRT2Index) { + case Panel_1024x768 : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break; + case Panel_1024x768 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data; break; + case Panel_1280x720 : + case Panel_1280x720 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data; break; + case Panel_1280x768_2 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break; + case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data; break; + case Panel_1280x800 : + case Panel_1280x800 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data; break; + case Panel_1280x800_2 : + case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data; break; + case Panel_1280x960 : + case Panel_1280x960 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data; break; + case Panel_1280x1024 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data; break; + case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break; + case Panel_1400x1050 : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data; break; + case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data; break; + case Panel_1600x1200 : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data; break; + case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data; break; + case Panel_1680x1050 : + case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data; break; + case 100 : LCDPtr = SiS_Pr->SiS_NoScaleData; break; +#ifdef SIS315H + case 200 : LCDPtr = SiS310_ExtCompaq1280x1024Data; break; + case 201 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break; +#endif + default : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break; + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex); +#endif + + SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX; + SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT; + SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT; + SiS_Pr->SiS_VGAVT = (LCDPtr+ResIndex)->VGAVT; + SiS_Pr->SiS_HT = (LCDPtr+ResIndex)->LCDHT; + SiS_Pr->SiS_VT = (LCDPtr+ResIndex)->LCDVT; + + } + + tempax = SiS_Pr->PanelXRes; + tempbx = SiS_Pr->PanelYRes; + + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + if(SiS_Pr->SiS_SetFlag & LCDVESATiming) { + if(HwInfo->jChipType < SIS_315H) { + if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560; + else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640; + } + } else { + if (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527; + else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620; + else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775; + else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775; + else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560; + else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640; + } + } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) { + if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 700; + else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 800; + else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960; + } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) { + if (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768; + else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800; + else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864; + } else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) { + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) { + if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 875; + else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 1000; + } + } + + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + tempax = SiS_Pr->SiS_VGAHDE; + tempbx = SiS_Pr->SiS_VGAVDE; + } + + SiS_Pr->SiS_HDE = tempax; + SiS_Pr->SiS_VDE = tempbx; + } + } +} + +static void +SiS_GetCRT2Data(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo) +{ + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + } else { + if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) { + /* Need LVDS Data for LCD on 301B-DH */ + SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + } else { + SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + } + } + + } else { + + SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + + } +} + +/*********************************************/ +/* GET LVDS DES (SKEW) DATA */ +/*********************************************/ + +static void +SiS_GetLVDSDesPtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, USHORT *PanelIndex, + USHORT *ResIndex, PSIS_HW_INFO HwInfo) +{ + USHORT modeflag; + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + } + + (*ResIndex) &= 0x1F; + (*PanelIndex) = 0; + + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + (*PanelIndex) = 50; + if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) (*PanelIndex) += 2; + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*PanelIndex) += 1; + /* Nothing special needed for SOverscan */ + /* PALM uses NTSC data, PALN uses PAL data */ + } + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + *PanelIndex = SiS_Pr->SiS_LCDTypeInfo; + if(HwInfo->jChipType >= SIS_661) { + /* As long as we don's use the BIOS tables, we + * need to convert the TypeInfo as for 315 series + */ + (*PanelIndex) = SiS_Pr->SiS_LCDResInfo - 1; + } + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + (*PanelIndex) += 16; + if(SiS_Pr->SiS_LCDInfo & LCDPass11) { + (*PanelIndex) = 32; + if(modeflag & HalfDCLK) (*PanelIndex)++; + } + } + } + + if(SiS_Pr->SiS_SetFlag & SetDOSMode) { + if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) { + (*ResIndex) = 7; + if(HwInfo->jChipType < SIS_315H) { + if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) (*ResIndex)++; + } + } + } +} + +static void +SiS_GetLVDSDesData(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo) +{ + USHORT modeflag; + USHORT PanelIndex,ResIndex; + const SiS_LVDSDesStruct *PanelDesPtr = NULL; + + SiS_Pr->SiS_LCDHDES = 0; + SiS_Pr->SiS_LCDVDES = 0; + + if( (SiS_Pr->UseCustomMode) || + (SiS_Pr->SiS_LCDResInfo == Panel_Custom) || + (SiS_Pr->SiS_CustomT == CUT_PANEL848) || + ((SiS_Pr->SiS_VBType & VB_SISVB) && + (SiS_Pr->SiS_LCDInfo & DontExpandLCD) && + (SiS_Pr->SiS_LCDInfo & LCDPass11)) ) { + return; + } + + if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + +#ifdef SIS315H + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + /* non-pass 1:1 only, see above */ + if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) { + SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2); + } + if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) { + SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2); + } + } + if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) { + switch(SiS_Pr->SiS_CustomT) { + case CUT_UNIWILL1024: + case CUT_UNIWILL10242: + case CUT_CLEVO1400: + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1; + } + break; + } + if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) { + if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) { + SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1; + } + } + } +#endif + + } else { + + SiS_GetLVDSDesPtr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, + &PanelIndex, &ResIndex, HwInfo); + + switch(PanelIndex) { + case 0: PanelDesPtr = SiS_Pr->SiS_PanelType00_1; break; /* --- */ + case 1: PanelDesPtr = SiS_Pr->SiS_PanelType01_1; break; + case 2: PanelDesPtr = SiS_Pr->SiS_PanelType02_1; break; + case 3: PanelDesPtr = SiS_Pr->SiS_PanelType03_1; break; + case 4: PanelDesPtr = SiS_Pr->SiS_PanelType04_1; break; + case 5: PanelDesPtr = SiS_Pr->SiS_PanelType05_1; break; + case 6: PanelDesPtr = SiS_Pr->SiS_PanelType06_1; break; + case 7: PanelDesPtr = SiS_Pr->SiS_PanelType07_1; break; + case 8: PanelDesPtr = SiS_Pr->SiS_PanelType08_1; break; + case 9: PanelDesPtr = SiS_Pr->SiS_PanelType09_1; break; + case 10: PanelDesPtr = SiS_Pr->SiS_PanelType0a_1; break; + case 11: PanelDesPtr = SiS_Pr->SiS_PanelType0b_1; break; + case 12: PanelDesPtr = SiS_Pr->SiS_PanelType0c_1; break; + case 13: PanelDesPtr = SiS_Pr->SiS_PanelType0d_1; break; + case 14: PanelDesPtr = SiS_Pr->SiS_PanelType0e_1; break; + case 15: PanelDesPtr = SiS_Pr->SiS_PanelType0f_1; break; + case 16: PanelDesPtr = SiS_Pr->SiS_PanelType00_2; break; /* --- */ + case 17: PanelDesPtr = SiS_Pr->SiS_PanelType01_2; break; + case 18: PanelDesPtr = SiS_Pr->SiS_PanelType02_2; break; + case 19: PanelDesPtr = SiS_Pr->SiS_PanelType03_2; break; + case 20: PanelDesPtr = SiS_Pr->SiS_PanelType04_2; break; + case 21: PanelDesPtr = SiS_Pr->SiS_PanelType05_2; break; + case 22: PanelDesPtr = SiS_Pr->SiS_PanelType06_2; break; + case 23: PanelDesPtr = SiS_Pr->SiS_PanelType07_2; break; + case 24: PanelDesPtr = SiS_Pr->SiS_PanelType08_2; break; + case 25: PanelDesPtr = SiS_Pr->SiS_PanelType09_2; break; + case 26: PanelDesPtr = SiS_Pr->SiS_PanelType0a_2; break; + case 27: PanelDesPtr = SiS_Pr->SiS_PanelType0b_2; break; + case 28: PanelDesPtr = SiS_Pr->SiS_PanelType0c_2; break; + case 29: PanelDesPtr = SiS_Pr->SiS_PanelType0d_2; break; + case 30: PanelDesPtr = SiS_Pr->SiS_PanelType0e_2; break; + case 31: PanelDesPtr = SiS_Pr->SiS_PanelType0f_2; break; + case 32: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_1; break; /* pass 1:1 */ + case 33: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_2; break; + case 50: PanelDesPtr = SiS_Pr->SiS_CHTVUNTSCDesData; break; /* TV */ + case 51: PanelDesPtr = SiS_Pr->SiS_CHTVONTSCDesData; break; + case 52: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData; break; + case 53: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData; break; + default: return; + } + + SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES; + SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES; + + if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632; + } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) { + if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) { + if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) { + if(HwInfo->jChipType < SIS_315H) { + if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320; + } else { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) SiS_Pr->SiS_LCDHDES = 480; + if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804; + if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704; + if(!(modeflag & HalfDCLK)) { + SiS_Pr->SiS_LCDHDES = 320; + if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632; + if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542; + } + } + } + } + } + } + } +} + +/*********************************************/ +/* DISABLE VIDEO BRIDGE */ +/*********************************************/ + +/* NEVER use any variables (VBInfo), this will be called + * from outside the context of modeswitch! + * MUST call getVBType before calling this + */ +void +SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ +#ifdef SIS315H + USHORT tempah,pushax=0,modenum; +#endif + USHORT temp=0; + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* ===== For 30xB/LV ===== */ + + if(HwInfo->jChipType < SIS_315H) { + +#ifdef SIS300 /* 300 series */ + + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) { + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE); + } else { + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08); + } + SiS_PanelDelay(SiS_Pr, HwInfo, 3); + } + if(SiS_Is301B(SiS_Pr)) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f); + SiS_ShortDelay(SiS_Pr,1); + } + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); + SiS_DisplayOff(SiS_Pr); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); + SiS_UnLockCRT2(SiS_Pr,HwInfo); + if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); + } + if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) || + (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) { + SiS_PanelDelay(SiS_Pr, HwInfo, 2); + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD); + } else { + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04); + } + } + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* 315 series */ + + BOOLEAN custom1 = ((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) || + (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) ? TRUE : FALSE; + + modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f; + + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + +#ifdef SET_EMI + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) { + if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c); + } + } +#endif + if( (modenum <= 0x13) || + (SiS_IsVAMode(SiS_Pr,HwInfo)) || + (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE); + if(custom1) SiS_PanelDelay(SiS_Pr, HwInfo, 3); + } + + if(!custom1) { + SiS_DDC2Delay(SiS_Pr,0xff00); + SiS_DDC2Delay(SiS_Pr,0xe000); + SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00); + pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06); + if(IS_SIS740) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3); + } + SiS_PanelDelay(SiS_Pr, HwInfo, 3); + } + + } + + if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) { + if(HwInfo->jChipType < SIS_340) { + tempah = 0xef; + if(SiS_IsVAMode(SiS_Pr,HwInfo)) tempah = 0xf7; + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah); + } + } + + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10); + } + + tempah = 0x3f; + if(SiS_IsDualEdge(SiS_Pr,HwInfo)) { + tempah = 0x7f; + if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) tempah = 0xbf; + } + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah); + + if((SiS_IsVAMode(SiS_Pr,HwInfo)) || + ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) { + + SiS_DisplayOff(SiS_Pr); + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + SiS_PanelDelay(SiS_Pr, HwInfo, 2); + } + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF); + + } + + if((!(SiS_IsVAMode(SiS_Pr,HwInfo))) || + ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) { + + if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) { + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf); + SiS_DisplayOff(SiS_Pr); + } + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80); + + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + SiS_PanelDelay(SiS_Pr, HwInfo, 2); + } + + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); + temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp); + + } + + if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f); + } + + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + + if(!custom1) { + + if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) { + if(!(SiS_CRT2IsLCD(SiS_Pr,HwInfo))) { + if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD); + } + } + } + + SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax); + + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) { + if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) { + SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 20); + } + } + + } else { + + if((SiS_IsVAMode(SiS_Pr,HwInfo)) || + (!(SiS_IsDualEdge(SiS_Pr,HwInfo)))) { + if((!(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo))) || + (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo)))) { + SiS_PanelDelay(SiS_Pr, HwInfo, 2); + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD); + SiS_PanelDelay(SiS_Pr, HwInfo, 4); + } + } + + } + } + +#endif /* SIS315H */ + + } + + } else { /* ============ For 301 ================ */ + + if(HwInfo->jChipType < SIS_315H) { +#ifdef SIS300 + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) { + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08); + SiS_PanelDelay(SiS_Pr, HwInfo, 3); + } +#endif + } + + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); /* disable VB */ + SiS_DisplayOff(SiS_Pr); + + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80); + } + + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); /* disable lock mode */ + + if(HwInfo->jChipType >= SIS_315H) { + temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10); + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp); + } else { +#ifdef SIS300 + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */ + if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) || + (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) { + SiS_PanelDelay(SiS_Pr, HwInfo, 2); + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04); + } +#endif + } + + } + + } else { /* ============ For LVDS =============*/ + + if(HwInfo->jChipType < SIS_315H) { + +#ifdef SIS300 /* 300 series */ + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) { + SiS_SetCH700x(SiS_Pr,0x090E); + } + + if(HwInfo->jChipType == SIS_730) { + if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) { + SiS_WaitVBRetrace(SiS_Pr,HwInfo); + } + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) { + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08); + SiS_PanelDelay(SiS_Pr, HwInfo, 3); + } + } else { + if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) { + if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) { + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) { + SiS_WaitVBRetrace(SiS_Pr,HwInfo); + if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) { + SiS_DisplayOff(SiS_Pr); + } + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08); + SiS_PanelDelay(SiS_Pr, HwInfo, 3); + } + } + } + } + + SiS_DisplayOff(SiS_Pr); + + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); + + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); + SiS_UnLockCRT2(SiS_Pr,HwInfo); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); + + if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) || + (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) { + SiS_PanelDelay(SiS_Pr, HwInfo, 2); + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04); + } + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* 315 series */ + + if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) { + if(HwInfo->jChipType < SIS_340) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18); + } + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + + if(HwInfo->jChipType == SIS_740) { + temp = SiS_GetCH701x(SiS_Pr,0x61); + if(temp < 1) { + SiS_SetCH701x(SiS_Pr,0xac76); + SiS_SetCH701x(SiS_Pr,0x0066); + } + + if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) || + (SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) ) { + SiS_SetCH701x(SiS_Pr,0x3e49); + } + } + + if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) || + (SiS_IsVAMode(SiS_Pr,HwInfo)) ) { + SiS_Chrontel701xBLOff(SiS_Pr); + SiS_Chrontel701xOff(SiS_Pr,HwInfo); + } + + if(HwInfo->jChipType != SIS_740) { + if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) || + (SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) ) { + SiS_SetCH701x(SiS_Pr,0x0149); + } + } + + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08); + SiS_PanelDelay(SiS_Pr, HwInfo, 3); + } + + if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) || + (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) || + (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo))) ) { + SiS_DisplayOff(SiS_Pr); + } + + if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) || + (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) || + (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80); + } + + if(HwInfo->jChipType == SIS_740) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f); + } + + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); + + if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) || + (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) || + (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf); + if(HwInfo->jChipType == SIS_550) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf); + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef); + } + } + } else { + if(HwInfo->jChipType == SIS_740) { + if(SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf); + } + } else if(SiS_IsVAMode(SiS_Pr,HwInfo)) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf); + } + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_IsDualEdge(SiS_Pr,HwInfo)) { + /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */ + } else { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb); + } + } + + SiS_UnLockCRT2(SiS_Pr,HwInfo); + + if(HwInfo->jChipType == SIS_550) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/ + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */ + } else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) || + (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) || + (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7); + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) { + if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) { + SiS_PanelDelay(SiS_Pr, HwInfo, 2); + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04); + } + } + } + +#endif /* SIS315H */ + + } /* 315 series */ + + } /* LVDS */ + +} + +/*********************************************/ +/* ENABLE VIDEO BRIDGE */ +/*********************************************/ + +/* NEVER use any variables (VBInfo), this will be called + * from outside the context of a mode switch! + * MUST call getVBType before calling this + */ +void +SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT temp=0,tempah; +#ifdef SIS315H + USHORT temp1,pushax=0; + BOOLEAN delaylong = FALSE; +#endif + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* ====== For 301B et al ====== */ + + if(HwInfo->jChipType < SIS_315H) { + +#ifdef SIS300 /* 300 series */ + + if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) { + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02); + } else if(SiS_Pr->SiS_VBType & VB_NoLCD) { + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00); + } + if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_NoLCD)) { + if(!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) { + SiS_PanelDelay(SiS_Pr, HwInfo, 0); + } + } + } + + if((SiS_Pr->SiS_VBType & VB_NoLCD) && + (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) { + + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* Enable CRT2 */ + SiS_DisplayOn(SiS_Pr); + SiS_UnLockCRT2(SiS_Pr,HwInfo); + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF); + if(SiS_BridgeInSlavemode(SiS_Pr)) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F); + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40); + } + if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) { + if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) { + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) { + SiS_PanelDelay(SiS_Pr, HwInfo, 1); + } + SiS_WaitVBRetrace(SiS_Pr,HwInfo); + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00); + } + } + + } else { + + temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */ + if(SiS_BridgeInSlavemode(SiS_Pr)) { + tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20; + } + SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp); + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */ + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0); + SiS_DisplayOn(SiS_Pr); + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) { + if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) { + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) { + SiS_PanelDelay(SiS_Pr, HwInfo, 1); + } + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01); + } + } + } + + } + + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* 315 series */ + +#ifdef SET_EMI + UCHAR r30=0, r31=0, r32=0, r33=0, cr36=0; + /* USHORT emidelay=0; */ +#endif + + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef); +#ifdef SET_EMI + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c); + } +#endif + } + + if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) { + if(HwInfo->jChipType < SIS_340) { + tempah = 0x10; + if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) { + if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18; + else tempah = 0x08; + } + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah); + } + } + + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + + SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00); + SiS_DisplayOff(SiS_Pr); + pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06); + if(IS_SIS740) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3); + } + + if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) { + if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) { + SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2); + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02); + SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2); + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) { + SiS_GenericDelay(SiS_Pr, 0x4500); + } + } + } + + if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) { + SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10); + delaylong = TRUE; + } + + } + + if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) { + + temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; + if(SiS_BridgeInSlavemode(SiS_Pr)) { + tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + if(!(tempah & SetCRT2ToRAMDAC)) { + if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20; + } + } + SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp); + + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */ + + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80); + + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + SiS_PanelDelay(SiS_Pr, HwInfo, 2); + } + + } else { + + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20); + + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80); + + tempah = 0xc0; + if(SiS_IsDualEdge(SiS_Pr, HwInfo)) { + tempah = 0x80; + if(!(SiS_IsVAMode(SiS_Pr, HwInfo))) tempah = 0x40; + } + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah); + + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + + SiS_PanelDelay(SiS_Pr, HwInfo, 2); + + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80); + + if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) { +#ifdef SET_EMI + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c); + SiS_GenericDelay(SiS_Pr, 0x500); + } +#endif + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c); + + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) { +#ifdef SET_EMI + cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36); + + if(SiS_Pr->SiS_ROMNew) { + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo); + if(romptr) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */ + SiS_Pr->EMI_30 = 0; + SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0]; + SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1]; + SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2]; + if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40; + /* emidelay = SISGETROMW((romptr + 0x22)); */ + SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = TRUE; + } + } + + /* (P4_30|0x40) */ + /* Compal 1400x1050: 0x05, 0x60, 0x00 YES (1.10.7w; CR36=69) */ + /* Compal 1400x1050: 0x0d, 0x70, 0x40 YES (1.10.7x; CR36=69) */ + /* Acer 1280x1024: 0x12, 0xd0, 0x6b NO (1.10.9k; CR36=73) */ + /* Compaq 1280x1024: 0x0d, 0x70, 0x6b YES (1.12.04b; CR36=03) */ + /* Clevo 1024x768: 0x05, 0x60, 0x33 NO (1.10.8e; CR36=12, DL!) */ + /* Clevo 1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES (1.10.8y; CR36=?2) */ + /* Clevo 1024x768: 0x05, 0x60, 0x33 (if type != 3) YES (1.10.8y; CR36=?2) */ + /* Asus 1024x768: ? ? (1.10.8o; CR36=?2) */ + /* Asus 1024x768: 0x08, 0x10, 0x3c (problematic) YES (1.10.8q; CR36=22) */ + + if(SiS_Pr->HaveEMI) { + r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31; + r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33; + } else { + r30 = 0; + } + + /* EMI_30 is read at driver start; however, the BIOS sets this + * (if it is used) only if the LCD is in use. In case we caught + * the machine while on TV output, this bit is not set and we + * don't know if it should be set - hence our detection is wrong. + * Work-around this here: + */ + + if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) { + switch((cr36 & 0x0f)) { + case 2: + r30 |= 0x40; + if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40; + if(!SiS_Pr->HaveEMI) { + r31 = 0x05; r32 = 0x60; r33 = 0x33; + if((cr36 & 0xf0) == 0x30) { + r31 = 0x0d; r32 = 0x70; r33 = 0x40; + } + } + break; + case 3: /* 1280x1024 */ + if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40; + if(!SiS_Pr->HaveEMI) { + r31 = 0x12; r32 = 0xd0; r33 = 0x6b; + if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) { + r31 = 0x0d; r32 = 0x70; r33 = 0x6b; + } + } + break; + case 9: /* 1400x1050 */ + r30 |= 0x40; + if(!SiS_Pr->HaveEMI) { + r31 = 0x05; r32 = 0x60; r33 = 0x00; + if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) { + r31 = 0x0d; r32 = 0x70; r33 = 0x40; /* BIOS values */ + } + } + break; + case 11: /* 1600x1200 - unknown */ + r30 |= 0x40; + if(!SiS_Pr->HaveEMI) { + r31 = 0x05; r32 = 0x60; r33 = 0x00; + } + } + } + + /* BIOS values don't work so well sometimes */ + if(!SiS_Pr->OverruleEMI) { +#ifdef COMPAL_HACK + if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) { + if((cr36 & 0x0f) == 0x09) { + r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00; + } + } +#endif +#ifdef COMPAQ_HACK + if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) { + if((cr36 & 0x0f) == 0x03) { + r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b; + } + } +#endif +#ifdef ASUS_HACK + if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) { + if((cr36 & 0x0f) == 0x02) { + /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 2 */ + /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 3 */ + /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 4 */ + /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 5 */ + } + } +#endif + } + + if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */ + SiS_GenericDelay(SiS_Pr, 0x500); + } + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33); +#endif /* SET_EMI */ + + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10); + +#ifdef SET_EMI + if( (SiS_LCDAEnabled(SiS_Pr, HwInfo)) || + (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) { + if(r30 & 0x40) { + SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5); + if(delaylong) { + SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5); + delaylong = FALSE; + } + SiS_WaitVBRetrace(SiS_Pr,HwInfo); + if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) { + SiS_GenericDelay(SiS_Pr, 0x500); + } + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40); /* Enable */ + } + } +#endif + } + } + + if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) { + if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) { + SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10); + if(delaylong) { + SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10); + } + SiS_WaitVBRetrace(SiS_Pr,HwInfo); + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) { + SiS_GenericDelay(SiS_Pr, 0x500); + } + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01); + } + } + + SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax); + SiS_DisplayOn(SiS_Pr); + SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff); + + } + + if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f); + } + +#endif /* SIS315H */ + + } + + } else { /* ============ For 301 ================ */ + + if(HwInfo->jChipType < SIS_315H) { + if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) { + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00); + SiS_PanelDelay(SiS_Pr, HwInfo, 0); + } + } + + temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */ + if(SiS_BridgeInSlavemode(SiS_Pr)) { + tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30); + if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20; + } + SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp); + + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */ + + if(HwInfo->jChipType >= SIS_315H) { + temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E); + if(!(temp & 0x80)) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80); /* BVBDOENABLE=1 */ + } + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */ + + SiS_VBLongWait(SiS_Pr); + SiS_DisplayOn(SiS_Pr); + if(HwInfo->jChipType >= SIS_315H) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f); + } + SiS_VBLongWait(SiS_Pr); + + if(HwInfo->jChipType < SIS_315H) { + if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) { + SiS_PanelDelay(SiS_Pr, HwInfo, 1); + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00); + } + } + + } + + } else { /* =================== For LVDS ================== */ + + if(HwInfo->jChipType < SIS_315H) { + +#ifdef SIS300 /* 300 series */ + + if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) { + if(HwInfo->jChipType == SIS_730) { + SiS_PanelDelay(SiS_Pr, HwInfo, 1); + SiS_PanelDelay(SiS_Pr, HwInfo, 1); + SiS_PanelDelay(SiS_Pr, HwInfo, 1); + } + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00); + if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) { + SiS_PanelDelay(SiS_Pr, HwInfo, 0); + } + } + + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); + SiS_DisplayOn(SiS_Pr); + SiS_UnLockCRT2(SiS_Pr,HwInfo); + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF); + if(SiS_BridgeInSlavemode(SiS_Pr)) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F); + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40); + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) { + if(!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) { + SiS_WaitVBRetrace(SiS_Pr, HwInfo); + SiS_SetCH700x(SiS_Pr,0x0B0E); + } + } + + if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) { + if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) { + if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) { + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) { + SiS_PanelDelay(SiS_Pr, HwInfo, 1); + SiS_PanelDelay(SiS_Pr, HwInfo, 1); + } + SiS_WaitVBRetrace(SiS_Pr, HwInfo); + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00); + } + } + } + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* 315 series */ + + if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) { + if(HwInfo->jChipType < SIS_340) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18); + } + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) { + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00); + SiS_PanelDelay(SiS_Pr, HwInfo, 0); + } + } + + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); + SiS_UnLockCRT2(SiS_Pr,HwInfo); + + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7); + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + temp = SiS_GetCH701x(SiS_Pr,0x66); + temp &= 0x20; + SiS_Chrontel701xBLOff(SiS_Pr); + } + + if(HwInfo->jChipType != SIS_550) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f); + } + + if(HwInfo->jChipType == SIS_740) { + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + if(SiS_IsLCDOrLCDA(SiS_Pr, HwInfo)) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20); + } + } + } + + temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E); + if(!(temp1 & 0x80)) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80); + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + if(temp) { + SiS_Chrontel701xBLOn(SiS_Pr, HwInfo); + } + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20); + if(HwInfo->jChipType == SIS_550) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10); + } + } + } else if(SiS_IsVAMode(SiS_Pr,HwInfo)) { + if(HwInfo->jChipType != SIS_740) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20); + } + } + + if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f); + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + if(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) { + SiS_Chrontel701xOn(SiS_Pr,HwInfo); + } + if( (SiS_IsVAMode(SiS_Pr,HwInfo)) || + (SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) ) { + SiS_ChrontelDoSomething1(SiS_Pr,HwInfo); + } + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) { + if( (SiS_IsVAMode(SiS_Pr,HwInfo)) || + (SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) ) { + SiS_Chrontel701xBLOn(SiS_Pr, HwInfo); + SiS_ChrontelInitTVVSync(SiS_Pr,HwInfo); + } + } + } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) { + if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) { + SiS_PanelDelay(SiS_Pr, HwInfo, 1); + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00); + } + } + } + +#endif /* SIS315H */ + + } /* 310 series */ + + } /* LVDS */ + +} + +/*********************************************/ +/* SET PART 1 REGISTER GROUP */ +/*********************************************/ + +/* Set CRT2 OFFSET / PITCH */ +static void +SiS_SetCRT2Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RRTI, PSIS_HW_INFO HwInfo) +{ + USHORT offset; + UCHAR temp; + + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return; + + offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI,HwInfo); + + if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) || + (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) { + offset >>= 1; + } + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF)); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8)); + temp = (UCHAR)(((offset >> 3) & 0xFF) + 1); + if(offset % 8) temp++; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp); +} + +/* Set CRT2 sync and PanelLink mode */ +static void +SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT RefreshRateTableIndex, + PSIS_HW_INFO HwInfo) +{ + USHORT tempah=0,tempbl,infoflag; + + tempbl = 0xC0; + + if(SiS_Pr->UseCustomMode) { + infoflag = SiS_Pr->CInfoFlag; + } else { + infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag; + } + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* LVDS */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + tempah = 0; + } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) { + tempah = SiS_Pr->SiS_LCDInfo; + } else tempah = infoflag >> 8; + tempah &= 0xC0; + tempah |= 0x20; + if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || + (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) { + tempah |= 0xf0; + } + if( (SiS_Pr->SiS_IF_DEF_FSTN) || + (SiS_Pr->SiS_IF_DEF_DSTN) || + (SiS_Pr->SiS_IF_DEF_TRUMPION) || + (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) { + tempah |= 0x30; + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(HwInfo->jChipType >= SIS_315H) { + tempah >>= 3; + tempah &= 0x18; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah); + /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */ + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0); + } + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah); + } + + } else if(SiS_Pr->SiS_VBType & VB_SISVB) { + + if(HwInfo->jChipType < SIS_315H) { + +#ifdef SIS300 /* ---- 300 series --- */ + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* 630 - 301B(-DH) */ + + tempah = infoflag >> 8; + tempbl = 0; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->SiS_LCDInfo & LCDSync) { + tempah = SiS_Pr->SiS_LCDInfo; + tempbl = (tempah >> 6) & 0x03; + } + } + tempah &= 0xC0; + tempah |= 0x20; + if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10; + tempah |= 0xc0; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah); + if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl); + } + + } else { /* 630 - 301 */ + + tempah = infoflag >> 8; + tempah &= 0xC0; + tempah |= 0x20; + if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah); + + } + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* ------- 315 series ------ */ + + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { /* 315 - LVDS */ + + tempbl = 0; + if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) && + (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) { + tempah = infoflag >> 8; + if(SiS_Pr->SiS_LCDInfo & LCDSync) { + tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6); + } + } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400) && + (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) { + tempah = infoflag >> 8; + tempbl = 0x03; + } else { + tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); + tempbl = (tempah >> 6) & 0x03; + tempbl |= 0x08; + if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04; + } + tempah &= 0xC0; + tempah |= 0x20; + if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) tempah |= 0xc0; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah); + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl); + } + } + + } else { /* 315 - TMDS */ + + tempah = tempbl = infoflag >> 8; + if(!SiS_Pr->UseCustomMode) { + tempbl = 0; + if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) { + if(ModeNo <= 0x13) { + tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)); + } + } + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { + if(SiS_Pr->SiS_LCDInfo & LCDSync) { + tempah = SiS_Pr->SiS_LCDInfo; + tempbl = (tempah >> 6) & 0x03; + } + } + } + } + tempah &= 0xC0; + tempah |= 0x20; + if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10; + if(SiS_Pr->SiS_VBType & VB_NoLCD) { + /* Imitate BIOS bug */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah |= 0xc0; + } + if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) { + tempah >>= 3; + tempah &= 0x18; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah); + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah); + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl); + } + } + } + + } +#endif /* SIS315H */ + } + } +} + +/* Set CRT2 FIFO on 300/630/730 */ +#ifdef SIS300 +static void +SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo, + PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT temp,index; + USHORT modeidindex,refreshratetableindex; + USHORT VCLK=0,MCLK,colorth=0,data2=0; + USHORT tempal, tempah, tempbx, tempcl, tempax; + USHORT CRT1ModeNo,CRT2ModeNo; + USHORT SelectRate_backup; + ULONG data,eax; + const UCHAR LatencyFactor[] = { + 97, 88, 86, 79, 77, 00, /*; 64 bit BQ=2 */ + 00, 87, 85, 78, 76, 54, /*; 64 bit BQ=1 */ + 97, 88, 86, 79, 77, 00, /*; 128 bit BQ=2 */ + 00, 79, 77, 70, 68, 48, /*; 128 bit BQ=1 */ + 80, 72, 69, 63, 61, 00, /*; 64 bit BQ=2 */ + 00, 70, 68, 61, 59, 37, /*; 64 bit BQ=1 */ + 86, 77, 75, 68, 66, 00, /*; 128 bit BQ=2 */ + 00, 68, 66, 59, 57, 37 /*; 128 bit BQ=1 */ + }; + const UCHAR LatencyFactor730[] = { + 69, 63, 61, + 86, 79, 77, + 103, 96, 94, + 120,113,111, + 137,130,128, /* <-- last entry, data below */ + 137,130,128, /* to avoid using illegal values */ + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + 137,130,128, + }; + const UCHAR ThLowB[] = { + 81, 4, 72, 6, 88, 8,120,12, + 55, 4, 54, 6, 66, 8, 90,12, + 42, 4, 45, 6, 55, 8, 75,12 + }; + const UCHAR ThTiming[] = { + 1, 2, 2, 3, 0, 1, 1, 2 + }; + + SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate; + + if(!SiS_Pr->CRT1UsesCustomMode) { + + CRT1ModeNo = SiS_Pr->SiS_CRT1Mode; /* get CRT1 ModeNo */ + SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex); + SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2); + SiS_Pr->SiS_SelectCRT2Rate = 0; + refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex, HwInfo); + + if(CRT1ModeNo >= 0x13) { + index = SiS_Pr->SiS_RefIndex[refreshratetableindex].Ext_CRTVCLK; + index &= 0x3F; + VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */ + + colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex); /* Get colordepth */ + colorth >>= 1; + if(!colorth) colorth++; + } + + } else { + + CRT1ModeNo = 0xfe; + VCLK = SiS_Pr->CSRClock_CRT1; /* Get VCLK */ + data2 = (SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2; + switch(data2) { /* Get color depth */ + case 0 : colorth = 1; break; + case 1 : colorth = 1; break; + case 2 : colorth = 2; break; + case 3 : colorth = 2; break; + case 4 : colorth = 3; break; + case 5 : colorth = 4; break; + default: colorth = 2; + } + + } + + if(CRT1ModeNo >= 0x13) { + if(HwInfo->jChipType == SIS_300) { + index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A); + } else { + index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A); + } + index &= 0x07; + MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */ + + data2 = (colorth * VCLK) / MCLK; + + temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14); + temp = ((temp & 0x00FF) >> 6) << 1; + if(temp == 0) temp = 1; + temp <<= 2; + temp &= 0xff; + + data2 = temp - data2; + + if((28 * 16) % data2) { + data2 = (28 * 16) / data2; + data2++; + } else { + data2 = (28 * 16) / data2; + } + + if(HwInfo->jChipType == SIS_300) { + + tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18); + tempah &= 0x62; + tempah >>= 1; + tempal = tempah; + tempah >>= 3; + tempal |= tempah; + tempal &= 0x07; + tempcl = ThTiming[tempal]; + tempbx = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16); + tempbx >>= 6; + tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14); + tempah >>= 4; + tempah &= 0x0c; + tempbx |= tempah; + tempbx <<= 1; + tempal = ThLowB[tempbx + 1]; + tempal *= tempcl; + tempal += ThLowB[tempbx]; + data = tempal; + + } else if(HwInfo->jChipType == SIS_730) { + +#ifdef LINUX_KERNEL + SiS_SetRegLong(0xcf8,0x80000050); + eax = SiS_GetRegLong(0xcfc); +#else + eax = pciReadLong(0x00000000, 0x50); +#endif + tempal = (USHORT)(eax >> 8); + tempal &= 0x06; + tempal <<= 5; + +#ifdef LINUX_KERNEL + SiS_SetRegLong(0xcf8,0x800000A0); + eax = SiS_GetRegLong(0xcfc); +#else + eax = pciReadLong(0x00000000, 0xA0); +#endif + temp = (USHORT)(eax >> 28); + temp &= 0x0F; + tempal |= temp; + + tempbx = tempal; /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */ + tempbx = 0; /* -- do it like the BIOS anyway... */ + tempax = tempbx; + tempbx &= 0xc0; + tempbx >>= 6; + tempax &= 0x0f; + tempax *= 3; + tempbx += tempax; + + data = LatencyFactor730[tempbx]; + data += 15; + temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14); + if(!(temp & 0x80)) data += 5; + + } else { + + index = 0; + temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14); + if(temp & 0x0080) index += 12; + +#ifdef LINUX_KERNEL + SiS_SetRegLong(0xcf8,0x800000A0); + eax = SiS_GetRegLong(0xcfc); +#else + /* We use pci functions X offers. We use tag 0, because + * we want to read/write to the host bridge (which is always + * 00:00.0 on 630, 730 and 540), not the VGA device. + */ + eax = pciReadLong(0x00000000, 0xA0); +#endif + temp = (USHORT)(eax >> 24); + if(!(temp&0x01)) index += 24; + +#ifdef LINUX_KERNEL + SiS_SetRegLong(0xcf8,0x80000050); + eax = SiS_GetRegLong(0xcfc); +#else + eax = pciReadLong(0x00000000, 0x50); +#endif + temp=(USHORT)(eax >> 24); + if(temp & 0x01) index += 6; + + temp = (temp & 0x0F) >> 1; + index += temp; + + data = LatencyFactor[index]; + data += 15; + temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14); + if(!(temp & 0x80)) data += 5; + } + + data += data2; /* CRT1 Request Period */ + + SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; + SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup; + + if(!SiS_Pr->UseCustomMode) { + + CRT2ModeNo = ModeNo; + SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex); + + refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex, HwInfo); + + index = SiS_GetVCLK2Ptr(SiS_Pr,CRT2ModeNo,modeidindex, + refreshratetableindex,HwInfo); + VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */ + + if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) { + if(SiS_Pr->SiS_UseROM) { + if(ROMAddr[0x220] & 0x01) { + VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8); + } + } + } + + } else { + + CRT2ModeNo = 0xfe; + VCLK = SiS_Pr->CSRClock; /* Get VCLK */ + + } + + colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex); /* Get colordepth */ + colorth >>= 1; + if(!colorth) colorth++; + + data = data * VCLK * colorth; + if(data % (MCLK << 4)) { + data = data / (MCLK << 4); + data++; + } else { + data = data / (MCLK << 4); + } + + if(data <= 6) data = 6; + if(data > 0x14) data = 0x14; + + temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x01); + if(HwInfo->jChipType == SIS_300) { + if(data <= 0x0f) temp = (temp & (~0x1F)) | 0x13; + else temp = (temp & (~0x1F)) | 0x16; + if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) { + temp = (temp & (~0x1F)) | 0x13; + } + } else { + if( ( (HwInfo->jChipType == SIS_630) || + (HwInfo->jChipType == SIS_730) ) && + (HwInfo->jChipRevision >= 0x30) ) /* 630s or 730(s?) */ + { + temp = (temp & (~0x1F)) | 0x1b; + } else { + temp = (temp & (~0x1F)) | 0x16; + } + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp); + + if( (HwInfo->jChipType == SIS_630) && + (HwInfo->jChipRevision >= 0x30) ) /* 630s, NOT 730 */ + { + if(data > 0x13) data = 0x13; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data); + + } else { /* If mode <= 0x13, we just restore everything */ + + SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; + SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup; + + } +} +#endif + +/* Set CRT2 FIFO on 315/330 series */ +#ifdef SIS315H +static void +SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B); + if( (HwInfo->jChipType == SIS_760) && + (SiS_Pr->SiS_SysFlags & SF_760LFB) && + (SiS_Pr->SiS_ModeType == Mode32Bpp) && + (SiS_Pr->SiS_VGAHDE >= 1280) && + (SiS_Pr->SiS_VGAVDE >= 1024) ) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e); + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04); + } + +} +#endif + +static USHORT +SiS_GetVGAHT2(SiS_Private *SiS_Pr) +{ + ULONG tempax,tempbx; + + tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX; + tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT; + tempax = (tempax * SiS_Pr->SiS_HT) / tempbx; + return((USHORT)tempax); +} + +/* Set Part 1 / SiS bridge slave mode */ +static void +SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo,USHORT RefreshRateTableIndex) +{ + USHORT push1,push2; + USHORT tempax,tempbx,tempcx,temp; + USHORT resinfo,modeflag,xres=0; + unsigned char p1_7, p1_8; + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; + } else if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + resinfo = 0; + xres = SiS_Pr->CHDisplay; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes; + } + + /* The following is only done if bridge is in slave mode: */ + + if((HwInfo->jChipType >= SIS_661) && (ModeNo > 0x13)) { + if(xres >= 1600) { + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04); + } + } + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0xff); /* set MAX HT */ + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) modeflag |= Charx8Dot; + + if(modeflag & Charx8Dot) tempcx = 0x08; + else tempcx = 0x09; + + tempax = SiS_Pr->SiS_VGAHDE; /* 0x04 Horizontal Display End */ + if(modeflag & HalfDCLK) tempax >>= 1; + tempax = ((tempax / tempcx) - 1) & 0xff; + tempbx = tempax; + + temp = tempax; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,temp); + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) { + temp += 2; + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + if(resinfo == SIS_RI_800x600) temp -= 2; + } + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x05,temp); /* 0x05 Horizontal Display Start */ + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x06,0x03); /* 0x06 Horizontal Blank end */ + + tempax = 0xFFFF; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempax = SiS_GetVGAHT2(SiS_Pr); + if(tempax >= SiS_Pr->SiS_VGAHT) tempax = SiS_Pr->SiS_VGAHT; + if(modeflag & HalfDCLK) tempax >>= 1; + tempax = (tempax / tempcx) - 5; + tempcx = tempax; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + temp = tempcx - 1; + if(!(modeflag & HalfDCLK)) { + temp -= 6; + if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) { + temp -= 2; + if(ModeNo > 0x13) temp -= 10; + } + } + } else { + tempcx = (tempcx + tempbx) >> 1; + temp = (tempcx & 0x00FF) + 2; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + temp--; + if(!(modeflag & HalfDCLK)) { + if((modeflag & Charx8Dot)) { + temp += 4; + if(SiS_Pr->SiS_VGAHDE >= 800) temp -= 6; + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VGAHDE == 800) temp += 2; + } + } + } + } else { + if(!(modeflag & HalfDCLK)) { + temp -= 4; + if((SiS_Pr->SiS_LCDResInfo != Panel_1280x960) && + (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)) { + if(SiS_Pr->SiS_VGAHDE >= 800) { + temp -= 7; + if(HwInfo->jChipType < SIS_315H) { + if(SiS_Pr->SiS_ModeType == ModeEGA) { + if(SiS_Pr->SiS_VGAVDE == 1024) { + temp += 15; + if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) + temp += 7; + } + } + } + if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) { + if(SiS_Pr->SiS_VGAHDE >= 1280) { + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) temp += 28; + } + } + } + } + } + } + } + + p1_7 = temp; + p1_8 = 0x00; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) { + if(ModeNo <= 0x01) { + p1_7 = 0x2a; + if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) p1_8 = 0x61; + else p1_8 = 0x41; + } else if(SiS_Pr->SiS_ModeType == ModeText) { + if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) p1_7 = 0x54; + else p1_7 = 0x55; + p1_8 = 0x00; + } else if(ModeNo <= 0x13) { + if(modeflag & HalfDCLK) { + if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { + p1_7 = 0x30; + p1_8 = 0x03; + } else { + p1_7 = 0x2f; + p1_8 = 0x02; + } + } else { + p1_7 = 0x5b; + p1_8 = 0x03; + } + } else if( ((HwInfo->jChipType >= SIS_315H) && + ((ModeNo == 0x50) || (ModeNo == 0x56) || (ModeNo == 0x53))) || + ((HwInfo->jChipType < SIS_315H) && + (resinfo == SIS_RI_320x200 || resinfo == SIS_RI_320x240)) ) { + if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { + p1_7 = 0x30, + p1_8 = 0x03; + } else { + p1_7 = 0x2f; + p1_8 = 0x03; + } + } + } + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { + if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p)) { + p1_7 = 0x63; + if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) p1_7 = 0x55; + } + if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) { + if(!(modeflag & HalfDCLK)) { + p1_7 = 0xb2; + if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) { + p1_7 = 0xab; + } + } + } else { + if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) { + if(modeflag & HalfDCLK) p1_7 = 0x30; + } + } + } + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,p1_7); /* 0x07 Horizontal Retrace Start */ + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,p1_8); /* 0x08 Horizontal Retrace End */ + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x03); /* 0x18 SR08 (FIFO Threshold?) */ + + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x19,0xF0); + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,0xFF); /* 0x09 Set Max VT */ + + tempcx = 0x121; + tempbx = SiS_Pr->SiS_VGAVDE; /* 0x0E Vertical Display End */ + if (tempbx == 357) tempbx = 350; + else if(tempbx == 360) tempbx = 350; + else if(tempbx == 375) tempbx = 350; + else if(tempbx == 405) tempbx = 400; + else if(tempbx == 420) tempbx = 400; + else if(tempbx == 525) tempbx = 480; + push2 = tempbx; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) { + if (tempbx == 350) tempbx += 5; + else if(tempbx == 480) tempbx += 5; + } + } + } + tempbx -= 2; + temp = tempbx & 0x00FF; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp); /* 0x10 vertical Blank Start */ + + tempbx = push2; + tempbx--; + temp = tempbx & 0x00FF; +#if 0 + /* Missing code from 630/301B 2.04.5a and 650/302LV 1.10.6s (calles int 2f) */ + if(xxx()) { + if(temp == 0xdf) temp = 0xda; + } +#endif + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp); + + temp = 0; + if(modeflag & DoubleScanMode) temp |= 0x80; + if(HwInfo->jChipType >= SIS_661) { + if(tempbx & 0x0200) temp |= 0x20; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x0B,0x5F,temp); + if(tempbx & 0x0100) tempcx |= 0x000a; + if(tempbx & 0x0400) tempcx |= 0x1200; + } else { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp); + if(tempbx & 0x0100) tempcx |= 0x0002; + if(tempbx & 0x0400) tempcx |= 0x0600; + } + + if(tempbx & 0x0200) tempcx |= 0x0040; + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,0x00); /* 0x11 Vertical Blank End */ + + tempax = (SiS_Pr->SiS_VGAVT - tempbx) >> 2; + + if((ModeNo > 0x13) || (HwInfo->jChipType < SIS_315H)) { + if(resinfo != SIS_RI_1280x1024) { + tempbx += (tempax << 1); + } + } else if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) { + tempbx += (tempax << 1); + } + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + tempbx -= 10; + } else { + if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) { + if(SiS_Pr->SiS_TVMode & TVSetPAL) { + tempbx += 40; + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VGAHDE == 800) tempbx += 10; + } + } + } + } + tempax >>= 2; + tempax++; + tempax += tempbx; + push1 = tempax; + if(SiS_Pr->SiS_TVMode & TVSetPAL) { + if(tempbx <= 513) { + if(tempax >= 513) tempbx = 513; + } + } + temp = tempbx & 0x00FF; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp); /* 0x0C Vertical Retrace Start */ + + tempbx--; + temp = tempbx & 0x00FF; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp); + + if(tempbx & 0x0100) tempcx |= 0x0008; + + if(tempbx & 0x0200) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x0B,0x20); + } + tempbx++; + + if(tempbx & 0x0100) tempcx |= 0x0004; + if(tempbx & 0x0200) tempcx |= 0x0080; + if(tempbx & 0x0400) { + if(HwInfo->jChipType >= SIS_661) tempcx |= 0x0800; + else if(SiS_Pr->SiS_VBType & VB_SIS301) tempcx |= 0x0800; + else tempcx |= 0x0C00; + } + + tempbx = push1; + temp = tempbx & 0x000F; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,temp); /* 0x0D vertical Retrace End */ + + if(tempbx & 0x0010) tempcx |= 0x2000; + + temp = tempcx & 0x00FF; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp); /* 0x0A CR07 */ + + temp = (tempcx & 0xFF00) >> 8; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp); /* 0x17 SR0A */ + + tempax = modeflag; + temp = (tempax & 0xFF00) >> 8; + temp = (temp >> 1) & 0x09; + if(!(SiS_Pr->SiS_VBType & VB_SIS301)) temp |= 0x01; /* Always 8 dotclock */ + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* 0x16 SR01 */ + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00); /* 0x0F CR14 */ + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00); /* 0x12 CR17 */ + + temp = 0x00; + if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) { + if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) { + temp = 0x80; + } + } + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* 0x1A SR0E */ + + temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp); +} + +/* Setup panel link + * This is used for LVDS, LCDA and Chrontel TV output + * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA + */ +static void +SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex) +{ + USHORT modeflag,resinfo; + USHORT push2,tempax,tempbx,tempcx,temp; + ULONG tempeax=0,tempebx,tempecx,tempvcfact=0; + BOOLEAN islvds = FALSE, issis = FALSE, chkdclkfirst = FALSE; +#ifdef SIS300 + USHORT crt2crtc; +#endif +#ifdef SIS315H + USHORT pushcx; +#endif + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; +#ifdef SIS300 + crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; +#endif + } else if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + resinfo = 0; +#ifdef SIS300 + crt2crtc = 0; +#endif + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; +#ifdef SIS300 + crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; +#endif + } + + /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */ + if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) { + islvds = TRUE; + } + + /* is really sis if sis bridge, but not 301B-DH */ + if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) { + issis = TRUE; + } + + if((HwInfo->jChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) { + if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) { + chkdclkfirst = TRUE; + } + } + +#ifdef SIS315H + if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + if(IS_SIS330) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10); + } else if(IS_SIS740) { + if(islvds) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03); + } else if(SiS_Pr->SiS_VBType & VB_SISVB) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10); + } + } else { + if(islvds) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00); + } else if(SiS_Pr->SiS_VBType & VB_SISVB) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f); + if(SiS_Pr->SiS_VBType & VB_SIS301C) { + if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) || + (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20); + } + } + } + } + } +#endif + + /* Horizontal */ + + tempax = SiS_Pr->SiS_LCDHDES; + if(islvds) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) { + if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) && + (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) { + tempax -= 8; + } + } + } + } + + temp = (tempax & 0x0007); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* BPLHDESKEW[2:0] */ + temp = (tempax >> 3) & 0x00FF; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* BPLHDESKEW[10:3] */ + + tempbx = SiS_Pr->SiS_HDE; + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) || + (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) { + tempbx >>= 1; + } + if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { + tempbx = SiS_Pr->PanelXRes; + } + } + + tempax += tempbx; + if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT; + + temp = tempax; + if(temp & 0x07) temp += 8; + temp >>= 3; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp); /* BPLHDEE */ + + tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2; + + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { + if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS; + } + } + + tempcx += tempax; + if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT; + + temp = (tempcx >> 3) & 0x00FF; + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(SiS_Pr->SiS_IF_DEF_TRUMPION) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + switch(ModeNo) { + case 0x04: + case 0x05: + case 0x0d: temp = 0x56; break; + case 0x10: temp = 0x60; break; + case 0x13: temp = 0x5f; break; + case 0x40: + case 0x41: + case 0x4f: + case 0x43: + case 0x44: + case 0x62: + case 0x56: + case 0x53: + case 0x5d: + case 0x5e: temp = 0x54; break; + } + } + } + } + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp); /* BPLHRS */ + + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + temp += 2; + if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { + temp += 8; + if(SiS_Pr->PanelHRE != 999) { + temp = tempcx + SiS_Pr->PanelHRE; + if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT; + temp >>= 3; + } + } + } else { + temp += 10; + } + + temp &= 0x1F; + temp |= ((tempcx & 0x07) << 5); +#if 0 + if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20; /* WRONG? BIOS loads cl, not ah */ +#endif + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp); /* BPLHRE */ + + /* Vertical */ + + tempax = SiS_Pr->SiS_VGAVDE; + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { + tempax = SiS_Pr->PanelYRes; + } + } + + tempbx = SiS_Pr->SiS_LCDVDES + tempax; + if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT; + + push2 = tempbx; + + tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE; + if(HwInfo->jChipType < SIS_315H) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { + tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes; + } + } + } + if(islvds) tempcx >>= 1; + else tempcx >>= 2; + + if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) && + (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) && + (SiS_Pr->PanelVRS != 999) ) { + tempcx = SiS_Pr->PanelVRS; + tempbx += tempcx; + if(issis) tempbx++; + } else { + tempbx += tempcx; + if(HwInfo->jChipType < SIS_315H) tempbx++; + else if(issis) tempbx++; + } + + if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT; /* BPLVRS */ + + temp = tempbx & 0x00FF; + if(SiS_Pr->SiS_IF_DEF_TRUMPION) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + if(ModeNo == 0x10) temp = 0xa9; + } + } + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp); + + tempcx >>= 3; + tempcx++; + + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { + if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE; + } + } + + tempcx += tempbx; + temp = tempcx & 0x000F; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp); /* BPLVRE */ + + temp = ((tempbx >> 8) & 0x07) << 3; + if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) { + if(SiS_Pr->SiS_HDE != 640) { + if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40; + } + } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40; + if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) temp |= 0x40; + tempbx = 0x87; + if((HwInfo->jChipType >= SIS_315H) || + (HwInfo->jChipRevision >= 0x30)) { + tempbx = 0x07; + if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) { + if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03) temp |= 0x80; + } + /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit mutliplexed) via VGA2 */ + if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10) temp |= 0x80; + } else { + if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80; + } + } + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp); + + tempbx = push2; /* BPLVDEE */ + + tempcx = SiS_Pr->SiS_LCDVDES; /* BPLVDES */ + + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + switch(SiS_Pr->SiS_LCDResInfo) { + case Panel_640x480: + tempbx = SiS_Pr->SiS_VGAVDE - 1; + tempcx = SiS_Pr->SiS_VGAVDE; + break; + case Panel_800x600: + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if(resinfo == SIS_RI_800x600) tempcx++; + } + break; + case Panel_1024x600: + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if(resinfo == SIS_RI_1024x600) tempcx++; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + if(resinfo == SIS_RI_800x600) tempcx++; + } + } + break; + case Panel_1024x768: + if(HwInfo->jChipType < SIS_315H) { + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if(resinfo == SIS_RI_1024x768) tempcx++; + } + } + break; + } + } + + temp = ((tempbx >> 8) & 0x07) << 3; + temp = temp | ((tempcx >> 8) & 0x07); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp); + /* if(SiS_Pr->SiS_IF_DEF_FSTN) tempbx++; */ + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx); + + /* Vertical scaling */ + + if(HwInfo->jChipType < SIS_315H) { + +#ifdef SIS300 /* 300 series */ + tempeax = SiS_Pr->SiS_VGAVDE << 6; + temp = (tempeax % (ULONG)SiS_Pr->SiS_VDE); + tempeax = tempeax / (ULONG)SiS_Pr->SiS_VDE; + if(temp) tempeax++; + + if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F; + + temp = (USHORT)(tempeax & 0x00FF); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp); /* BPLVCFACT */ + tempvcfact = temp; +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* 315 series */ + tempeax = SiS_Pr->SiS_VGAVDE << 18; + tempebx = SiS_Pr->SiS_VDE; + temp = (tempeax % tempebx); + tempeax = tempeax / tempebx; + if(temp) tempeax++; + tempvcfact = tempeax; + + temp = (USHORT)(tempeax & 0x00FF); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp); + temp = (USHORT)((tempeax & 0x00FF00) >> 8); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp); + temp = (USHORT)((tempeax & 0x00030000) >> 16); + if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp); + + if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) { + temp = (USHORT)(tempeax & 0x00FF); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp); + temp = (USHORT)((tempeax & 0x00FF00) >> 8); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp); + temp = (USHORT)(((tempeax & 0x00030000) >> 16) << 6); + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp); + temp = 0; + if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08; + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp); + } +#endif + + } + + /* Horizontal scaling */ + + tempeax = SiS_Pr->SiS_VGAHDE; /* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/ + if(chkdclkfirst) { + if(modeflag & HalfDCLK) tempeax >>= 1; + } + tempebx = tempeax << 16; + if(SiS_Pr->SiS_HDE == tempeax) { + tempecx = 0xFFFF; + } else { + tempecx = tempebx / SiS_Pr->SiS_HDE; + if(HwInfo->jChipType >= SIS_315H) { + if(tempebx % SiS_Pr->SiS_HDE) tempecx++; + } + } + + if(HwInfo->jChipType >= SIS_315H) { + tempeax = (tempebx / tempecx) - 1; + } else { + tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1; + } + tempecx = (tempecx << 16) | (tempeax & 0xFFFF); + temp = (USHORT)(tempecx & 0x00FF); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp); + + if(HwInfo->jChipType >= SIS_315H) { + tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact; + tempbx = (USHORT)(tempeax & 0xFFFF); + } else { + tempeax = SiS_Pr->SiS_VGAVDE << 6; + tempbx = tempvcfact & 0x3f; + if(tempbx == 0) tempbx = 64; + tempeax /= tempbx; + tempbx = (USHORT)(tempeax & 0xFFFF); + } + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--; + if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) { + if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1; + else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) tempbx = 1; + } + + temp = ((tempbx >> 8) & 0x07) << 3; + temp = temp | ((tempecx >> 8) & 0x07); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx); + + tempecx >>= 16; /* BPLHCFACT */ + if(!chkdclkfirst) { + if(modeflag & HalfDCLK) tempecx >>= 1; + } + temp = (USHORT)((tempecx & 0xFF00) >> 8); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp); + temp = (USHORT)(tempecx & 0x00FF); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp); + +#ifdef SIS315H + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SIS301LV302LV)) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20); + } + } else { + if(islvds) { + if(HwInfo->jChipType == SIS_740) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03); + } else { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23); + } + } + } + } +#endif + +#ifdef SIS300 + if(SiS_Pr->SiS_IF_DEF_TRUMPION) { + int i; + UCHAR TrumpMode13[4] = { 0x01, 0x10, 0x2c, 0x00 }; + UCHAR TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 }; + UCHAR TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 }; + + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf); + for(i=0; i<5; i++) { + SiS_SetTrumpionBlock(SiS_Pr, &SiS300_TrumpionData[crt2crtc][0]); + } + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + if(ModeNo == 0x13) { + for(i=0; i<4; i++) { + SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]); + } + } else if(ModeNo == 0x10) { + for(i=0; i<4; i++) { + SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]); + SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]); + } + } + } + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); + } +#endif + +#ifdef SIS315H + if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x27,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03); + tempax = SiS_Pr->SiS_HDE; /* Blps = lcdhdee(lcdhdes+HDE) + 64 */ + if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 || + SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1; + tempax += 64; + temp = tempax & 0x00FF; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,temp); + temp = ((tempax & 0xFF00) >> 8) << 3; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp); + tempax += 32; /* Blpe=lBlps+32 */ + temp = tempax & 0x00FF; + if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,temp); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00); /* Bflml=0 */ + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x007,0x00); + + tempax = SiS_Pr->SiS_VDE; + if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 || + SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1; + tempax >>= 1; + temp = tempax & 0x00FF; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,temp); + temp = ((tempax & 0xFF00) >> 8) << 3; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp); + + tempeax = SiS_Pr->SiS_HDE; + if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 || + SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempeax >>= 1; + tempeax <<= 2; /* BDxFIFOSTOP = (HDE*4)/128 */ + tempebx = 128; + temp = (USHORT)(tempeax % tempebx); + tempeax = tempeax / tempebx; + if(temp) tempeax++; + temp = (USHORT)(tempeax & 0x003F); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x45,~0x0FF,temp); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00); /* BDxWadrst0 */ + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x040,0x00); + + tempax = SiS_Pr->SiS_HDE; + if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 || + SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1; + tempax >>= 4; /* BDxWadroff = HDE*4/8/8 */ + pushcx = tempax; + temp = tempax & 0x00FF; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp); + temp = ((tempax & 0xFF00) >> 8) << 3; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp); + + tempax = SiS_Pr->SiS_VDE; /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */ + if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 || + SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1; + tempeax = (tempax * pushcx); + tempebx = 0x00100000 + tempeax; + temp = (USHORT)tempebx & 0x000000FF; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp); + temp = (USHORT)((tempebx & 0x0000FF00) >> 8); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp); + temp = (USHORT)((tempebx & 0x00FF0000) >> 16); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp); + temp = (USHORT)(((tempebx & 0x01000000) >> 24) << 7); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp); + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x01); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0x38); + + if(SiS_Pr->SiS_IF_DEF_FSTN) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2b,0x02); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2c,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,0x0c); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,0x80); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,0xA0); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3a,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3b,0xf0); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3c,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3d,0x10); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3e,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3f,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,0x10); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,0x25); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,0x80); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,0x14); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x44,0x03); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a); + } + } +#endif /* SIS315H */ +} + +/* Set Part 1 */ +static void +SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex) +{ +#if defined(SIS300) || defined(SIS315H) + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; +#endif + USHORT temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0; + USHORT pushbx=0, CRT1Index=0, modeflag, resinfo=0; +#ifdef SIS315H + USHORT tempbl=0; +#endif + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex); + return; + } + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } else if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + } else { + CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } + + SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + + if( ! ((HwInfo->jChipType >= SIS_315H) && + (SiS_Pr->SiS_IF_DEF_LVDS == 1) && + (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) { + + if(HwInfo->jChipType < SIS_315H ) { +#ifdef SIS300 + SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo, HwInfo); +#endif + } else { +#ifdef SIS315H + SiS_SetCRT2FIFO_310(SiS_Pr, HwInfo); +#endif + } + + /* 1. Horizontal setup */ + + if(HwInfo->jChipType < SIS_315H ) { + +#ifdef SIS300 /* ------------- 300 series --------------*/ + + temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */ + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */ + + temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp); /* CRT2 Horizontal Total Overflow [7:4] */ + + temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */ + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp); /* CRT2 Horizontal Display Enable End */ + + pushbx = SiS_Pr->SiS_VGAHDE + 12; /* bx BTVGA2HRS 0x0B,0x0C */ + tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2; + tempbx = pushbx + tempcx; + tempcx <<= 1; + tempcx += tempbx; + + bridgeadd = 12; + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* ------------------- 315/330 series --------------- */ + + tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HT 0x08,0x09 */ + if(modeflag & HalfDCLK) { + if(SiS_Pr->SiS_VBType & VB_SISVB) { + tempcx >>= 1; + } else { + tempax = SiS_Pr->SiS_VGAHDE >> 1; + tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + tempcx = SiS_Pr->SiS_HT - tempax; + } + } + } + tempcx--; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx); /* CRT2 Horizontal Total */ + temp = (tempcx >> 4) & 0xF0; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp); /* CRT2 Horizontal Total Overflow [7:4] */ + + tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HDEE 0x0A,0x0C */ + tempbx = SiS_Pr->SiS_VGAHDE; + tempcx -= tempbx; + tempcx >>= 2; + if(modeflag & HalfDCLK) { + tempbx >>= 1; + tempcx >>= 1; + } + tempbx += 16; + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx); /* CRT2 Horizontal Display Enable End */ + + pushbx = tempbx; + tempcx >>= 1; + tempbx += tempcx; + tempcx += tempbx; + + bridgeadd = 16; + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + if(HwInfo->jChipType >= SIS_661) { + if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) || + (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) { + if(resinfo == SIS_RI_1280x1024) { + tempcx = (tempcx & 0xff00) | 0x30; + } else if(resinfo == SIS_RI_1600x1200) { + tempcx = (tempcx & 0xff00) | 0xff; + } + } + } + } + +#endif /* SIS315H */ + + } /* 315/330 series */ + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + + if(SiS_Pr->UseCustomMode) { + tempbx = SiS_Pr->CHSyncStart + bridgeadd; + tempcx = SiS_Pr->CHSyncEnd + bridgeadd; + tempax = SiS_Pr->SiS_VGAHT; + if(modeflag & HalfDCLK) tempax >>= 1; + tempax--; + if(tempcx > tempax) tempcx = tempax; + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { + unsigned char cr4, cr14, cr5, cr15; + if(SiS_Pr->UseCustomMode) { + cr4 = SiS_Pr->CCRT1CRTC[4]; + cr14 = SiS_Pr->CCRT1CRTC[14]; + cr5 = SiS_Pr->CCRT1CRTC[5]; + cr15 = SiS_Pr->CCRT1CRTC[15]; + } else { + cr4 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4]; + cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14]; + cr5 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5]; + cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15]; + } + tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; /* (VGAHRS-3)*8 */ + tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; /* (VGAHRE-3)*8 */ + tempcx &= 0x00FF; + tempcx |= (tempbx & 0xFF00); + tempbx += bridgeadd; + tempcx += bridgeadd; + tempax = SiS_Pr->SiS_VGAHT; + if(modeflag & HalfDCLK) tempax >>= 1; + tempax--; + if(tempcx > tempax) tempcx = tempax; + } + + if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) { + tempbx = 1040; + tempcx = 1044; /* HWCursor bug! */ + } + + } + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx); /* CRT2 Horizontal Retrace Start */ + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx); /* CRT2 Horizontal Retrace End */ + + temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp); /* Overflow */ + + /* 2. Vertical setup */ + + tempcx = SiS_Pr->SiS_VGAVT - 1; + temp = tempcx & 0x00FF; + + if(HwInfo->jChipType < SIS_661) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(HwInfo->jChipType < SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) { + temp--; + } + } + } else { + temp--; + } + } else if(HwInfo->jChipType >= SIS_315H) { + temp--; + } + } + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp); /* CRT2 Vertical Total */ + + tempbx = SiS_Pr->SiS_VGAVDE - 1; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx); /* CRT2 Vertical Display Enable End */ + + temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp); /* Overflow */ + + if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) { + tempbx++; + tempax = tempbx; + tempcx++; + tempcx -= tempax; + tempcx >>= 2; + tempbx += tempcx; + if(tempcx < 4) tempcx = 4; + tempcx >>= 2; + tempcx += tempbx; + tempcx++; + } else { + tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */ + tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */ + } + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + if(SiS_Pr->UseCustomMode) { + tempbx = SiS_Pr->CVSyncStart; + tempcx = SiS_Pr->CVSyncEnd; + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { + unsigned char cr8, cr7, cr13; + if(SiS_Pr->UseCustomMode) { + cr8 = SiS_Pr->CCRT1CRTC[8]; + cr7 = SiS_Pr->CCRT1CRTC[7]; + cr13 = SiS_Pr->CCRT1CRTC[13]; + tempcx = SiS_Pr->CCRT1CRTC[9]; + } else { + cr8 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8]; + cr7 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7]; + cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13]; + tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9]; + } + tempbx = cr8; + if(cr7 & 0x04) tempbx |= 0x0100; + if(cr7 & 0x80) tempbx |= 0x0200; + if(cr13 & 0x08) tempbx |= 0x0400; + } + } + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx); /* CRT2 Vertical Retrace Start */ + + temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp); /* CRT2 Vert. Retrace End; Overflow */ + + /* 3. Panel delay compensation */ + + if(HwInfo->jChipType < SIS_315H) { + +#ifdef SIS300 /* ---------- 300 series -------------- */ + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + temp = 0x20; + if(HwInfo->jChipType == SIS_300) { + temp = 0x10; + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) temp = 0x2c; + if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20; + } + if(SiS_Pr->SiS_VBType & VB_SIS301) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20; + } + if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) temp = 0x24; + if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) temp = 0x2c; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x08; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) temp = 0x2c; + else temp = 0x20; + } + if(SiS_Pr->SiS_UseROM) { + if(ROMAddr[0x220] & 0x80) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) + temp = ROMAddr[0x221]; + else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) + temp = ROMAddr[0x222]; + else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) + temp = ROMAddr[0x223]; + else + temp = ROMAddr[0x224]; + temp &= 0x3c; + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC & 0x3c; + } + + } else { + temp = 0x20; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) { + if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04; + } + if(SiS_Pr->SiS_UseROM) { + if(ROMAddr[0x220] & 0x80) { + temp = ROMAddr[0x220] & 0x3c; + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC & 0x3c; + } + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */ + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* --------------- 315/330 series ---------------*/ + + if(HwInfo->jChipType < SIS_661) { + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + + if(HwInfo->jChipType == SIS_740) temp = 0x03; + else temp = 0x00; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a; + tempbl = 0xF0; + if(HwInfo->jChipType == SIS_650) { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F; + } + } + + if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) { + temp = 0x08; + tempbl = 0; + if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) { + if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0; + } + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp); /* Panel Link Delay Compensation */ + } + + } /* < 661 */ + + tempax = 0; + if(modeflag & DoubleScanMode) tempax |= 0x80; + if(modeflag & HalfDCLK) tempax |= 0x40; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax); + +#endif /* SIS315H */ + + } + + } /* Slavemode */ + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) { + /* For 301BDH with LCD, we set up the Panel Link */ + SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex); + } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex); + } + } else { + if(HwInfo->jChipType < SIS_315H) { + SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex); + } else { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex); + } + } else { + SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex); + } + } + } +} + +/*********************************************/ +/* SET PART 2 REGISTER GROUP */ +/*********************************************/ + +#ifdef SIS315H +static UCHAR * +SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr, int tabletype, PSIS_HW_INFO HwInfo) +{ + const UCHAR *tableptr = NULL; + USHORT a, b, p = 0; + + a = SiS_Pr->SiS_VGAHDE; + b = SiS_Pr->SiS_HDE; + if(tabletype) { + a = SiS_Pr->SiS_VGAVDE; + b = SiS_Pr->SiS_VDE; + } + + if(a < b) { + tableptr = SiS_Part2CLVX_1; + } else if(a == b) { + tableptr = SiS_Part2CLVX_2; + } else { + if(SiS_Pr->SiS_TVMode & TVSetPAL) { + tableptr = SiS_Part2CLVX_4; + } else { + tableptr = SiS_Part2CLVX_3; + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { + if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) tableptr = SiS_Part2CLVX_3; + else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tableptr = SiS_Part2CLVX_3; + else tableptr = SiS_Part2CLVX_5; + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + tableptr = SiS_Part2CLVX_6; + } + do { + if((tableptr[p] | tableptr[p+1] << 8) == a) break; + p += 0x42; + } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff); + if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42; + } + p += 2; + return((UCHAR *)&tableptr[p]); +} + +static void +SiS_SetGroup2_C_ELV(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo) +{ + UCHAR *tableptr; + int i, j; + UCHAR temp; + + if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return; + + tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0, HwInfo); + for(i = 0x80, j = 0; i <= 0xbf; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]); + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1, HwInfo); + for(i = 0xc0, j = 0; i <= 0xff; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]); + } + } + temp = 0x10; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp |= 0x04; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp); +} + +static BOOLEAN +SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *CRT2Index, + USHORT *ResIndex,PSIS_HW_INFO HwInfo) +{ + + if(HwInfo->jChipType < SIS_315H) return FALSE; + + if(ModeNo <= 0x13) + (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + else + (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + + (*ResIndex) &= 0x3f; + (*CRT2Index) = 0; + + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) { + (*CRT2Index) = 200; + } + } + + if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206; + } + } + return(((*CRT2Index) != 0)); +} +#endif + +#ifdef SIS300 +static void +SiS_Group2LCDSpecial(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT crt2crtc) +{ + USHORT tempcx; + const UCHAR atable[] = { + 0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02, + 0xab,0x87,0xab,0x9e,0xe7,0x02,0x02 + }; + + if(!SiS_Pr->UseCustomMode) { + if( ( ( (HwInfo->jChipType == SIS_630) || + (HwInfo->jChipType == SIS_730) ) && + (HwInfo->jChipRevision > 2) ) && + (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) && + (!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) && + (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) { + if(ModeNo == 0x13) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6); + } else { + if((crt2crtc & 0x3F) == 4) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2); + } + } + } + + if(HwInfo->jChipType < SIS_315H) { + if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) { + crt2crtc &= 0x1f; + tempcx = 0; + if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + tempcx += 7; + } + } + tempcx += crt2crtc; + if(crt2crtc >= 4) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff); + } + + if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(crt2crtc == 4) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28); + } + } + } + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]); + } + } + } +} + +/* For ECS A907. Highly preliminary. */ +static void +SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeIdIndex, USHORT RefreshRateTableIndex, + USHORT ModeNo) +{ + USHORT crt2crtc, resindex; + int i,j; + const SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL; + + if(HwInfo->jChipType != SIS_300) return; + if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return; + if(SiS_Pr->UseCustomMode) return; + + if(ModeNo <= 0x13) { + crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + } else { + crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + } + + resindex = crt2crtc & 0x3F; + if(SiS_Pr->SiS_SetFlag & LCDVESATiming) CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1; + else CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2; + + /* The BIOS code (1.16.51,56) is obviously a fragment! */ + if(ModeNo > 0x13) { + CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1; + resindex = 4; + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]); + for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]); + } + for(j = 0x1c; j <= 0x1d; i++, j++ ) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]); + } + for(j = 0x1f; j <= 0x21; i++, j++ ) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]); + } + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]); +} +#endif + +static void +SiS_SetTVSpecial(SiS_Private *SiS_Pr, USHORT ModeNo) +{ + if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return; + if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return; + + if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { + if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) { + const UCHAR specialtv[] = { + 0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53, + 0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a, + 0x58,0xe4,0x73,0xda,0x13 + }; + int i, j; + for(i = 0x1c, j = 0; i <= 0x30; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,specialtv[j]); + } + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,0x72); + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) { + if(SiS_Pr->SiS_TVMode & TVSetPALM) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b); + } else { + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14); /* 15 */ + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a); /* 1b */ + } + } + } + } else { + if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) || + (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b); /* 21 */ + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54); /* 5a */ + } else { + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a); /* 21 */ + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53); /* 5a */ + } + } +} + +static void +SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo) +{ + USHORT temp; + + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) { + if(SiS_Pr->SiS_VGAVDE == 525) { + temp = 0xc3; + if(SiS_Pr->SiS_ModeType <= ModeVGA) { + temp++; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2; + } + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3); + } else if(SiS_Pr->SiS_VGAVDE == 420) { + temp = 0x4d; + if(SiS_Pr->SiS_ModeType <= ModeVGA) { + temp++; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++; + } + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp); + } + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) { + if(SiS_Pr->SiS_VBType & VB_SIS301B302B) { + SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03); + /* Not always for LV, see SetGrp2 */ + } + temp = 1; + if(ModeNo <= 0x13) temp = 3; + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp); + } +#if 0 + /* 651+301C, for 1280x768 - do I really need that? */ + if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) { + if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) { + if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) || + ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) { + SiS_SetReg(SiS_Part2Port,0x01,0x2b); + SiS_SetReg(SiS_Part2Port,0x02,0x13); + SiS_SetReg(SiS_Part2Port,0x04,0xe5); + SiS_SetReg(SiS_Part2Port,0x05,0x08); + SiS_SetReg(SiS_Part2Port,0x06,0xe2); + SiS_SetReg(SiS_Part2Port,0x1c,0x21); + SiS_SetReg(SiS_Part2Port,0x1d,0x45); + SiS_SetReg(SiS_Part2Port,0x1f,0x0b); + SiS_SetReg(SiS_Part2Port,0x20,0x00); + SiS_SetReg(SiS_Part2Port,0x21,0xa9); + SiS_SetReg(SiS_Part2Port,0x23,0x0b); + SiS_SetReg(SiS_Part2Port,0x25,0x04); + } + } + } +#endif + } +} + +static void +SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT RefreshRateTableIndex, + PSIS_HW_INFO HwInfo) +{ + USHORT i, j, tempax, tempbx, tempcx, tempch, tempcl, temp; + USHORT push2, modeflag, crt2crtc, bridgeoffset; + ULONG longtemp; + const UCHAR *PhasePoint; + const UCHAR *TimingPoint; +#ifdef SIS315H + USHORT resindex, CRT2Index; + const SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return; +#endif + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + } else if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + crt2crtc = 0; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + } + + temp = 0; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO)) temp |= 0x08; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x04; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) temp |= 0x02; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp |= 0x01; + + if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) temp |= 0x10; + + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp); + + PhasePoint = SiS_Pr->SiS_PALPhase; + TimingPoint = SiS_Pr->SiS_PALTiming; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + + TimingPoint = SiS_Pr->SiS_HiTVExtTiming; + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + TimingPoint = SiS_Pr->SiS_HiTVSt2Timing; + if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) { + TimingPoint = SiS_Pr->SiS_HiTVSt1Timing; +#if 0 + if(!(modeflag & Charx8Dot)) TimingPoint = SiS_Pr->SiS_HiTVTextTiming; +#endif + } + } + + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { + + if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) TimingPoint = &SiS_YPbPrTable[2][0]; + else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) TimingPoint = &SiS_YPbPrTable[1][0]; + else TimingPoint = &SiS_YPbPrTable[0][0]; + + PhasePoint = SiS_Pr->SiS_NTSCPhase; + + } else if(SiS_Pr->SiS_TVMode & TVSetPAL) { + + if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && + ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || + (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) { + PhasePoint = SiS_Pr->SiS_PALPhase2; + } + + } else { + + TimingPoint = SiS_Pr->SiS_NTSCTiming; + PhasePoint = SiS_Pr->SiS_NTSCPhase; + if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) { + PhasePoint = SiS_Pr->SiS_PALPhase; + } + + if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && + ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || + (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) { + PhasePoint = SiS_Pr->SiS_NTSCPhase2; + if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) { + PhasePoint = SiS_Pr->SiS_PALPhase2; + } + } + + } + + if(SiS_Pr->SiS_TVMode & TVSetPALM) { + PhasePoint = SiS_Pr->SiS_PALMPhase; + if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && + ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || + (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) { + PhasePoint = SiS_Pr->SiS_PALMPhase2; + } + } + + if(SiS_Pr->SiS_TVMode & TVSetPALN) { + PhasePoint = SiS_Pr->SiS_PALNPhase; + if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && + ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || + (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) { + PhasePoint = SiS_Pr->SiS_PALNPhase2; + } + } + + if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) { + PhasePoint = SiS_Pr->SiS_SpecialPhase; + if(SiS_Pr->SiS_TVMode & TVSetPALM) { + PhasePoint = SiS_Pr->SiS_SpecialPhaseM; + } else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) { + PhasePoint = SiS_Pr->SiS_SpecialPhaseJ; + } + } + + for(i=0x31, j=0; i<=0x34; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,PhasePoint[j]); + } + + for(i=0x01, j=0; i<=0x2D; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]); + } + for(i=0x39; i<=0x45; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]); + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_Pr->SiS_ModeType != ModeText) { + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F); + } + } + + SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode); + + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,SiS_Pr->SiS_RY1COE); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,SiS_Pr->SiS_RY2COE); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE); + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempax = 950; + else if(SiS_Pr->SiS_TVMode & TVSetPAL) tempax = 520; + else tempax = 440; /* NTSC, YPbPr 525, 750 */ + + if( ( (!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) && (SiS_Pr->SiS_VDE <= tempax) ) || + ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) && + ((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) { + + tempax -= SiS_Pr->SiS_VDE; + tempax >>= 2; + tempax &= 0x00ff; + + temp = tempax + (USHORT)TimingPoint[0]; + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp); + + temp = tempax + (USHORT)TimingPoint[1]; + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp); + + if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) { + if(SiS_Pr->SiS_TVMode & TVSetPAL) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b); /* 19 */ + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54); /* 52 */ + } else { + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d); + } + } + + } + + tempcx = SiS_Pr->SiS_HT; + if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1; + tempcx--; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx--; + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f)); + + tempcx = SiS_Pr->SiS_HT >> 1; + if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1; + tempcx += 7; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0)); + + tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8); + tempbx += tempcx; + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0)); + + tempbx += 8; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + tempbx -= 4; + tempcx = tempbx; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0)); + + j += 2; + tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8)); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0)); + + tempcx += 8; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0)); + + tempcx = SiS_Pr->SiS_HT >> 1; + if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1; + j += 2; + tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8)); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0)); + + tempcx -= 11; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) { + tempcx = SiS_GetVGAHT2(SiS_Pr) - 1; + } + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx); + + tempbx = SiS_Pr->SiS_VDE; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746; + if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746; + if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853; + } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && + (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) { + tempbx >>= 1; + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) { + if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++; + } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(SiS_Pr->SiS_ModeType <= ModeVGA) { + if(crt2crtc == 4) tempbx++; + } + } + } + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++; + } + if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { + if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */ + } + } + } + tempbx -= 2; + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx); + + temp = (tempcx >> 8) & 0x0F; + temp |= ((tempbx >> 2) & 0xC0); + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) { + temp |= 0x10; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20; + } + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp); + + if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5)); + } + +#if 0 + /* TEST qqqq */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { + for(i=0x01, j=0; i<=0x2D; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]); + } + for(i=0x39; i<=0x45; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]); + } + } +#endif + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + tempbx = SiS_Pr->SiS_VDE; + if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && + (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) { + tempbx >>= 1; + } + tempbx -= 3; + temp = ((tempbx >> 3) & 0x60) | 0x18; + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx); + + if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4)); + } + } + + tempbx = 0; + if(!(modeflag & HalfDCLK)) { + if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) { + tempax = 0; + tempbx |= 0x20; + } + } + + tempch = tempcl = 0x01; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_Pr->SiS_VGAHDE >= 1024) { + if((!(modeflag & HalfDCLK)) || (HwInfo->jChipType < SIS_315H)) { + tempch = 0x19; + tempcl = 0x20; + if(SiS_Pr->SiS_VGAHDE >= 1280) { + tempch = 0x14; + tempbx &= ~0x20; + } + } + } + } + + if(!(tempbx & 0x20)) { + if(modeflag & HalfDCLK) tempcl <<= 1; + longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) longtemp <<= 3; + tempax = longtemp / SiS_Pr->SiS_HDE; + if(longtemp % SiS_Pr->SiS_HDE) tempax++; + tempbx |= ((tempax >> 8) & 0x1F); + tempcx = tempax >> 13; + } + + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx); + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + + tempcx &= 0x07; + if(tempbx & 0x20) tempcx = 0; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx); + + if(SiS_Pr->SiS_TVMode & TVSetPAL) { + tempbx = 0x0382; + tempcx = 0x007e; + } else { + tempbx = 0x0369; + tempcx = 0x0061; + } + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx); + temp = (tempcx & 0x0300) >> 6; + temp |= ((tempbx >> 8) & 0x03); + if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { + temp |= 0x10; + if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp |= 0x20; + else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp |= 0x40; + } + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp); + + temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3)); + + SiS_SetTVSpecial(SiS_Pr, ModeNo); + + if(SiS_Pr->SiS_VBType & VB_SIS301C) { + temp = 0; + if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp); + } + + } + + if(SiS_Pr->SiS_TVMode & TVSetPALM) { + if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) { + temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1)); + } + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF); + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,0x00); + } + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) return; + + /* From here: Part2 LCD setup */ + + tempbx = SiS_Pr->SiS_HDE; + if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1; + tempbx--; /* RHACTE = HDE - 1 */ + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0)); + + temp = 0x01; + if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) { + if(SiS_Pr->SiS_ModeType == ModeEGA) { + if(SiS_Pr->SiS_VGAHDE >= 1024) { + temp = 0x02; + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_SetFlag & LCDVESATiming) { + temp = 0x01; + } + } + } + } + } + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp); + + tempbx = SiS_Pr->SiS_VDE - 1; + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07)); + + tempcx = SiS_Pr->SiS_VT - 1; + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx); + temp = (tempcx >> 3) & 0xE0; + if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) { + /* Enable dithering; only do this for 32bpp mode */ + if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) { + temp |= 0x10; + } + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp); + + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0); + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0); + + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB); + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF); + +#ifdef SIS315H + if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, + &CRT2Index, &resindex, HwInfo)) { + switch(CRT2Index) { + case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1; break; + case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3; break; + default: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3; break; + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]); + for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]); + } + for(j = 0x1c; j <= 0x1d; i++, j++ ) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]); + } + for(j = 0x1f; j <= 0x21; i++, j++ ) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]); + } + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]); + + SiS_SetGroup2_Tail(SiS_Pr, ModeNo); + + + } else { +#endif + + /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */ + /* Clevo dual-link 1024x768 */ + /* Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct) */ + /* Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */ + + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) { + tempbx = SiS_Pr->SiS_VDE - 1; + tempcx = SiS_Pr->SiS_VT - 1; + } else { + tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2); + tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2); + } + } else { + tempbx = SiS_Pr->PanelYRes; + tempcx = SiS_Pr->SiS_VT; + tempax = 1; + if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) { + tempax = SiS_Pr->PanelYRes; + /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c; */ /* 651+301C */ + if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) { + tempax = tempcx = 0; + } else { + tempax -= SiS_Pr->SiS_VDE; + } + tempax >>= 1; + } + tempcx -= tempax; /* lcdvdes */ + tempbx -= tempax; /* lcdvdee */ + } + + /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */ + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx); +#endif + + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx); /* lcdvdes */ + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx); /* lcdvdee */ + + temp = (tempbx >> 5) & 0x38; + temp |= ((tempcx >> 8) & 0x07); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp); + + tempax = SiS_Pr->SiS_VDE; + if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) { + tempax = SiS_Pr->PanelYRes; + } + tempcx = (SiS_Pr->SiS_VT - tempax) >> 4; + if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) { + if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) { + tempcx = (SiS_Pr->SiS_VT - tempax) / 10; + } + } + + tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) { + if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */ + tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes; + if(tempax % 4) { tempax >>= 2; tempax++; } + else { tempax >>= 2; } + tempbx -= (tempax - 1); + } else { + tempbx -= 10; + if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1; + } + } + } + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + tempbx++; + if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) { + if(SiS_Pr->SiS_SetFlag & LCDVESATiming) { + tempbx = 770; + tempcx = 3; + } + } + } + + /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */ + + if(SiS_Pr->UseCustomMode) { + tempbx = SiS_Pr->CVSyncStart; + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx); +#endif + + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx); /* lcdvrs */ + + temp = (tempbx >> 4) & 0xF0; + tempbx += (tempcx + 1); + temp |= (tempbx & 0x0F); + + if(SiS_Pr->UseCustomMode) { + temp &= 0xf0; + temp |= (SiS_Pr->CVSyncEnd & 0x0f); + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "lcdvre[3:0] 0x%x\n", (temp & 0x0f)); +#endif + + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp); + +#ifdef SIS300 + SiS_Group2LCDSpecial(SiS_Pr, HwInfo, ModeNo, crt2crtc); +#endif + + bridgeoffset = 7; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) bridgeoffset += 2; + if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) bridgeoffset++; + if(SiS_IsDualLink(SiS_Pr, HwInfo)) bridgeoffset++; + + temp = 0; + if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) { + if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) { + temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2); + if(SiS_IsDualLink(SiS_Pr, HwInfo)) temp >>= 1; + } + } + temp += bridgeoffset; + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp); /* lcdhdes */ + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0)); + + tempcx = SiS_Pr->SiS_HT; + tempax = tempbx = SiS_Pr->SiS_HDE; + if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) { + if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) { + tempax = SiS_Pr->PanelXRes; + tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2); + } + } + if(SiS_IsDualLink(SiS_Pr, HwInfo)) { + tempcx >>= 1; + tempbx >>= 1; + tempax >>= 1; + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx); +#endif + + tempbx += bridgeoffset; + + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx); /* lcdhdee */ + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f)); + + tempcx = (tempcx - tempax) >> 2; + + tempbx += tempcx; + push2 = tempbx; + + if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) { + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { + if(SiS_Pr->SiS_LCDInfo & LCDPass11) { + if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47; + } + } + } + + if(SiS_Pr->UseCustomMode) { + tempbx = SiS_Pr->CHSyncStart; + if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1; + tempbx += bridgeoffset; + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx); +#endif + + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx); /* lcdhrs */ + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0)); + + tempbx = push2; + + tempcx <<= 1; + if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) { + if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2; + } + tempbx += tempcx; + + if(SiS_Pr->UseCustomMode) { + tempbx = SiS_Pr->CHSyncEnd; + if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1; + tempbx += bridgeoffset; + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx); +#endif + + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx); /* lcdhre */ + + SiS_SetGroup2_Tail(SiS_Pr, ModeNo); + +#ifdef SIS300 + SiS_Set300Part2Regs(SiS_Pr, HwInfo, ModeIdIndex, RefreshRateTableIndex, ModeNo); +#endif +#ifdef SIS315H + } /* CRT2-LCD from table */ +#endif +} + +/*********************************************/ +/* SET PART 3 REGISTER GROUP */ +/*********************************************/ + +static void +SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo) +{ + USHORT i; + const UCHAR *tempdi; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return; + +#ifndef SIS_CP + SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00); +#else + SIS_CP_INIT301_CP +#endif + + if(SiS_Pr->SiS_TVMode & TVSetPAL) { + SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA); + SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8); + } else { + SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xF5); + SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xB7); + } + + if(SiS_Pr->SiS_TVMode & TVSetPALM) { + SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA); + SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8); + SiS_SetReg(SiS_Pr->SiS_Part3Port,0x3D,0xA8); + } + + tempdi = NULL; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + tempdi = SiS_Pr->SiS_HiTVGroup3Data; + if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) { + tempdi = SiS_Pr->SiS_HiTVGroup3Simu; + } + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) { + if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) { + tempdi = SiS_HiTVGroup3_1; + if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempdi = SiS_HiTVGroup3_2; + } + } + if(tempdi) { + for(i=0; i<=0x3E; i++) { + SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]); + } + if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) { + if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) { + SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f); + } + } + } + +#ifdef SIS_CP + SIS_CP_INIT301_CP2 +#endif +} + +/*********************************************/ +/* SET PART 4 REGISTER GROUP */ +/*********************************************/ + +#ifdef SIS315H +static void +SiS_ShiftXPos(SiS_Private *SiS_Pr, int shift) +{ + USHORT temp, temp1, temp2; + + temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f); + temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20); + temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0)); + temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f; + temp = (USHORT)((int)(temp) + shift); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f)); + temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43); + temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42); + temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0)); +} + +static void +SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo, USHORT ModeIdIndex) +{ + USHORT temp, temp1, resinfo = 0; + + if(!(SiS_Pr->SiS_VBType & VB_SIS301C)) return; + if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return; + + if(ModeNo > 0x13) { + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + } + + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08); + temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a); + if(!(temp & 0x01)) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf); + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc); + if((HwInfo->jChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8); + } + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb); + if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp = 0x0000; + else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002; + else if(SiS_Pr->SiS_TVMode & TVSetHiVision) temp = 0x0400; + else temp = 0x0402; + if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) { + temp1 = 0; + if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1); + if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01; + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff)); + } else { + temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03; + if(temp1 == 0x01) temp |= 0x01; + if(temp1 == 0x03) temp |= 0x04; /* ? why not 0x10? */ + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff)); + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8)); + if(ModeNo > 0x13) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd); + } + + if(HwInfo->jChipType >= SIS_661) { /* ? */ + if(SiS_Pr->SiS_TVMode & TVAspect43) { + if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) { + if(resinfo == SIS_RI_1024x768) { + SiS_ShiftXPos(SiS_Pr, 97); + } else { + SiS_ShiftXPos(SiS_Pr, 111); + } + } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) { + SiS_ShiftXPos(SiS_Pr, 136); + } + } + } + } +} +#endif + +static void +SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo) +{ + USHORT vclkindex; + USHORT temp, reg1, reg2; + + if(SiS_Pr->UseCustomMode) { + reg1 = SiS_Pr->CSR2B; + reg2 = SiS_Pr->CSR2C; + } else { + vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, + HwInfo); + reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A; + reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B; + } + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) { + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6); + } else { + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2); + } + } else { + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x01); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1); + } + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00); + temp = 0x08; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20; + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp); +} + +static void +SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo) +{ + USHORT tempax,tempcx,tempbx,modeflag,temp,resinfo; + ULONG tempebx,tempeax,templong; + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; + } else if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + resinfo = 0; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + } + + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e); + } + } + } + + if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV)) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f); + } + } + + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + if(SiS_IsDualLink(SiS_Pr, HwInfo)) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c); + } else { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20); + } + + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) { + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00); +#ifdef SET_EMI + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c); +#endif + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10); + } + } + return; + } + } + + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT); + + tempbx = SiS_Pr->SiS_RVBHCMAX; + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx); + + temp = (tempbx >> 1) & 0x80; + + tempcx = SiS_Pr->SiS_VGAHT - 1; + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx); + + temp |= ((tempcx >> 5) & 0x78); + + tempcx = SiS_Pr->SiS_VGAVT - 1; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5; + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx); + + temp |= ((tempcx >> 8) & 0x07); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp); + + tempbx = SiS_Pr->SiS_VGAHDE; + if(modeflag & HalfDCLK) tempbx >>= 1; + if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + temp = 0; + if(tempbx > 800) temp = 0x60; + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + temp = 0; + if(tempbx == 1024) temp = 0xA0; + else if(tempbx > 1024) temp = 0xC0; + } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) { + temp = 0; + if(tempbx >= 1280) temp = 0x40; + else if(tempbx >= 1024) temp = 0x20; + } else { + temp = 0x80; + if(tempbx >= 1024) temp = 0xA0; + } + + if(SiS_Pr->SiS_VBType & VB_SIS301) { + if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) temp |= 0x0A; + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp); + + tempeax = SiS_Pr->SiS_VGAVDE; + tempebx = SiS_Pr->SiS_VDE; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) { + if(!(temp & 0xE0)) tempebx >>=1; + } + + tempcx = SiS_Pr->SiS_RVBHRS; + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx); + tempcx >>= 8; + tempcx |= 0x40; + + if(tempeax <= tempebx) { + tempcx ^= 0x40; + } else { + tempeax -= tempebx; + } + + tempeax *= (256 * 1024); + templong = tempeax % tempebx; + tempeax /= tempebx; + if(templong) tempeax++; + + temp = (USHORT)(tempeax & 0x000000FF); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp); + temp = (USHORT)((tempeax & 0x0000FF00) >> 8); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp); + temp = (USHORT)((tempeax >> 12) & 0x70); /* sic! */ + temp |= (tempcx & 0x4F); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp); + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28); + + /* Calc Linebuffer max address and set/clear decimode */ + tempbx = 0; + if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08; + tempax = SiS_Pr->SiS_VGAHDE; + if(modeflag & HalfDCLK) tempax >>= 1; + if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempax >>= 1; + if(tempax > 800) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + tempax -= 800; + } else { /* 651+301C: Only if TVNoHiviNoYPbPr */ + tempbx = 0x08; + if(tempax == 1024) tempax *= 25; + else tempax *= 20; + temp = tempax % 32; + tempax /= 32; + if(temp) tempax++; + tempax++; + if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) || + (SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) { + if(resinfo == SIS_RI_1024x768) { + /* Otherwise white line at right edge */ + tempax = (tempax & 0xff00) | 0x20; + } + } + } + } + tempax--; + temp = ((tempax >> 4) & 0x30) | tempbx; + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax); + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp); + + temp = 0x0036; tempbx = 0xD0; + if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) { + temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */ + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) { + temp |= 0x01; + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) { + temp &= ~0x01; + } + } + } + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp); + + tempbx = SiS_Pr->SiS_HT >> 1; + if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1; + tempbx -= 2; + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx); + temp = (tempbx >> 5) & 0x38; + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp); + + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e); + /* LCD-too-dark-error-source, see FinalizeLCD() */ + } + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_IsDualLink(SiS_Pr, HwInfo)) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c); + } else { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20); + } + } + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) { + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00); +#ifdef SET_EMI + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c); +#endif + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10); + } + } + + } /* 301B */ + + SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); +} + +/*********************************************/ +/* SET PART 5 REGISTER GROUP */ +/*********************************************/ + +static void +SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo) +{ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return; + + if(SiS_Pr->SiS_ModeType == ModeVGA) { + if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) { + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); + SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex); + } + } +} + +/*********************************************/ +/* MODIFY CRT1 GROUP FOR SLAVE MODE */ +/*********************************************/ + +static void +SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo) +{ + USHORT tempah,i,modeflag,j; + USHORT ResIndex,DisplayType; + const SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr=NULL; + + if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + else modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + + if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || + (SiS_Pr->SiS_CustomT == CUT_BARCO1024) || + (SiS_Pr->SiS_CustomT == CUT_PANEL848)) + return; + + if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, + &ResIndex, &DisplayType))) { + return; + } + + if(HwInfo->jChipType < SIS_315H) { + if(SiS_Pr->SiS_SetFlag & SetDOSMode) return; + } + + switch(DisplayType) { + case 0 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1; break; + case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H; break; + case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2; break; + case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H; break; + case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1; break; + case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H; break; + case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2; break; + case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H; break; + case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1; break; + case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H; break; + case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2; break; + case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2_H; break; + case 12: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1; break; + case 13: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H; break; + case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_1; break; + case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_1_H; break; + case 16: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_2; break; + case 17: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_2_H; break; + case 18: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC; break; + case 19: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC; break; + case 20: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL; break; + case 21: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL; break; + case 22: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x480_1; break; /* FSTN */ + case 23: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1; break; + case 24: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H; break; + case 25: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2; break; + case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H; break; + case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_1; break; + case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_1_H; break; + case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_2; break; + case 30: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_2_H; break; + case 36: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_1; break; + case 37: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_1_H; break; + case 38: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_2; break; + case 39: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_2_H; break; + case 40: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_1; break; + case 41: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_1_H; break; + case 42: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2; break; + case 43: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2_H; break; + case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1; break; + case 51: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H; break; + case 52: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2; break; + case 53: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2_H; break; + case 54: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3; break; + case 55: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3_H; break; + case 99: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL; break; + default: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1; break; + } + + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); + + tempah = (LVDSCRT1Ptr + ResIndex)->CR[0]; + SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,tempah); + + for(i=0x02,j=1;i<=0x05;i++,j++){ + tempah = (LVDSCRT1Ptr + ResIndex)->CR[j]; + SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x06,j=5;i<=0x07;i++,j++){ + tempah = (LVDSCRT1Ptr + ResIndex)->CR[j]; + SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x10,j=7;i<=0x11;i++,j++){ + tempah = (LVDSCRT1Ptr + ResIndex)->CR[j]; + SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x15,j=9;i<=0x16;i++,j++){ + tempah = (LVDSCRT1Ptr + ResIndex)->CR[j]; + SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x0A,j=11;i<=0x0C;i++,j++){ + tempah = (LVDSCRT1Ptr + ResIndex)->CR[j]; + SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah); + } + + tempah = (LVDSCRT1Ptr + ResIndex)->CR[14]; + tempah &= 0xE0; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah); + + tempah = (LVDSCRT1Ptr + ResIndex)->CR[14]; + tempah &= 0x01; + tempah <<= 5; + if(modeflag & DoubleScanMode) tempah |= 0x080; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah); +} + +/*********************************************/ +/* SET CRT2 ECLK */ +/*********************************************/ + +static void +SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT clkbase, vclkindex=0; + UCHAR sr2b, sr2c; + + if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) || (SiS_Pr->SiS_LCDInfo & LCDPass11)) { + SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2); + if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK & 0x3f) == 2) { + RefreshRateTableIndex--; + } + vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, + RefreshRateTableIndex, HwInfo); + SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; + } else { + vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, + RefreshRateTableIndex, HwInfo); + } + + sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B; + sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C; + + if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) { + if(SiS_Pr->SiS_UseROM) { + if(ROMAddr[0x220] & 0x01) { + sr2b = ROMAddr[0x227]; + sr2c = ROMAddr[0x228]; + } + } + } + + clkbase = 0x02B; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + clkbase += 3; + } + } + + SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20); + SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b); + SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10); + SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b); + SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00); + SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b); + SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c); +} + +/*********************************************/ +/* SET UP CHRONTEL CHIPS */ +/*********************************************/ + +static void +SiS_SetCHTVReg(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex) +{ +#if defined(SIS300) || defined(SIS315H) + USHORT temp, tempbx; +#endif + USHORT tempcl; + USHORT TVType, resindex; + const SiS_CHTVRegDataStruct *CHTVRegData = NULL; + + if(ModeNo <= 0x13) + tempcl = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + else + tempcl = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + + TVType = 0; + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1; + if(SiS_Pr->SiS_TVMode & TVSetPAL) { + TVType += 2; + if(SiS_Pr->SiS_ModeType > ModeVGA) { + if(SiS_Pr->SiS_CHSOverScan) TVType = 8; + } + if(SiS_Pr->SiS_TVMode & TVSetPALM) { + TVType = 4; + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1; + } else if(SiS_Pr->SiS_TVMode & TVSetPALN) { + TVType = 6; + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1; + } + } + switch(TVType) { + case 0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break; + case 1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break; + case 2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL; break; + case 3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break; + case 4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break; + case 5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break; + case 6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break; + case 7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break; + case 8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break; + default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break; + } + resindex = tempcl & 0x3F; + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) { + +#ifdef SIS300 + + /* Chrontel 7005 - I assume that it does not come with a 315 series chip */ + + /* We don't support modes >800x600 */ + if (resindex > 5) return; + + if(SiS_Pr->SiS_TVMode & TVSetPAL) { + SiS_SetCH700x(SiS_Pr,0x4304); /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/ + SiS_SetCH700x(SiS_Pr,0x6909); /* Black level for PAL (105)*/ + } else { + SiS_SetCH700x(SiS_Pr,0x0304); /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/ + SiS_SetCH700x(SiS_Pr,0x7109); /* Black level for NTSC (113)*/ + } + + temp = CHTVRegData[resindex].Reg[0]; + tempbx=((temp&0x00FF)<<8)|0x00; /* Mode register */ + SiS_SetCH700x(SiS_Pr,tempbx); + temp = CHTVRegData[resindex].Reg[1]; + tempbx=((temp&0x00FF)<<8)|0x07; /* Start active video register */ + SiS_SetCH700x(SiS_Pr,tempbx); + temp = CHTVRegData[resindex].Reg[2]; + tempbx=((temp&0x00FF)<<8)|0x08; /* Position overflow register */ + SiS_SetCH700x(SiS_Pr,tempbx); + temp = CHTVRegData[resindex].Reg[3]; + tempbx=((temp&0x00FF)<<8)|0x0A; /* Horiz Position register */ + SiS_SetCH700x(SiS_Pr,tempbx); + temp = CHTVRegData[resindex].Reg[4]; + tempbx=((temp&0x00FF)<<8)|0x0B; /* Vertical Position register */ + SiS_SetCH700x(SiS_Pr,tempbx); + + /* Set minimum flicker filter for Luma channel (SR1-0=00), + minimum text enhancement (S3-2=10), + maximum flicker filter for Chroma channel (S5-4=10) + =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!) + */ + SiS_SetCH700x(SiS_Pr,0x2801); + + /* Set video bandwidth + High bandwith Luma composite video filter(S0=1) + low bandwith Luma S-video filter (S2-1=00) + disable peak filter in S-video channel (S3=0) + high bandwidth Chroma Filter (S5-4=11) + =00110001=0x31 + */ + SiS_SetCH700x(SiS_Pr,0xb103); /* old: 3103 */ + + /* Register 0x3D does not exist in non-macrovision register map + (Maybe this is a macrovision register?) + */ +#ifndef SIS_CP + SiS_SetCH70xx(SiS_Pr,0x003D); +#endif + + /* Register 0x10 only contains 1 writable bit (S0) for sensing, + all other bits a read-only. Macrovision? + */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0010,0x1F); + + /* Register 0x11 only contains 3 writable bits (S0-S2) for + contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) ) + */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0211,0xF8); + + /* Clear DSEN + */ + SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xEF); + + if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { /* ---- NTSC ---- */ + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) { + if(resindex == 0x04) { /* 640x480 overscan: Mode 16 */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE); /* ACIV on, no need to set FSCI */ + } else if(resindex == 0x05) { /* 800x600 overscan: Mode 23 */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0118,0xF0); /* 0x18-0x1f: FSCI 469,762,048 */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0C19,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x001A,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x001B,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x001D,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x001E,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x001F,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x0120,0xEF); /* Loop filter on for mode 23 */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0021,0xFE); /* ACIV off, need to set FSCI */ + } + } else { + if(resindex == 0x04) { /* ----- 640x480 underscan; Mode 17 */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE); + } else if(resindex == 0x05) { /* ----- 800x600 underscan: Mode 24 */ +#if 0 + SiS_SetCH70xxANDOR(SiS_Pr,0x0118,0xF0); /* (FSCI was 0x1f1c71c7 - this is for mode 22) */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0919,0xF0); /* FSCI for mode 24 is 428,554,851 */ + SiS_SetCH70xxANDOR(SiS_Pr,0x081A,0xF0); /* 198b3a63 */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0b1B,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x041C,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x011D,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x061E,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x051F,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off for mode 24 */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0021,0xFE); /* ACIV off, need to set FSCI */ +#endif /* All alternatives wrong (datasheet wrong?), don't use FSCI */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE); + } + } + } else { /* ---- PAL ---- */ + /* We don't play around with FSCI in PAL mode */ + if(resindex == 0x04) { + SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE); /* ACIV on */ + } else { + SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE); /* ACIV on */ + } + } + +#endif /* 300 */ + + } else { + + /* Chrontel 7019 - assumed that it does not come with a 300 series chip */ + +#ifdef SIS315H + + /* We don't support modes >1024x768 */ + if (resindex > 6) return; + + temp = CHTVRegData[resindex].Reg[0]; + if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) { + temp |= 0x10; + } + tempbx=((temp & 0x00FF) << 8) | 0x00; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[1]; + tempbx=((temp & 0x00FF) << 8) | 0x01; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[2]; + tempbx=((temp & 0x00FF) << 8) | 0x02; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[3]; + tempbx=((temp & 0x00FF) << 8) | 0x04; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[4]; + tempbx=((temp & 0x00FF) << 8) | 0x03; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[5]; + tempbx=((temp & 0x00FF) << 8) | 0x05; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[6]; + tempbx=((temp & 0x00FF) << 8) | 0x06; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[7]; + if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) { + temp = 0x66; + } + tempbx=((temp & 0x00FF) << 8) | 0x07; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[8]; + tempbx=((temp & 0x00FF) << 8) | 0x08; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[9]; + tempbx=((temp & 0x00FF) << 8) | 0x15; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[10]; + tempbx=((temp & 0x00FF) << 8) | 0x1f; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[11]; + tempbx=((temp & 0x00FF) << 8) | 0x0c; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[12]; + tempbx=((temp & 0x00FF) << 8) | 0x0d; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[13]; + tempbx=((temp & 0x00FF) << 8) | 0x0e; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[14]; + tempbx=((temp & 0x00FF) << 8) | 0x0f; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = CHTVRegData[resindex].Reg[15]; + tempbx=((temp & 0x00FF) << 8) | 0x10; + SiS_SetCH701x(SiS_Pr,tempbx); + + temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02; + /* D1 should be set for PAL, PAL-N and NTSC-J, + but I won't do that for PAL unless somebody + tells me to do so. Since the BIOS uses + non-default CIV values and blacklevels, + this might be compensated anyway. + */ + if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02; + SiS_SetCH701x(SiS_Pr,((temp << 8) | 0x21)); + +#endif /* 315 */ + + } + +#ifdef SIS_CP + SIS_CP_INIT301_CP3 +#endif + +} + +void +SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT temp; + + /* Enable Chrontel 7019 LCD panel backlight */ + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + if(HwInfo->jChipType == SIS_740) { + SiS_SetCH701x(SiS_Pr,0x6566); + } else { + temp = SiS_GetCH701x(SiS_Pr,0x66); + temp |= 0x20; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66); + } + } +} + +void +SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr) +{ + USHORT temp; + + /* Disable Chrontel 7019 LCD panel backlight */ + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + temp = SiS_GetCH701x(SiS_Pr,0x66); + temp &= 0xDF; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66); + } +} + +#ifdef SIS315H /* ----------- 315 series only ---------- */ + +static void +SiS_ChrontelPowerSequencing(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR regtable[] = { 0x67, 0x68, 0x69, 0x6a, 0x6b }; + UCHAR table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 }; + UCHAR table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 }; + UCHAR asus1024_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 }; + UCHAR asus1400_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 }; + UCHAR table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 }; + UCHAR table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 }; + UCHAR *tableptr = NULL; + int i; + + /* Set up Power up/down timing */ + + if(HwInfo->jChipType == SIS_740) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740; + else tableptr = table1024_740; + } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) || + (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) || + (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) { + if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740; + else tableptr = table1400_740; + } else return; + } else { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + tableptr = table1024_650; + } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) || + (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) || + (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) { + tableptr = table1400_650; + } else return; + } + + for(i=0; i<5; i++) { + SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]); + } +} + +static void +SiS_SetCH701xForLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR regtable[] = { 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71, + 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66 }; + UCHAR table1024_740[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed, + 0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44 }; + UCHAR table1280_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3, + 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 }; + UCHAR table1400_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3, + 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 }; + UCHAR table1600_740[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3, + 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44 }; + UCHAR table1024_650[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed, + 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02 }; + UCHAR table1280_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3, + 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02 }; + UCHAR table1400_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xef, + 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02 }; + UCHAR table1600_650[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3, + 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a }; + UCHAR *tableptr = NULL; + USHORT tempbh; + int i; + + if(HwInfo->jChipType == SIS_740) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_740; + else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740; + else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740; + else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740; + else return; + } else { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_650; + else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650; + else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650; + else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650; + else return; + } + + tempbh = SiS_GetCH701x(SiS_Pr,0x74); + if((tempbh == 0xf6) || (tempbh == 0xc7)) { + tempbh = SiS_GetCH701x(SiS_Pr,0x73); + if(tempbh == 0xc8) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return; + } else if(tempbh == 0xdb) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return; + if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return; + } else if(tempbh == 0xde) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return; + } + } + + if(HwInfo->jChipType == SIS_740) tempbh = 0x0d; + else tempbh = 0x0c; + + for(i = 0; i < tempbh; i++) { + SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]); + } + SiS_ChrontelPowerSequencing(SiS_Pr,HwInfo); + tempbh = SiS_GetCH701x(SiS_Pr,0x1e); + tempbh |= 0xc0; + SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1e); + + if(HwInfo->jChipType == SIS_740) { + tempbh = SiS_GetCH701x(SiS_Pr,0x1c); + tempbh &= 0xfb; + SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1c); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03); + tempbh = SiS_GetCH701x(SiS_Pr,0x64); + tempbh |= 0x40; + SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x64); + tempbh = SiS_GetCH701x(SiS_Pr,0x03); + tempbh &= 0x3f; + SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x03); + } +} + +static void +SiS_ChrontelResetVSync(SiS_Private *SiS_Pr) +{ + unsigned char temp, temp1; + + temp1 = SiS_GetCH701x(SiS_Pr,0x49); + SiS_SetCH701x(SiS_Pr,0x3e49); + temp = SiS_GetCH701x(SiS_Pr,0x47); + temp &= 0x7f; /* Use external VSYNC */ + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); + SiS_LongDelay(SiS_Pr,3); + temp = SiS_GetCH701x(SiS_Pr,0x47); + temp |= 0x80; /* Use internal VSYNC */ + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); + SiS_SetCH701x(SiS_Pr,(temp1 << 8) | 0x49); +} + +static void +SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT temp; + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + if(HwInfo->jChipType == SIS_740) { + temp = SiS_GetCH701x(SiS_Pr,0x1c); + temp |= 0x04; /* Invert XCLK phase */ + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c); + } + if(SiS_IsYPbPr(SiS_Pr, HwInfo)) { + temp = SiS_GetCH701x(SiS_Pr,0x01); + temp &= 0x3f; + temp |= 0x80; /* Enable YPrPb (HDTV) */ + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01); + } + if(SiS_IsChScart(SiS_Pr, HwInfo)) { + temp = SiS_GetCH701x(SiS_Pr,0x01); + temp &= 0x3f; + temp |= 0xc0; /* Enable SCART + CVBS */ + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01); + } + if(HwInfo->jChipType == SIS_740) { + SiS_ChrontelResetVSync(SiS_Pr); + SiS_SetCH701x(SiS_Pr,0x2049); /* Enable TV path */ + } else { + SiS_SetCH701x(SiS_Pr,0x2049); /* Enable TV path */ + temp = SiS_GetCH701x(SiS_Pr,0x49); + if(SiS_IsYPbPr(SiS_Pr,HwInfo)) { + temp = SiS_GetCH701x(SiS_Pr,0x73); + temp |= 0x60; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x73); + } + temp = SiS_GetCH701x(SiS_Pr,0x47); + temp &= 0x7f; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); + SiS_LongDelay(SiS_Pr,2); + temp = SiS_GetCH701x(SiS_Pr,0x47); + temp |= 0x80; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); + } + } +} + +static void +SiS_Chrontel701xOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT temp; + + /* Complete power down of LVDS */ + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + if(HwInfo->jChipType == SIS_740) { + SiS_LongDelay(SiS_Pr,1); + SiS_GenericDelay(SiS_Pr,0x16ff); + SiS_SetCH701x(SiS_Pr,0xac76); + SiS_SetCH701x(SiS_Pr,0x0066); + } else { + SiS_LongDelay(SiS_Pr,2); + temp = SiS_GetCH701x(SiS_Pr,0x76); + temp &= 0xfc; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76); + SiS_SetCH701x(SiS_Pr,0x0066); + } + } +} + +static void +SiS_ChrontelResetDB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT temp; + + if(HwInfo->jChipType == SIS_740) { + + temp = SiS_GetCH701x(SiS_Pr,0x4a); /* Version ID */ + temp &= 0x01; + if(!temp) { + + if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo)) { + temp = SiS_GetCH701x(SiS_Pr,0x49); + SiS_SetCH701x(SiS_Pr,0x3e49); + } + /* Reset Chrontel 7019 datapath */ + SiS_SetCH701x(SiS_Pr,0x1048); + SiS_LongDelay(SiS_Pr,1); + SiS_SetCH701x(SiS_Pr,0x1848); + + if(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo)) { + SiS_ChrontelResetVSync(SiS_Pr); + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x49); + } + + } else { + + /* Clear/set/clear GPIO */ + temp = SiS_GetCH701x(SiS_Pr,0x5c); + temp &= 0xef; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c); + temp = SiS_GetCH701x(SiS_Pr,0x5c); + temp |= 0x10; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c); + temp = SiS_GetCH701x(SiS_Pr,0x5c); + temp &= 0xef; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c); + temp = SiS_GetCH701x(SiS_Pr,0x61); + if(!temp) { + SiS_SetCH701xForLCD(SiS_Pr, HwInfo); + } + } + + } else { /* 650 */ + /* Reset Chrontel 7019 datapath */ + SiS_SetCH701x(SiS_Pr,0x1048); + SiS_LongDelay(SiS_Pr,1); + SiS_SetCH701x(SiS_Pr,0x1848); + } +} + +static void +SiS_ChrontelInitTVVSync(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT temp; + + if(HwInfo->jChipType == SIS_740) { + + if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo)) { + SiS_ChrontelResetVSync(SiS_Pr); + } + + } else { + + SiS_SetCH701x(SiS_Pr,0xaf76); /* Power up LVDS block */ + temp = SiS_GetCH701x(SiS_Pr,0x49); + temp &= 1; + if(temp != 1) { /* TV block powered? (0 = yes, 1 = no) */ + temp = SiS_GetCH701x(SiS_Pr,0x47); + temp &= 0x70; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); /* enable VSYNC */ + SiS_LongDelay(SiS_Pr,3); + temp = SiS_GetCH701x(SiS_Pr,0x47); + temp |= 0x80; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); /* disable VSYNC */ + } + + } +} + +static void +SiS_ChrontelDoSomething3(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo) +{ + USHORT temp,temp1; + + if(HwInfo->jChipType == SIS_740) { + + temp = SiS_GetCH701x(SiS_Pr,0x61); + if(temp < 1) { + temp++; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61); + } + SiS_SetCH701x(SiS_Pr,0x4566); /* Panel power on */ + SiS_SetCH701x(SiS_Pr,0xaf76); /* All power on */ + SiS_LongDelay(SiS_Pr,1); + SiS_GenericDelay(SiS_Pr,0x16ff); + + } else { /* 650 */ + + temp1 = 0; + temp = SiS_GetCH701x(SiS_Pr,0x61); + if(temp < 2) { + temp++; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61); + temp1 = 1; + } + SiS_SetCH701x(SiS_Pr,0xac76); + temp = SiS_GetCH701x(SiS_Pr,0x66); + temp |= 0x5f; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66); + if(ModeNo > 0x13) { + if(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo)) { + SiS_GenericDelay(SiS_Pr,0x3ff); + } else { + SiS_GenericDelay(SiS_Pr,0x2ff); + } + } else { + if(!temp1) + SiS_GenericDelay(SiS_Pr,0x2ff); + } + temp = SiS_GetCH701x(SiS_Pr,0x76); + temp |= 0x03; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76); + temp = SiS_GetCH701x(SiS_Pr,0x66); + temp &= 0x7f; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66); + SiS_LongDelay(SiS_Pr,1); + + } +} + +static void +SiS_ChrontelDoSomething2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT temp,tempcl,tempch; + + SiS_LongDelay(SiS_Pr, 1); + tempcl = 3; + tempch = 0; + + do { + temp = SiS_GetCH701x(SiS_Pr,0x66); + temp &= 0x04; /* PLL stable? -> bail out */ + if(temp == 0x04) break; + + if(HwInfo->jChipType == SIS_740) { + /* Power down LVDS output, PLL normal operation */ + SiS_SetCH701x(SiS_Pr,0xac76); + } + + SiS_SetCH701xForLCD(SiS_Pr,HwInfo); + + if(tempcl == 0) { + if(tempch == 3) break; + SiS_ChrontelResetDB(SiS_Pr,HwInfo); + tempcl = 3; + tempch++; + } + tempcl--; + temp = SiS_GetCH701x(SiS_Pr,0x76); + temp &= 0xfb; /* Reset PLL */ + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76); + SiS_LongDelay(SiS_Pr,2); + temp = SiS_GetCH701x(SiS_Pr,0x76); + temp |= 0x04; /* PLL normal operation */ + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76); + if(HwInfo->jChipType == SIS_740) { + SiS_SetCH701x(SiS_Pr,0xe078); /* PLL loop filter */ + } else { + SiS_SetCH701x(SiS_Pr,0x6078); + } + SiS_LongDelay(SiS_Pr,2); + } while(0); + + SiS_SetCH701x(SiS_Pr,0x0077); /* MV? */ +} + +static void +SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT temp; + + temp = SiS_GetCH701x(SiS_Pr,0x03); + temp |= 0x80; /* Set datapath 1 to TV */ + temp &= 0xbf; /* Set datapath 2 to LVDS */ + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03); + + if(HwInfo->jChipType == SIS_740) { + + temp = SiS_GetCH701x(SiS_Pr,0x1c); + temp &= 0xfb; /* Normal XCLK phase */ + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c); + + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03); + + temp = SiS_GetCH701x(SiS_Pr,0x64); + temp |= 0x40; /* ? Bit not defined */ + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x64); + + temp = SiS_GetCH701x(SiS_Pr,0x03); + temp &= 0x3f; /* D1 input to both LVDS and TV */ + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03); + + if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) { + SiS_SetCH701x(SiS_Pr,0x4063); /* LVDS off */ + SiS_LongDelay(SiS_Pr, 1); + SiS_SetCH701x(SiS_Pr,0x0063); /* LVDS on */ + SiS_ChrontelResetDB(SiS_Pr, HwInfo); + SiS_ChrontelDoSomething2(SiS_Pr, HwInfo); + SiS_ChrontelDoSomething3(SiS_Pr, 0, HwInfo); + } else { + temp = SiS_GetCH701x(SiS_Pr,0x66); + if(temp != 0x45) { + SiS_ChrontelResetDB(SiS_Pr, HwInfo); + SiS_ChrontelDoSomething2(SiS_Pr, HwInfo); + SiS_ChrontelDoSomething3(SiS_Pr, 0, HwInfo); + } + } + + } else { /* 650 */ + + SiS_ChrontelResetDB(SiS_Pr,HwInfo); + SiS_ChrontelDoSomething2(SiS_Pr,HwInfo); + temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34); + SiS_ChrontelDoSomething3(SiS_Pr,temp,HwInfo); + SiS_SetCH701x(SiS_Pr,0xaf76); /* All power on, LVDS normal operation */ + + } + +} +#endif /* 315 series */ + +/*********************************************/ +/* MAIN: SET CRT2 REGISTER GROUP */ +/*********************************************/ + +BOOLEAN +SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo) +{ +#ifdef SIS300 + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; +#endif + USHORT ModeIdIndex, RefreshRateTableIndex; +#if 0 + USHORT temp; +#endif + + SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; + + if(!SiS_Pr->UseCustomMode) { + SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex); + } else { + ModeIdIndex = 0; + } + + /* Used for shifting CR33 */ + SiS_Pr->SiS_SelectCRT2Rate = 4; + + SiS_UnLockCRT2(SiS_Pr, HwInfo); + + RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + + SiS_SaveCRT2Info(SiS_Pr,ModeNo); + + if(SiS_Pr->SiS_SetFlag & LowModeTests) { + SiS_DisableBridge(SiS_Pr,HwInfo); + if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (HwInfo->jChipType == SIS_730)) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80); + } + SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + } + + if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) { + SiS_LockCRT2(SiS_Pr, HwInfo); + SiS_DisplayOn(SiS_Pr); + return TRUE; + } + + SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + + /* Set up Panel Link for LVDS and LCDA */ + SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0; + if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) || + ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) || + ((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) { + SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); + } + +#ifdef LINUX_XF86 +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "(init301: LCDHDES 0x%03x LCDVDES 0x%03x)\n", SiS_Pr->SiS_LCDHDES, SiS_Pr->SiS_LCDVDES); + xf86DrvMsg(0, X_INFO, "(init301: HDE 0x%03x VDE 0x%03x)\n", SiS_Pr->SiS_HDE, SiS_Pr->SiS_VDE); + xf86DrvMsg(0, X_INFO, "(init301: VGAHDE 0x%03x VGAVDE 0x%03x)\n", SiS_Pr->SiS_VGAHDE, SiS_Pr->SiS_VGAVDE); + xf86DrvMsg(0, X_INFO, "(init301: HT 0x%03x VT 0x%03x)\n", SiS_Pr->SiS_HT, SiS_Pr->SiS_VT); + xf86DrvMsg(0, X_INFO, "(init301: VGAHT 0x%03x VGAVT 0x%03x)\n", SiS_Pr->SiS_VGAHT, SiS_Pr->SiS_VGAVT); +#endif +#endif + + if(SiS_Pr->SiS_SetFlag & LowModeTests) { + SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex); + } + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + + if(SiS_Pr->SiS_SetFlag & LowModeTests) { + + SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); +#ifdef SIS315H + SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); +#endif + SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo); +#ifdef SIS315H + SiS_SetGroup4_C_ELV(SiS_Pr, HwInfo, ModeNo, ModeIdIndex); +#endif + SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + + SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo); + + /* For 301BDH (Panel link initialization): */ + if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) { + if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) { + if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwInfo); + } + } + } + SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwInfo); + } + } + + } else { + + SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo); + + if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { + SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo); + } + + SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo); + + if(SiS_Pr->SiS_SetFlag & LowModeTests) { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { +#ifdef SIS315H + SiS_SetCH701xForLCD(SiS_Pr,HwInfo); +#endif + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex); + } + } + } + + } + +#ifdef SIS300 + if(HwInfo->jChipType < SIS_315H) { + if(SiS_Pr->SiS_SetFlag & LowModeTests) { + if(SiS_Pr->SiS_UseOEM) { + if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) { + if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) { + SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex, + RefreshRateTableIndex); + } + } else { + SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex, + RefreshRateTableIndex); + } + } + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || + (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) { + SetOEMLCDData2(SiS_Pr, HwInfo, ModeNo, ModeIdIndex,RefreshRateTableIndex); + } + SiS_DisplayOn(SiS_Pr); + } + } + } +#endif + +#ifdef SIS315H + if(HwInfo->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_SetFlag & LowModeTests) { + if(HwInfo->jChipType < SIS_661) { + SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex, HwInfo); + SiS_OEM310Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex); + } else { + SiS_OEM661Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex); + } + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40); + } + } +#endif + + if(SiS_Pr->SiS_SetFlag & LowModeTests) { + SiS_EnableBridge(SiS_Pr, HwInfo); + } + + SiS_DisplayOn(SiS_Pr); + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + /* Disable LCD panel when using TV */ + SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFF,0x0C); + } else { + /* Disable TV when using LCD */ + SiS_SetCH70xxANDOR(SiS_Pr,0x010E,0xF8); + } + } + + if(SiS_Pr->SiS_SetFlag & LowModeTests) { + SiS_LockCRT2(SiS_Pr,HwInfo); + } + + return TRUE; +} + + +/*********************************************/ +/* ENABLE/DISABLE LCD BACKLIGHT (SIS) */ +/*********************************************/ + +void +SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + /* Switch on LCD backlight on SiS30xLV */ + SiS_DDC2Delay(SiS_Pr,0xff00); + if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02); + SiS_WaitVBRetrace(SiS_Pr,HwInfo); + } + if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01); + } +} + +void +SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + /* Switch off LCD backlight on SiS30xLV */ + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE); + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD); + SiS_DDC2Delay(SiS_Pr,0xe000); +} + +/*********************************************/ +/* DDC RELATED FUNCTIONS */ +/*********************************************/ + +static void +SiS_SetupDDCN(SiS_Private *SiS_Pr) +{ + SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data; + SiS_Pr->SiS_DDC_NClk = ~SiS_Pr->SiS_DDC_Clk; + if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) { + SiS_Pr->SiS_DDC_NData &= 0x0f; + SiS_Pr->SiS_DDC_NClk &= 0x0f; + } +} + +#ifdef SIS300 +static UCHAR * +SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr) +{ + int i, j, num; + USHORT tempah,temp; + UCHAR *mydataptr; + + for(i=0; i<20; i++) { /* Do 20 attempts to write */ + mydataptr = dataptr; + num = *mydataptr++; + if(!num) return mydataptr; + if(i) { + SiS_SetStop(SiS_Pr); + SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT*2); + } + if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */ + tempah = SiS_Pr->SiS_DDC_DeviceAddr; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */ + if(temp) continue; /* (ERROR: no ack) */ + tempah = *mydataptr++; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write register number */ + if(temp) continue; /* (ERROR: no ack) */ + for(j=0; j<num; j++) { + tempah = *mydataptr++; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */ + if(temp) break; + } + if(temp) continue; + if(SiS_SetStop(SiS_Pr)) continue; + return mydataptr; + } + return NULL; +} + +static BOOLEAN +SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr) +{ + SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB (Device Address Byte) */ + SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */ + SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */ + SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */ + SiS_SetupDDCN(SiS_Pr); + + SiS_SetSwitchDDC2(SiS_Pr); + + while(*dataptr) { + dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr); + if(!dataptr) return FALSE; + } +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "Trumpion block success\n"); +#endif + return TRUE; +} +#endif + +/* The Chrontel 700x is connected to the 630/730 via + * the 630/730's DDC/I2C port. + * + * On 630(S)T chipset, the index changed from 0x11 to + * 0x0a, possibly for working around the DDC problems + */ + +static BOOLEAN +SiS_SetChReg(SiS_Private *SiS_Pr, USHORT tempbx, USHORT myor) +{ + USHORT tempah,temp,i; + + for(i=0; i<20; i++) { /* Do 20 attempts to write */ + if(i) { + SiS_SetStop(SiS_Pr); + SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT); + } + if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */ + tempah = SiS_Pr->SiS_DDC_DeviceAddr; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */ + if(temp) continue; /* (ERROR: no ack) */ + tempah = tempbx & 0x00FF; /* Write RAB */ + tempah |= myor; /* (700x: set bit 7, see datasheet) */ + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); + if(temp) continue; /* (ERROR: no ack) */ + tempah = (tempbx & 0xFF00) >> 8; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write data */ + if(temp) continue; /* (ERROR: no ack) */ + if(SiS_SetStop(SiS_Pr)) continue; /* Set stop condition */ + SiS_Pr->SiS_ChrontelInit = 1; + return TRUE; + } + return FALSE; +} + +#if 0 +#ifdef SIS300 +/* Write Trumpion register */ +static void +SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx) +{ + SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB (Device Address Byte) */ + SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */ + SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */ + SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */ + SiS_SetupDDCN(SiS_Pr); + SiS_SetChReg(SiS_Pr, tempbx, 0); +} +#endif +#endif + +/* Write to Chrontel 700x */ +/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */ +void +SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx) +{ + SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */ + + if(!(SiS_Pr->SiS_ChrontelInit)) { + SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */ + SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */ + SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */ + SiS_SetupDDCN(SiS_Pr); + } + + if( (!(SiS_SetChReg(SiS_Pr, tempbx, 0x80))) && + (!(SiS_Pr->SiS_ChrontelInit)) ) { + SiS_Pr->SiS_DDC_Index = 0x0a; /* Bit 7 = SC; Bit 6 = SD */ + SiS_Pr->SiS_DDC_Data = 0x80; /* Bitmask in IndexReg for Data */ + SiS_Pr->SiS_DDC_Clk = 0x40; /* Bitmask in IndexReg for Clk */ + SiS_SetupDDCN(SiS_Pr); + + SiS_SetChReg(SiS_Pr, tempbx, 0x80); + } +} + +/* Write to Chrontel 701x */ +/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */ +void +SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx) +{ + SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */ + SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */ + SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */ + SiS_SetupDDCN(SiS_Pr); + SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */ + SiS_SetChReg(SiS_Pr, tempbx, 0); +} + +void +SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx) +{ + if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) + SiS_SetCH700x(SiS_Pr,tempbx); + else + SiS_SetCH701x(SiS_Pr,tempbx); +} + +static USHORT +SiS_GetChReg(SiS_Private *SiS_Pr, USHORT myor) +{ + USHORT tempah,temp,i; + + for(i=0; i<20; i++) { /* Do 20 attempts to read */ + if(i) { + SiS_SetStop(SiS_Pr); + SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT); + } + if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */ + tempah = SiS_Pr->SiS_DDC_DeviceAddr; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */ + if(temp) continue; /* (ERROR: no ack) */ + tempah = SiS_Pr->SiS_DDC_ReadAddr | myor; /* Write RAB (700x: | 0x80) */ + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); + if(temp) continue; /* (ERROR: no ack) */ + if (SiS_SetStart(SiS_Pr)) continue; /* Re-start */ + tempah = SiS_Pr->SiS_DDC_DeviceAddr | 0x01;/* DAB | 0x01 = Read */ + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* DAB (S0=1=read) */ + if(temp) continue; /* (ERROR: no ack) */ + tempah = SiS_ReadDDC2Data(SiS_Pr,tempah); /* Read byte */ + if(SiS_SetStop(SiS_Pr)) continue; /* Stop condition */ + SiS_Pr->SiS_ChrontelInit = 1; + return(tempah); + } + return 0xFFFF; +} + +#if 0 +#ifdef SIS300 +/* Read from Trumpion */ +static USHORT +SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx) +{ + SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB */ + SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */ + SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */ + SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */ + SiS_SetupDDCN(SiS_Pr); + SiS_Pr->SiS_DDC_ReadAddr = tempbx; + return(SiS_GetChReg(SiS_Pr,0)); +} +#endif +#endif + +/* Read from Chrontel 700x */ +/* Parameter is [Register no (S7-S0)] */ +USHORT +SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx) +{ + USHORT result; + + SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */ + + if(!(SiS_Pr->SiS_ChrontelInit)) { + SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */ + SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */ + SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */ + SiS_SetupDDCN(SiS_Pr); + } + + SiS_Pr->SiS_DDC_ReadAddr = tempbx; + + if( ((result = SiS_GetChReg(SiS_Pr,0x80)) == 0xFFFF) && + (!SiS_Pr->SiS_ChrontelInit) ) { + + SiS_Pr->SiS_DDC_Index = 0x0a; + SiS_Pr->SiS_DDC_Data = 0x80; + SiS_Pr->SiS_DDC_Clk = 0x40; + SiS_SetupDDCN(SiS_Pr); + + result = SiS_GetChReg(SiS_Pr,0x80); + } + return(result); +} + +/* Read from Chrontel 701x */ +/* Parameter is [Register no (S7-S0)] */ +USHORT +SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx) +{ + SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */ + SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */ + SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */ + SiS_SetupDDCN(SiS_Pr); + SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */ + + SiS_Pr->SiS_DDC_ReadAddr = tempbx; + + return(SiS_GetChReg(SiS_Pr,0)); +} + +/* Read from Chrontel 70xx */ +/* Parameter is [Register no (S7-S0)] */ +USHORT +SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx) +{ + if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) + return(SiS_GetCH700x(SiS_Pr, tempbx)); + else + return(SiS_GetCH701x(SiS_Pr, tempbx)); +} + +/* Our own DDC functions */ +static USHORT +SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine, + USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32) +{ + unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 }; + unsigned char flag, cr32; + USHORT temp = 0, myadaptnum = adaptnum; + + if(adaptnum != 0) { + if(!(VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0xFFFF; + if((VBFlags & VB_30xBDH) && (adaptnum == 1)) return 0xFFFF; + } + + /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */ + + SiS_Pr->SiS_ChrontelInit = 0; /* force re-detection! */ + + SiS_Pr->SiS_DDC_SecAddr = 0; + SiS_Pr->SiS_DDC_DeviceAddr = ddcdtype[DDCdatatype]; + SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_P3c4; + SiS_Pr->SiS_DDC_Index = 0x11; + flag = 0xff; + + cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32); + +#if 0 + if(VBFlags & VB_SISBRIDGE) { + if(myadaptnum == 0) { + if(!(cr32 & 0x20)) { + myadaptnum = 2; + if(!(cr32 & 0x10)) { + myadaptnum = 1; + if(!(cr32 & 0x08)) { + myadaptnum = 0; + } + } + } + } + } +#endif + + if(VGAEngine == SIS_300_VGA) { /* 300 series */ + + if(myadaptnum != 0) { + flag = 0; + if(VBFlags & VB_SISBRIDGE) { + SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port; + SiS_Pr->SiS_DDC_Index = 0x0f; + } + } + + if(!(VBFlags & VB_301)) { + if((cr32 & 0x80) && (checkcr32)) { + if(myadaptnum >= 1) { + if(!(cr32 & 0x08)) { + myadaptnum = 1; + if(!(cr32 & 0x10)) return 0xFFFF; + } + } + } + } + + temp = 4 - (myadaptnum * 2); + if(flag) temp = 0; + + } else { /* 315/330 series */ + + /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */ + + if(VBFlags & VB_SISBRIDGE) { + if(myadaptnum == 2) { + myadaptnum = 1; + } + } + + if(myadaptnum == 1) { + flag = 0; + if(VBFlags & VB_SISBRIDGE) { + SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port; + SiS_Pr->SiS_DDC_Index = 0x0f; + } + } + + if((cr32 & 0x80) && (checkcr32)) { + if(myadaptnum >= 1) { + if(!(cr32 & 0x08)) { + myadaptnum = 1; + if(!(cr32 & 0x10)) return 0xFFFF; + } + } + } + + temp = myadaptnum; + if(myadaptnum == 1) { + temp = 0; + if(VBFlags & VB_LVDS) flag = 0xff; + } + + if(flag) temp = 0; + } + + SiS_Pr->SiS_DDC_Data = 0x02 << temp; + SiS_Pr->SiS_DDC_Clk = 0x01 << temp; + + SiS_SetupDDCN(SiS_Pr); + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "DDC Port %x Index %x Shift %d\n", + SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, temp); +#endif + + return 0; +} + +static USHORT +SiS_WriteDABDDC(SiS_Private *SiS_Pr) +{ + if(SiS_SetStart(SiS_Pr)) return 0xFFFF; + if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) { + return 0xFFFF; + } + if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) { + return 0xFFFF; + } + return(0); +} + +static USHORT +SiS_PrepareReadDDC(SiS_Private *SiS_Pr) +{ + if(SiS_SetStart(SiS_Pr)) return 0xFFFF; + if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) { + return 0xFFFF; + } + return(0); +} + +static USHORT +SiS_PrepareDDC(SiS_Private *SiS_Pr) +{ + if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr); + if(SiS_PrepareReadDDC(SiS_Pr)) return(SiS_PrepareReadDDC(SiS_Pr)); + return(0); +} + +static void +SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno) +{ + SiS_SetSCLKLow(SiS_Pr); + if(yesno) { + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, + SiS_Pr->SiS_DDC_Index, + SiS_Pr->SiS_DDC_NData, + SiS_Pr->SiS_DDC_Data); + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, + SiS_Pr->SiS_DDC_Index, + SiS_Pr->SiS_DDC_NData, + 0); + } + SiS_SetSCLKHigh(SiS_Pr); +} + +static USHORT +SiS_DoProbeDDC(SiS_Private *SiS_Pr) +{ + unsigned char mask, value; + USHORT temp, ret=0; + BOOLEAN failed = FALSE; + + SiS_SetSwitchDDC2(SiS_Pr); + if(SiS_PrepareDDC(SiS_Pr)) { + SiS_SetStop(SiS_Pr); +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "Probe: Prepare failed\n"); +#endif + return(0xFFFF); + } + mask = 0xf0; + value = 0x20; + if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) { + temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0); + SiS_SendACK(SiS_Pr, 0); + if(temp == 0) { + mask = 0xff; + value = 0xff; + } else { + failed = TRUE; + ret = 0xFFFF; +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "Probe: Read 1 failed\n"); +#endif + } + } + if(failed == FALSE) { + temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0); + SiS_SendACK(SiS_Pr, 1); + temp &= mask; + if(temp == value) ret = 0; + else { + ret = 0xFFFF; +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "Probe: Read 2 failed\n"); +#endif + if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) { + if(temp == 0x30) ret = 0; + } + } + } + SiS_SetStop(SiS_Pr); + return(ret); +} + +static USHORT +SiS_ProbeDDC(SiS_Private *SiS_Pr) +{ + USHORT flag; + + flag = 0x180; + SiS_Pr->SiS_DDC_DeviceAddr = 0xa0; + if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x02; + SiS_Pr->SiS_DDC_DeviceAddr = 0xa2; + if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x08; + SiS_Pr->SiS_DDC_DeviceAddr = 0xa6; + if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10; + if(!(flag & 0x1a)) flag = 0; + return(flag); +} + +static USHORT +SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer) +{ + USHORT flag, length, i; + unsigned char chksum,gotcha; + + if(DDCdatatype > 4) return 0xFFFF; + + flag = 0; + SiS_SetSwitchDDC2(SiS_Pr); + if(!(SiS_PrepareDDC(SiS_Pr))) { + length = 127; + if(DDCdatatype != 1) length = 255; + chksum = 0; + gotcha = 0; + for(i=0; i<length; i++) { + buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0); + chksum += buffer[i]; + gotcha |= buffer[i]; + SiS_SendACK(SiS_Pr, 0); + } + buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0); + chksum += buffer[i]; + SiS_SendACK(SiS_Pr, 1); + if(gotcha) flag = (USHORT)chksum; + else flag = 0xFFFF; + } else { + flag = 0xFFFF; + } + SiS_SetStop(SiS_Pr); + return(flag); +} + +/* Our private DDC functions + + It complies somewhat with the corresponding VESA function + in arguments and return values. + + Since this is probably called before the mode is changed, + we use our pre-detected pSiS-values instead of SiS_Pr as + regards chipset and video bridge type. + + Arguments: + adaptnum: 0=CRT1(analog), 1=CRT2/LCD(digital), 2=CRT2/VGA2(analog) + CRT2 DDC is only supported on SiS301, 301B, 301C, 302B. + LCDA is CRT1, but DDC is read from CRT2 port. + DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2) + buffer: ptr to 256 data bytes which will be filled with read data. + + Returns 0xFFFF if error, otherwise + if DDCdatatype > 0: Returns 0 if reading OK (included a correct checksum) + if DDCdatatype = 0: Returns supported DDC modes + + */ +USHORT +SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine, + USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer) +{ + unsigned char sr1f,cr17=1; + USHORT result; + + if(adaptnum > 2) return 0xFFFF; + if(DDCdatatype > 4) return 0xFFFF; + if((!(VBFlags & VB_VIDEOBRIDGE)) && (adaptnum > 0)) return 0xFFFF; + if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, FALSE) == 0xFFFF) return 0xFFFF; + + sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04); + if(VGAEngine == SIS_300_VGA) { + cr17 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80; + if(!cr17) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x17,0x80); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x01); + SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03); + } + } + if((sr1f) || (!cr17)) { + SiS_WaitRetrace1(SiS_Pr); + SiS_WaitRetrace1(SiS_Pr); + SiS_WaitRetrace1(SiS_Pr); + SiS_WaitRetrace1(SiS_Pr); + } + + if(DDCdatatype == 0) { + result = SiS_ProbeDDC(SiS_Pr); + } else { + result = SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer); + if((!result) && (DDCdatatype == 1)) { + if((buffer[0] == 0x00) && (buffer[1] == 0xff) && + (buffer[2] == 0xff) && (buffer[3] == 0xff) && + (buffer[4] == 0xff) && (buffer[5] == 0xff) && + (buffer[6] == 0xff) && (buffer[7] == 0x00) && + (buffer[0x12] == 1)) { + if(adaptnum == 1) { + if(!(buffer[0x14] & 0x80)) result = 0xFFFE; + } else { + if(buffer[0x14] & 0x80) result = 0xFFFE; + } + } + } + } + SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,sr1f); + if(VGAEngine == SIS_300_VGA) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x17,0x7f,cr17); + } + return result; +} + +#ifdef LINUX_XF86 + +static BOOLEAN +checkedid1(unsigned char *buffer) +{ + /* Check header */ + if((buffer[0] != 0x00) || + (buffer[1] != 0xff) || + (buffer[2] != 0xff) || + (buffer[3] != 0xff) || + (buffer[4] != 0xff) || + (buffer[5] != 0xff) || + (buffer[6] != 0xff) || + (buffer[7] != 0x00)) + return FALSE; + + /* Check EDID version and revision */ + if((buffer[0x12] != 1) || (buffer[0x13] > 4)) return FALSE; + + /* Check week of manufacture for sanity */ + if(buffer[0x10] > 53) return FALSE; + + /* Check year of manufacture for sanity */ + if(buffer[0x11] > 40) return FALSE; + + return TRUE; +} + +static BOOLEAN +checkedid2(unsigned char *buffer) +{ + USHORT year = buffer[6] | (buffer[7] << 8); + + /* Check EDID version */ + if((buffer[0] & 0xf0) != 0x20) return FALSE; + + /* Check week of manufacture for sanity */ + if(buffer[5] > 53) return FALSE; + + /* Check year of manufacture for sanity */ + if((year != 0) && ((year < 1990) || (year > 2030))) return FALSE; + + return TRUE; +} + +/* Sense the LCD parameters (CR36, CR37) via DDC */ +/* SiS30x(B) only */ +USHORT +SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS) +{ + USHORT DDCdatatype, paneltype, flag, xres=0, yres=0; + USHORT index, myindex, lumsize, numcodes, panelvendor, panelproduct; + int maxx=0, maxy=0, prefx=0, prefy=0; + unsigned char cr37=0, seekcode; + BOOLEAN checkexpand = FALSE; + BOOLEAN havesync = FALSE; + BOOLEAN indb = FALSE; + int retry, i; + unsigned char buffer[256]; + + for(i=0; i<7; i++) SiS_Pr->CP_DataValid[i] = FALSE; + SiS_Pr->CP_HaveCustomData = FALSE; + SiS_Pr->CP_MaxX = SiS_Pr->CP_MaxY = SiS_Pr->CP_MaxClock = 0; + SiS_Pr->CP_PreferredX = SiS_Pr->CP_PreferredY = 0; + SiS_Pr->CP_PreferredIndex = -1; + SiS_Pr->CP_PrefClock = 0; + SiS_Pr->PanelSelfDetected = FALSE; + + if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0; + if(pSiS->VBFlags & VB_30xBDH) return 0; + + if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 1, 0, FALSE) == 0xFFFF) return 0; + + SiS_Pr->SiS_DDC_SecAddr = 0x00; + + /* Probe supported DA's */ + flag = SiS_ProbeDDC(SiS_Pr); +#ifdef TWDEBUG + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO, + "CRT2 DDC capabilities 0x%x\n", flag); +#endif + if(flag & 0x10) { + SiS_Pr->SiS_DDC_DeviceAddr = 0xa6; /* EDID V2 (FP) */ + DDCdatatype = 4; + } else if(flag & 0x08) { + SiS_Pr->SiS_DDC_DeviceAddr = 0xa2; /* EDID V2 (P&D-D Monitor) */ + DDCdatatype = 3; + } else if(flag & 0x02) { + SiS_Pr->SiS_DDC_DeviceAddr = 0xa0; /* EDID V1 */ + DDCdatatype = 1; + } else return 0; /* no DDC support (or no device attached) */ + + /* Read the entire EDID */ + retry = 2; + do { + if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + "CRT2: DDC read failed (attempt %d), %s\n", + (3-retry), (retry == 1) ? "giving up" : "retrying"); + retry--; + if(retry == 0) return 0xFFFF; + } else break; + } while(1); + +#ifdef TWDEBUG + for(i=0; i<256; i+=16) { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + buffer[i], buffer[i+1], buffer[i+2], buffer[i+3], + buffer[i+4], buffer[i+5], buffer[i+6], buffer[i+7], + buffer[i+8], buffer[i+9], buffer[i+10], buffer[i+11], + buffer[i+12], buffer[i+13], buffer[i+14], buffer[i+15]); + } +#endif + + /* Analyze EDID and retrieve LCD panel information */ + paneltype = 0; + switch(DDCdatatype) { + case 1: /* Analyze EDID V1 */ + /* Catch a few clear cases: */ + if(!(checkedid1(buffer))) { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + "LCD sense: EDID corrupt\n"); + return 0; + } + + if(!(buffer[0x14] & 0x80)) { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + "LCD sense: Attached display expects analog input (0x%02x)\n", + buffer[0x14]); + return 0; + } + + if((buffer[0x18] & 0x18) != 0x08) { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + "LCD sense: Warning: Attached display is not of RGB but of %s type (0x%02x)\n", + ((buffer[0x18] & 0x18) == 0x00) ? "monochrome/greyscale" : + ( ((buffer[0x18] & 0x18) == 0x10) ? "non-RGB multicolor" : + "undefined"), + buffer[0x18]); + } + + /* Now analyze the first Detailed Timing Block and see + * if the preferred timing mode is stored there. If so, + * check if this is a standard panel for which we already + * know the timing. + */ + + paneltype = Panel_Custom; + checkexpand = FALSE; + + panelvendor = buffer[9] | (buffer[8] << 8); + panelproduct = buffer[10] | (buffer[11] << 8); + + /* Overrule bogus preferred modes from database */ + if((indb = SiS_FindPanelFromDB(pSiS, panelvendor, panelproduct, &maxx, &maxy, &prefx, &prefy))) { + if(prefx) SiS_Pr->CP_PreferredX = xres = prefx; + if(prefy) SiS_Pr->CP_PreferredY = yres = prefy; + } + + if(buffer[0x18] & 0x02) { + + USHORT pclk = (buffer[0x36] | (buffer[0x37] << 8)); + USHORT phb = (buffer[0x39] | ((buffer[0x3a] & 0x0f) << 8)); + USHORT pvb = (buffer[0x3c] | ((buffer[0x3d] & 0x0f) << 8)); + + if(!xres) SiS_Pr->CP_PreferredX = xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4); + if(!yres) SiS_Pr->CP_PreferredY = yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4); + + switch(xres) { +#if 0 /* Treat as custom */ + case 800: + if(yres == 600) { + paneltype = Panel_800x600; + checkexpand = TRUE; + } + break; +#endif + case 1024: + if(yres == 768) { + paneltype = Panel_1024x768; + checkexpand = TRUE; + } + break; + case 1280: + if(yres == 1024) { + paneltype = Panel_1280x1024; + checkexpand = TRUE; + } else if(yres == 960) { + if(pSiS->VGAEngine == SIS_300_VGA) { + paneltype = Panel300_1280x960; + } else { + paneltype = Panel310_1280x960; + } + } else if(yres == 768) { + if( (pclk == 8100) && + (phb == (1688 - 1280)) && + (pvb == (802 - 768)) ) { + paneltype = Panel_1280x768; + checkexpand = FALSE; + cr37 |= 0x10; + } + } else if(yres == 800) { + if( (pclk == 6900) && + (phb == (1408 - 1280)) && + (pvb == (816 - 800)) ) { + paneltype = Panel_1280x800; + } + } + break; + case 1400: + if(pSiS->VGAEngine == SIS_315_VGA) { + if(yres == 1050) { + paneltype = Panel310_1400x1050; + checkexpand = TRUE; + } + } + break; + case 1600: + if(pSiS->VGAEngine == SIS_315_VGA) { + if(pSiS->VBFlags & VB_301C) { + if(yres == 1200) { + paneltype = Panel310_1600x1200; + checkexpand = TRUE; + } + } + } + break; + } + + /* Save sync: This is used if "Pass 1:1" is off; in this case + * we always use the panel's native mode = this "preferred mode" + * we just have been analysing. Hence, we also need its sync. + */ + if((buffer[0x47] & 0x18) == 0x18) { + cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20); + havesync = TRUE; + } else { + /* What now? There is no digital separate output timing... */ + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, + "LCD sense: Unable to retrieve Sync polarity information\n"); + cr37 |= 0xc0; /* Default */ + } + + } + + /* Check against our database; eg. Sanyo Z2 projector reports + * 1024x768 as preferred mode, although it supports 1280x720 + * natively in non-HDCP mode. Treat such wrongly reporting + * panels as custom and fixup actual maximum resolutions. + */ + if(paneltype != Panel_Custom) { + if(indb) { + paneltype = Panel_Custom; + SiS_Pr->CP_MaxX = maxx; + SiS_Pr->CP_MaxY = maxy; + /* Leave preferred unchanged (MUST contain a valid mode!) */ + } + } + + /* If we still don't know what panel this is, we take it + * as a custom panel and derive the timing data from the + * detailed timing blocks + */ + if(paneltype == Panel_Custom) { + + int i, temp, base = 0x36; + unsigned long estpack; + const unsigned short estx[] = { + 720, 720, 640, 640, 640, 640, 800, 800, + 800, 800, 832,1024,1024,1024,1024,1280, + 1152 + }; + const unsigned short esty[] = { + 400, 400, 480, 480, 480, 480, 600, 600, + 600, 600, 624, 768, 768, 768, 768,1024, + 870 + }; + const int estclk[] = { + 0, 0, 25100, 0, 31500, 31500, 36100, 40000, + 50100, 49500, 0, 0, 65100, 75200, 78700,135200, + 0 + }; + + paneltype = 0; + SiS_Pr->CP_Supports64048075 = TRUE; + + /* Find the maximum resolution */ + + /* 1. From Established timings */ + estpack = (buffer[0x23] << 9) | (buffer[0x24] << 1) | ((buffer[0x25] >> 7) & 0x01); + for(i=16; i>=0; i--) { + if(estpack & (1 << i)) { + if(estx[16 - i] > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = estx[16 - i]; + if(esty[16 - i] > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = esty[16 - i]; + if(estclk[16 - i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = estclk[16 - i]; + } + } + + /* By default we drive the LCD at 75Hz in 640x480 mode; if + * the panel does not provide this mode, use 60hz + */ + if(!(buffer[0x23] & 0x04)) SiS_Pr->CP_Supports64048075 = FALSE; + + /* 2. From Standard Timings */ + for(i=0x26; i < 0x36; i+=2) { + if((buffer[i] != 0x01) && (buffer[i+1] != 0x01)) { + temp = (buffer[i] + 31) * 8; + if(temp > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = temp; + switch((buffer[i+1] & 0xc0) >> 6) { + case 0x03: temp = temp * 9 / 16; break; + case 0x02: temp = temp * 4 / 5; break; + case 0x01: temp = temp * 3 / 4; break; + } + if(temp > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = temp; + } + } + + /* Now extract the Detailed Timings and convert them into modes */ + + for(i = 0; i < 4; i++, base += 18) { + + /* Is this a detailed timing block or a monitor descriptor? */ + if(buffer[base] || buffer[base+1] || buffer[base+2]) { + + xres = buffer[base+2] | ((buffer[base+4] & 0xf0) << 4); + yres = buffer[base+5] | ((buffer[base+7] & 0xf0) << 4); + + SiS_Pr->CP_HDisplay[i] = xres; + SiS_Pr->CP_HSyncStart[i] = xres + (buffer[base+8] | ((buffer[base+11] & 0xc0) << 2)); + SiS_Pr->CP_HSyncEnd[i] = SiS_Pr->CP_HSyncStart[i] + (buffer[base+9] | ((buffer[base+11] & 0x30) << 4)); + SiS_Pr->CP_HTotal[i] = xres + (buffer[base+3] | ((buffer[base+4] & 0x0f) << 8)); + SiS_Pr->CP_HBlankStart[i] = xres + 1; + SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i]; + + SiS_Pr->CP_VDisplay[i] = yres; + SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[base+10] & 0xf0) >> 4) | ((buffer[base+11] & 0x0c) << 2)); + SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[base+10] & 0x0f) | ((buffer[base+11] & 0x03) << 4)); + SiS_Pr->CP_VTotal[i] = yres + (buffer[base+6] | ((buffer[base+7] & 0x0f) << 8)); + SiS_Pr->CP_VBlankStart[i] = yres + 1; + SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i]; + + SiS_Pr->CP_Clock[i] = (buffer[base] | (buffer[base+1] << 8)) * 10; + + SiS_Pr->CP_DataValid[i] = TRUE; + + /* Sort out invalid timings, interlace and too high clocks */ + if((SiS_Pr->CP_HDisplay[i] & 7) || + (SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i]) || + (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i]) || + (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i]) || + (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i]) || + (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i]) || + (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i]) || + (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i]) || + (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i]) || + (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i]) || + (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i]) || + (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i]) || + (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i]) || + (((pSiS->VBFlags & VB_301C) && (SiS_Pr->CP_Clock[i] > 162500)) || + ((!(pSiS->VBFlags & VB_301C)) && + ((SiS_Pr->CP_Clock[i] > 108200) || (SiS_Pr->CP_VDisplay[i] > 1024) || + (SiS_Pr->CP_HDisplay[i] > 1600)))) || + (buffer[base+17] & 0x80)) { + + SiS_Pr->CP_DataValid[i] = FALSE; + + } else { + + SiS_Pr->CP_HaveCustomData = TRUE; + + if(xres > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = xres; + if(yres > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = yres; + if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i]; + + if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) { + SiS_Pr->CP_PreferredIndex = i; + SiS_MakeClockRegs(pSiS->pScrn, SiS_Pr->CP_Clock[i], &SiS_Pr->CP_PrefSR2B, &SiS_Pr->CP_PrefSR2C); + SiS_Pr->CP_PrefClock = (SiS_Pr->CP_Clock[i] / 1000) + 1; + } + + /* Extract the sync polarisation information. This only works + * if the Flags indicate a digital separate output. + */ + if((buffer[base+17] & 0x18) == 0x18) { + SiS_Pr->CP_HSync_P[i] = (buffer[base+17] & 0x02) ? TRUE : FALSE; + SiS_Pr->CP_VSync_P[i] = (buffer[base+17] & 0x04) ? TRUE : FALSE; + SiS_Pr->CP_SyncValid[i] = TRUE; + if((i == SiS_Pr->CP_PreferredIndex) && (!havesync)) { + cr37 |= ((((buffer[base+17] & 0x06) ^ 0x06) << 5) | 0x20); + havesync = TRUE; + } + } else { + SiS_Pr->CP_SyncValid[i] = FALSE; + } + + } + + } else if((!buffer[base]) && (!buffer[base+1]) && (!buffer[base+2]) && (!buffer[base+4])) { + + /* Maximum pixclock from Monitor Range Limits */ + if((buffer[base+3] == 0xfd) && (buffer[base+9] != 0xff)) { + int maxclk = buffer[base+9] * 10; + /* More than 170 is not supported anyway */ + if(maxclk <= 170) SiS_Pr->CP_MaxClock = maxclk * 1000; + } + + } + + } + + if(SiS_Pr->CP_MaxX && SiS_Pr->CP_MaxY) { + paneltype = Panel_Custom; + checkexpand = FALSE; + cr37 |= 0x10; + SiS_Pr->CP_Vendor = panelvendor; + SiS_Pr->CP_Product = panelproduct; + } + + } + + if(paneltype && checkexpand) { + /* If any of the Established low-res modes is supported, the + * panel can scale automatically. For 800x600 panels, we only + * check the even lower ones. + */ + if(paneltype == Panel_800x600) { + if(buffer[0x23] & 0xfc) cr37 |= 0x10; + } else { + if(buffer[0x23]) cr37 |= 0x10; + } + } + + break; + + case 3: /* Analyze EDID V2 */ + case 4: + index = 0; + + if(!(checkedid2(buffer))) { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + "LCD sense: EDID corrupt\n"); + return 0; + } + + if((buffer[0x41] & 0x0f) == 0x03) { + index = 0x42 + 3; + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + "LCD sense: Display supports TMDS input on primary interface\n"); + } else if((buffer[0x41] & 0xf0) == 0x30) { + index = 0x46 + 3; + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + "LCD sense: Display supports TMDS input on secondary interface\n"); + } else { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + "LCD sense: Display does not support TMDS video interface (0x%02x)\n", + buffer[0x41]); + return 0; + } + + SiS_Pr->CP_Vendor = panelvendor = buffer[2] | (buffer[1] << 8); + SiS_Pr->CP_Product = panelproduct = buffer[3] | (buffer[4] << 8); + + paneltype = Panel_Custom; + SiS_Pr->CP_MaxX = SiS_Pr->CP_PreferredX = xres = buffer[0x76] | (buffer[0x77] << 8); + SiS_Pr->CP_MaxY = SiS_Pr->CP_PreferredY = yres = buffer[0x78] | (buffer[0x79] << 8); + + switch(xres) { +#if 0 + case 800: + if(yres == 600) { + paneltype = Panel_800x600; + checkexpand = TRUE; + } + break; +#endif + case 1024: + if(yres == 768) { + paneltype = Panel_1024x768; + checkexpand = TRUE; + } + break; + case 1280: + if(yres == 960) { + if(pSiS->VGAEngine == SIS_315_VGA) { + paneltype = Panel310_1280x960; + } else { + paneltype = Panel300_1280x960; + } + } else if(yres == 1024) { + paneltype = Panel_1280x1024; + checkexpand = TRUE; + } + /* 1280x768 treated as custom here */ + break; + case 1400: + if(pSiS->VGAEngine == SIS_315_VGA) { + if(yres == 1050) { + paneltype = Panel310_1400x1050; + checkexpand = TRUE; + } + } + break; + case 1600: + if(pSiS->VGAEngine == SIS_315_VGA) { + if(pSiS->VBFlags & VB_301C) { + if(yres == 1200) { + paneltype = Panel310_1600x1200; + checkexpand = TRUE; + } + } + } + break; + } + + /* Determine if RGB18 or RGB24 */ + if(index) { + if((buffer[index] == 0x20) || (buffer[index] == 0x34)) { + cr37 |= 0x01; + } + } + + if(checkexpand) { + /* TODO - for now, we let the panel scale */ + cr37 |= 0x10; + } + + /* Now seek 4-Byte Timing codes and extract sync pol info */ + index = 0x80; + if(buffer[0x7e] & 0x20) { /* skip Luminance Table (if provided) */ + lumsize = buffer[0x80] & 0x1f; + if(buffer[0x80] & 0x80) lumsize *= 3; + lumsize++; /* luminance header byte */ + index += lumsize; + } +#if 0 /* "pixel rate" = pixel clock? */ + if(buffer[0x7e] & 0x1c) { + for(i=0; i<((buffer[0x7e] & 0x1c) >> 2); i++) { + if(buffer[index + (i*8) + 6] && (buffer[index + (i*8) + 7] & 0x0f)) { + int clk = (buffer[index + (i*8) + 6] | ((buffer[index + (i*8) + 7] & 0x0f) << 4)) * 1000; + if(clk > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = clk; + } + } + } +#endif + index += (((buffer[0x7e] & 0x1c) >> 2) * 8); /* skip Frequency Ranges */ + if(buffer[0x7e] & 0x03) { + for(i=0; i<(buffer[0x7e] & 0x03); i++) { + if((buffer[index + (i*27) + 9]) || (buffer[index + (i*27) + 10])) { + int clk = ((buffer[index + (i*27) + 9]) | ((buffer[index + (i*27) + 9]) << 8)) * 10; + if(clk > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = clk; + } + } + } + index += ((buffer[0x7e] & 0x03) * 27); /* skip Detailed Range Limits */ + numcodes = (buffer[0x7f] & 0xf8) >> 3; + if(numcodes) { + myindex = index; + seekcode = (xres - 256) / 16; + for(i=0; i<numcodes; i++) { + if(buffer[myindex] == seekcode) break; + myindex += 4; + } + if(buffer[myindex] == seekcode) { + cr37 |= ((((buffer[myindex + 1] & 0x0c) ^ 0x0c) << 4) | 0x20); + havesync = TRUE; + } else { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, + "LCD sense: Unable to retrieve Sync polarity information\n"); + } + } else { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING, + "LCD sense: Unable to retrieve Sync polarity information\n"); + } + + /* Check against our database; Eg. Sanyo projector reports + * 1024x768 in non-HDPC mode, although it supports 1280x720. + * Treat such wrongly reporting panels as custom. + */ + if(paneltype != Panel_Custom) { + int maxx, maxy, prefx, prefy; + if((SiS_FindPanelFromDB(pSiS, panelvendor, panelproduct, &maxx, &maxy, &prefx, &prefy))) { + paneltype = Panel_Custom; + SiS_Pr->CP_MaxX = maxx; + SiS_Pr->CP_MaxY = maxy; + cr37 |= 0x10; + /* Leave preferred unchanged (MUST be a valid mode!) */ + } + } + + /* Now seek the detailed timing descriptions for custom panels */ + if(paneltype == Panel_Custom) { + + SiS_Pr->CP_Supports64048075 = TRUE; + + index += (numcodes * 4); + numcodes = buffer[0x7f] & 0x07; + for(i=0; i<numcodes; i++, index += 18) { + xres = buffer[index+2] | ((buffer[index+4] & 0xf0) << 4); + yres = buffer[index+5] | ((buffer[index+7] & 0xf0) << 4); + + SiS_Pr->CP_HDisplay[i] = xres; + SiS_Pr->CP_HSyncStart[i] = xres + (buffer[index+8] | ((buffer[index+11] & 0xc0) << 2)); + SiS_Pr->CP_HSyncEnd[i] = SiS_Pr->CP_HSyncStart[i] + (buffer[index+9] | ((buffer[index+11] & 0x30) << 4)); + SiS_Pr->CP_HTotal[i] = xres + (buffer[index+3] | ((buffer[index+4] & 0x0f) << 8)); + SiS_Pr->CP_HBlankStart[i] = xres + 1; + SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i]; + + SiS_Pr->CP_VDisplay[i] = yres; + SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[index+10] & 0xf0) >> 4) | ((buffer[index+11] & 0x0c) << 2)); + SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[index+10] & 0x0f) | ((buffer[index+11] & 0x03) << 4)); + SiS_Pr->CP_VTotal[i] = yres + (buffer[index+6] | ((buffer[index+7] & 0x0f) << 8)); + SiS_Pr->CP_VBlankStart[i] = yres + 1; + SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i]; + + SiS_Pr->CP_Clock[i] = (buffer[index] | (buffer[index+1] << 8)) * 10; + + SiS_Pr->CP_DataValid[i] = TRUE; + + if((SiS_Pr->CP_HDisplay[i] & 7) || + (SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i]) || + (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i]) || + (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i]) || + (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i]) || + (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i]) || + (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i]) || + (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i]) || + (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i]) || + (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i]) || + (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i]) || + (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i]) || + (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i]) || + (((pSiS->VBFlags & VB_301C) && (SiS_Pr->CP_Clock[i] > 162500)) || + ((!(pSiS->VBFlags & VB_301C)) && + ((SiS_Pr->CP_Clock[i] > 108200) || (SiS_Pr->CP_VDisplay[i] > 1024)))) || + (buffer[index + 17] & 0x80)) { + + SiS_Pr->CP_DataValid[i] = FALSE; + + } else { + + SiS_Pr->CP_HaveCustomData = TRUE; + + if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i]; + + if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) { + SiS_Pr->CP_PreferredIndex = i; + SiS_MakeClockRegs(pSiS->pScrn, SiS_Pr->CP_Clock[i], &SiS_Pr->CP_PrefSR2B, &SiS_Pr->CP_PrefSR2C); + SiS_Pr->CP_PrefClock = (SiS_Pr->CP_Clock[i] / 1000) + 1; + if(!havesync) { + cr37 |= ((((buffer[index + 17] & 0x06) ^ 0x06) << 5) | 0x20); + havesync = TRUE; + } + } + + SiS_Pr->CP_HSync_P[i] = (buffer[index + 17] & 0x02) ? TRUE : FALSE; + SiS_Pr->CP_VSync_P[i] = (buffer[index + 17] & 0x04) ? TRUE : FALSE; + SiS_Pr->CP_SyncValid[i] = TRUE; + + } + } + + cr37 |= 0x10; + + } + + break; + + } + + /* 1280x960 panels are always RGB24, unable to scale and use + * high active sync polarity + */ + if(pSiS->VGAEngine == SIS_315_VGA) { + if(paneltype == Panel310_1280x960) cr37 &= 0x0e; + } else { + if(paneltype == Panel300_1280x960) cr37 &= 0x0e; + } + + for(i = 0; i < 7; i++) { + if(SiS_Pr->CP_DataValid[i]) { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + "Non-standard LCD/DVI-D timing data no. %d:\n", i); + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + " HDisplay %d HSync %d HSyncEnd %d HTotal %d\n", + SiS_Pr->CP_HDisplay[i], SiS_Pr->CP_HSyncStart[i], + SiS_Pr->CP_HSyncEnd[i], SiS_Pr->CP_HTotal[i]); + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + " VDisplay %d VSync %d VSyncEnd %d VTotal %d\n", + SiS_Pr->CP_VDisplay[i], SiS_Pr->CP_VSyncStart[i], + SiS_Pr->CP_VSyncEnd[i], SiS_Pr->CP_VTotal[i]); + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + " Pixel clock: %3.3fMhz\n", (float)SiS_Pr->CP_Clock[i] / 1000); + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO, + " To use this, add \"%dx%d\" to the list of Modes in the Screen section\n", + SiS_Pr->CP_HDisplay[i], + SiS_Pr->CP_VDisplay[i]); + } + } + + if(paneltype) { + if(!SiS_Pr->CP_PreferredX) SiS_Pr->CP_PreferredX = SiS_Pr->CP_MaxX; + if(!SiS_Pr->CP_PreferredY) SiS_Pr->CP_PreferredY = SiS_Pr->CP_MaxY; + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x08); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,paneltype); + cr37 &= 0xf1; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0x0c,cr37); + SiS_Pr->PanelSelfDetected = TRUE; +#ifdef TWDEBUG + xf86DrvMsgVerb(pSiS->pScrn->scrnIndex, X_PROBED, 3, + "LCD sense: [DDC LCD results: 0x%02x, 0x%02x]\n", paneltype, cr37); +#endif + } else { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x32,~0x08); + SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,0x00); + } + return 0; +} + +USHORT +SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS) +{ + USHORT DDCdatatype,flag; + BOOLEAN foundcrt = FALSE; + int retry; + unsigned char buffer[256]; + + if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0; + + if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2, 0, FALSE) == 0xFFFF) return 0; + + SiS_Pr->SiS_DDC_SecAddr = 0x00; + + /* Probe supported DA's */ + flag = SiS_ProbeDDC(SiS_Pr); + if(flag & 0x10) { + SiS_Pr->SiS_DDC_DeviceAddr = 0xa6; /* EDID V2 (FP) */ + DDCdatatype = 4; + } else if(flag & 0x08) { + SiS_Pr->SiS_DDC_DeviceAddr = 0xa2; /* EDID V2 (P&D-D Monitor) */ + DDCdatatype = 3; + } else if(flag & 0x02) { + SiS_Pr->SiS_DDC_DeviceAddr = 0xa0; /* EDID V1 */ + DDCdatatype = 1; + } else { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + "VGA2 sense: Do DDC answer\n"); + return 0; /* no DDC support (or no device attached) */ + } + + /* Read the entire EDID */ + retry = 2; + do { + if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED, + "VGA2 sense: DDC read failed (attempt %d), %s\n", + (3-retry), (retry == 1) ? "giving up" : "retrying"); + retry--; + if(retry == 0) return 0xFFFF; + } else break; + } while(1); + + /* Analyze EDID. We don't have many chances to + * distinguish a flat panel from a CRT... + */ + switch(DDCdatatype) { + case 1: + if(!(checkedid1(buffer))) { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR, + "VGA2 sense: EDID corrupt\n"); + return 0; + } + if(buffer[0x14] & 0x80) { /* Display uses digital input */ + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR, + "VGA2 sense: Attached display expects digital input\n"); + return 0; + } + SiS_Pr->CP_Vendor = buffer[9] | (buffer[8] << 8); + SiS_Pr->CP_Product = buffer[10] | (buffer[11] << 8); + foundcrt = TRUE; + break; + case 3: + case 4: + if(!(checkedid2(buffer))) { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR, + "VGA2 sense: EDID corrupt\n"); + return 0; + } + if( ((buffer[0x41] & 0x0f) != 0x01) && /* Display does not support analog input */ + ((buffer[0x41] & 0x0f) != 0x02) && + ((buffer[0x41] & 0xf0) != 0x10) && + ((buffer[0x41] & 0xf0) != 0x20) ) { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR, + "VGA2 sense: Attached display does not support analog input (0x%02x)\n", + buffer[0x41]); + return 0; + } + SiS_Pr->CP_Vendor = buffer[2] | (buffer[1] << 8); + SiS_Pr->CP_Product = buffer[3] | (buffer[4] << 8); + foundcrt = TRUE; + break; + } + + if(foundcrt) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x10); + } + return(0); +} + +#endif + +void +SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh) +{ + USHORT tempbl; + + tempbl = SiS_GetCH70xx(SiS_Pr,(tempax & 0x00FF)); + tempbl = (((tempbl & tempbh) << 8) | tempax); + SiS_SetCH70xx(SiS_Pr,tempbl); +} + +/* Generic I2C functions for Chrontel & DDC --------- */ + +static void +SiS_SetSwitchDDC2(SiS_Private *SiS_Pr) +{ + SiS_SetSCLKHigh(SiS_Pr); + SiS_WaitRetrace1(SiS_Pr); + + SiS_SetSCLKLow(SiS_Pr); + SiS_WaitRetrace1(SiS_Pr); +} + +USHORT +SiS_ReadDDC1Bit(SiS_Private *SiS_Pr) +{ + SiS_WaitRetrace1(SiS_Pr); + return((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1); +} + +/* Set I2C start condition */ +/* This is done by a SD high-to-low transition while SC is high */ +static USHORT +SiS_SetStart(SiS_Private *SiS_Pr) +{ + if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */ + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, + SiS_Pr->SiS_DDC_Index, + SiS_Pr->SiS_DDC_NData, + SiS_Pr->SiS_DDC_Data); /* SD->high */ + if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */ + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, + SiS_Pr->SiS_DDC_Index, + SiS_Pr->SiS_DDC_NData, + 0x00); /* SD->low = start condition */ + if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->low) */ + return 0; +} + +/* Set I2C stop condition */ +/* This is done by a SD low-to-high transition while SC is high */ +static USHORT +SiS_SetStop(SiS_Private *SiS_Pr) +{ + if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */ + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, + SiS_Pr->SiS_DDC_Index, + SiS_Pr->SiS_DDC_NData, + 0x00); /* SD->low */ + if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */ + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, + SiS_Pr->SiS_DDC_Index, + SiS_Pr->SiS_DDC_NData, + SiS_Pr->SiS_DDC_Data); /* SD->high = stop condition */ + if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->high) */ + return 0; +} + +/* Write 8 bits of data */ +static USHORT +SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax) +{ + USHORT i,flag,temp; + + flag = 0x80; + for(i=0; i<8; i++) { + SiS_SetSCLKLow(SiS_Pr); /* SC->low */ + if(tempax & flag) { + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, + SiS_Pr->SiS_DDC_Index, + SiS_Pr->SiS_DDC_NData, + SiS_Pr->SiS_DDC_Data); /* Write bit (1) to SD */ + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, + SiS_Pr->SiS_DDC_Index, + SiS_Pr->SiS_DDC_NData, + 0x00); /* Write bit (0) to SD */ + } + SiS_SetSCLKHigh(SiS_Pr); /* SC->high */ + flag >>= 1; + } + temp = SiS_CheckACK(SiS_Pr); /* Check acknowledge */ + return(temp); +} + +static USHORT +SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax) +{ + USHORT i,temp,getdata; + + getdata=0; + for(i=0; i<8; i++) { + getdata <<= 1; + SiS_SetSCLKLow(SiS_Pr); + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, + SiS_Pr->SiS_DDC_Index, + SiS_Pr->SiS_DDC_NData, + SiS_Pr->SiS_DDC_Data); + SiS_SetSCLKHigh(SiS_Pr); + temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); + if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01; + } + return(getdata); +} + +static USHORT +SiS_SetSCLKLow(SiS_Private *SiS_Pr) +{ + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, + SiS_Pr->SiS_DDC_Index, + SiS_Pr->SiS_DDC_NClk, + 0x00); /* SetSCLKLow() */ + SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT); + return 0; +} + +static USHORT +SiS_SetSCLKHigh(SiS_Private *SiS_Pr) +{ + USHORT temp, watchdog=1000; + + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, + SiS_Pr->SiS_DDC_Index, + SiS_Pr->SiS_DDC_NClk, + SiS_Pr->SiS_DDC_Clk); /* SetSCLKHigh() */ + do { + temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); + } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog); + if (!watchdog) { +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "SetClkHigh failed\n"); +#endif + return 0xFFFF; + } + SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT); + return 0; +} + +/* Check I2C acknowledge */ +/* Returns 0 if ack ok, non-0 if ack not ok */ +static USHORT +SiS_CheckACK(SiS_Private *SiS_Pr) +{ + USHORT tempah; + + SiS_SetSCLKLow(SiS_Pr); /* (SC->low) */ + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, + SiS_Pr->SiS_DDC_Index, + SiS_Pr->SiS_DDC_NData, + SiS_Pr->SiS_DDC_Data); /* (SD->high) */ + SiS_SetSCLKHigh(SiS_Pr); /* SC->high = clock impulse for ack */ + tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */ + SiS_SetSCLKLow(SiS_Pr); /* SC->low = end of clock impulse */ + if(tempah & SiS_Pr->SiS_DDC_Data) return(1); /* Ack OK if bit = 0 */ + else return(0); +} + +/* End of I2C functions ----------------------- */ + + +/* =============== SiS 315/330 O.E.M. ================= */ + +#ifdef SIS315H + +static USHORT +GetRAMDACromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT romptr; + + if(HwInfo->jChipType < SIS_330) { + romptr = SISGETROMW(0x128); + if(SiS_Pr->SiS_VBType & VB_SIS301B302B) + romptr = SISGETROMW(0x12a); + } else { + romptr = SISGETROMW(0x1a8); + if(SiS_Pr->SiS_VBType & VB_SIS301B302B) + romptr = SISGETROMW(0x1aa); + } + return(romptr); +} + +static USHORT +GetLCDromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT romptr; + + if(HwInfo->jChipType < SIS_330) { + romptr = SISGETROMW(0x120); + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) + romptr = SISGETROMW(0x122); + } else { + romptr = SISGETROMW(0x1a0); + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) + romptr = SISGETROMW(0x1a2); + } + return(romptr); +} + +static USHORT +GetTVromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT romptr; + + if(HwInfo->jChipType < SIS_330) { + romptr = SISGETROMW(0x114); + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) + romptr = SISGETROMW(0x11a); + } else { + romptr = SISGETROMW(0x194); + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) + romptr = SISGETROMW(0x19a); + } + return(romptr); +} + +static USHORT +GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + USHORT index; + + if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) { + if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) { + if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) { + index >>= 4; + index *= 3; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2; + else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++; + return index; + } + } + } + + index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F; + if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) index -= 5; + else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6; + index--; + index *= 3; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2; + else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++; + return index; +} + +static USHORT +GetLCDPtrIndex(SiS_Private *SiS_Pr) +{ + USHORT index; + + index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2; + else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++; + return index; +} + +static USHORT +GetTVPtrIndex(SiS_Private *SiS_Pr) +{ + USHORT index; + + index = 0; + if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0; + + index <<= 1; + + if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && + (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) { + index++; + } + + return index; +} + +static ULONG +GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme) +{ + USHORT index = 0, temp = 0; + + if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1; + if(SiS_Pr->SiS_TVMode & TVSetPALM) index = 2; + if(SiS_Pr->SiS_TVMode & TVSetPALN) index = 3; + if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 6; + if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) { + index = 4; + if(SiS_Pr->SiS_TVMode & TVSetPALM) index++; + if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7; + } + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || + (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) { + index += addme; + temp++; + } + temp += 0x0100; + } + return(ULONG)(index | (temp << 16)); +} + +static ULONG +GetOEMTVPtr661_2_OLD(SiS_Private *SiS_Pr) +{ + return(GetOEMTVPtr661_2_GEN(SiS_Pr, 8)); +} + +#if 0 +static ULONG +GetOEMTVPtr661_2_NEW(SiS_Private *SiS_Pr) +{ + return(GetOEMTVPtr661_2_GEN(SiS_Pr, 6)); +} +#endif + +static int +GetOEMTVPtr661(SiS_Private *SiS_Pr) +{ + int index = 0; + + if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 2; + if(SiS_Pr->SiS_ROMNew) { + if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4; + if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6; + if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8; + if(SiS_Pr->SiS_TVMode & TVSetHiVision) index = 10; + } else { + if(SiS_Pr->SiS_TVMode & TVSetHiVision) index = 4; + if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6; + if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8; + if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10; + } + + if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++; + + return index; +} + +static void +SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT delay=0,index,myindex,temp,romptr=0; + BOOLEAN dochiptest = TRUE; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf); + } else { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f); + } + + /* Find delay (from ROM, internal tables, PCI subsystem) */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { /* ------------ VGA */ + + if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) { + romptr = GetRAMDACromptr(SiS_Pr, HwInfo); + } + if(romptr) delay = ROMAddr[romptr]; + else { + delay = 0x04; + if(SiS_Pr->SiS_VBType & VB_SIS301B302B) { + if(IS_SIS650) { + delay = 0x0a; + } else if(IS_SIS740) { + delay = 0x00; + } else if(HwInfo->jChipType < SIS_330) { + delay = 0x0c; + } else { + delay = 0x0c; + } + } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + delay = 0x00; + } + } + + } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) { /* ---------- LCD/LCDA */ + + BOOLEAN gotitfrompci = FALSE; + + /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->PDC != -1) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f)); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7)); + return; + } + } else { + if(SiS_Pr->PDCA != -1) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0)); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6)); + return; + } + } + + /* Custom Panel? */ + + if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + delay = 0x00; + if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) { + delay = 0x20; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay); + } else { + delay = 0x0c; + if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x03; + else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + if(IS_SIS740) delay = 0x01; + else delay = 0x03; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay); + } + return; + } + + /* This is a piece of typical SiS crap: They code the OEM LCD + * delay into the code, at no defined place in the BIOS. + * We now have to start doing a PCI subsystem check here. + */ + + switch(SiS_Pr->SiS_CustomT) { + case CUT_COMPAQ1280: + case CUT_COMPAQ12802: + if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) { + gotitfrompci = TRUE; + dochiptest = FALSE; + delay = 0x03; + } + break; + case CUT_CLEVO1400: + case CUT_CLEVO14002: + gotitfrompci = TRUE; + dochiptest = FALSE; + delay = 0x02; + break; + case CUT_CLEVO1024: + case CUT_CLEVO10242: + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + gotitfrompci = TRUE; + dochiptest = FALSE; + delay = 0x33; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay); + delay &= 0x0f; + } + break; + } + + /* Could we find it through the PCI ID? If no, use ROM or table */ + + if(!gotitfrompci) { + + index = GetLCDPtrIndexBIOS(SiS_Pr, HwInfo); + myindex = GetLCDPtrIndex(SiS_Pr); + + if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) { + + if(SiS_IsNotM650orLater(SiS_Pr, HwInfo)) { + + if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) { + /* Always use the second pointer on 650; some BIOSes */ + /* still carry old 301 data at the first location */ + /* romptr = SISGETROMW(0x120); */ + /* if(SiS_Pr->SiS_VBType & VB_SIS302LV) */ + romptr = SISGETROMW(0x122); + if(!romptr) return; + delay = ROMAddr[(romptr + index)]; + } else { + delay = SiS310_LCDDelayCompensation_650301LV[myindex]; + } + + } else { + + delay = SiS310_LCDDelayCompensation_651301LV[myindex]; + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) + delay = SiS310_LCDDelayCompensation_651302LV[myindex]; + + } + + } else if(SiS_Pr->SiS_UseROM && + (!(SiS_Pr->SiS_ROMNew)) && + (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) && + (SiS_Pr->SiS_LCDResInfo != Panel_1280x768) && + (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)) { + + /* Data for 1280x1024 wrong in 301B BIOS */ + romptr = GetLCDromptr(SiS_Pr, HwInfo); + if(!romptr) return; + delay = ROMAddr[(romptr + index)]; + + } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + + if(IS_SIS740) delay = 0x03; + else delay = 0x00; + + } else { + + delay = SiS310_LCDDelayCompensation_301[myindex]; + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + if(IS_SIS740) delay = 0x01; + else if(HwInfo->jChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex]; + else delay = SiS310_LCDDelayCompensation_650301LV[myindex]; + } else if(SiS_Pr->SiS_VBType & VB_SIS301C) { + if(IS_SIS740) delay = 0x01; /* ? */ + else delay = 0x03; + } else if(SiS_Pr->SiS_VBType & VB_SIS301B302B) { + if(IS_SIS740) delay = 0x01; + else delay = SiS310_LCDDelayCompensation_3xx301B[myindex]; + } + + } + + } /* got it from PCI */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0)); + dochiptest = FALSE; + } + + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* ------------ TV */ + + index = GetTVPtrIndex(SiS_Pr); + + if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) { + + if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) { + + if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) { + /* Always use the second pointer on 650; some BIOSes */ + /* still carry old 301 data at the first location */ + /* romptr = SISGETROMW(0x114); */ + /* if(SiS_Pr->SiS_VBType & VB_SIS302LV) */ + romptr = SISGETROMW(0x11a); + if(!romptr) return; + delay = ROMAddr[romptr + index]; + + } else { + + delay = SiS310_TVDelayCompensation_301B[index]; + + } + + } else { + + switch(SiS_Pr->SiS_CustomT) { + case CUT_COMPAQ1280: + case CUT_COMPAQ12802: + case CUT_CLEVO1400: + case CUT_CLEVO14002: + delay = 0x02; + dochiptest = FALSE; + break; + case CUT_CLEVO1024: + case CUT_CLEVO10242: + delay = 0x03; + dochiptest = FALSE; + break; + default: + delay = SiS310_TVDelayCompensation_651301LV[index]; + if(SiS_Pr->SiS_VBType & VB_SIS302LV) { + delay = SiS310_TVDelayCompensation_651302LV[index]; + } + } + } + + } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) { + + romptr = GetTVromptr(SiS_Pr, HwInfo); + if(!romptr) return; + delay = ROMAddr[romptr + index]; + + } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + + delay = SiS310_TVDelayCompensation_LVDS[index]; + + } else { + + delay = SiS310_TVDelayCompensation_301[index]; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(IS_SIS740) { + delay = SiS310_TVDelayCompensation_740301B[index]; + /* LV: use 301 data? BIOS bug? */ + } else { + delay = SiS310_TVDelayCompensation_301B[index]; + if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02; + } + } + + } + + if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) { + delay &= 0x0f; + dochiptest = FALSE; + } + + } else return; + + /* Write delay */ + + if(SiS_Pr->SiS_VBType & VB_SISVB) { + + if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && dochiptest) { + + temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4; + if(temp == 8) { /* 1400x1050 BIOS (COMPAL) */ + delay &= 0x0f; + delay |= 0xb0; + } else if(temp == 6) { + delay &= 0x0f; + delay |= 0xc0; + } else if(temp > 7) { /* 1280x1024 BIOS (which one?) */ + delay = 0x35; + } + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay); + + } else { + + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay); + + } + + } else { /* LVDS */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay); + } else { + if(IS_SIS650 && (SiS_Pr->SiS_IF_DEF_CH70xx != 0)) { + delay <<= 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,delay); + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay); + } + } + + } + +} + +static void +SetAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT index,temp,temp1,romptr=0; + + if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return; + + if(ModeNo<=0x13) + index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex; + else + index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex; + + temp = GetTVPtrIndex(SiS_Pr); + temp >>= 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */ + temp1 = temp; + + if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) { + if(HwInfo->jChipType >= SIS_661) { + temp1 = GetOEMTVPtr661(SiS_Pr); + temp1 >>= 1; + romptr = SISGETROMW(0x260); + if(HwInfo->jChipType >= SIS_760) { + romptr = SISGETROMW(0x360); + } + } else if(HwInfo->jChipType >= SIS_330) { + romptr = SISGETROMW(0x192); + } else { + romptr = SISGETROMW(0x112); + } + } + + if(romptr) { + temp1 <<= 1; + temp = ROMAddr[romptr + temp1 + index]; + } else { + temp = SiS310_TVAntiFlick1[temp][index]; + } + temp <<= 4; + + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp); /* index 0A D[6:4] */ +} + +static void +SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT index,temp,temp1,romptr=0; + + temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */ + + if(ModeNo <= 0x13) + index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex; + else + index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex; + + if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) { + if(HwInfo->jChipType >= SIS_661) { + romptr = SISGETROMW(0x26c); + if(HwInfo->jChipType >= SIS_760) { + romptr = SISGETROMW(0x36c); + } + temp1 = GetOEMTVPtr661(SiS_Pr); + temp1 >>= 1; + } else if(HwInfo->jChipType >= SIS_330) { + romptr = SISGETROMW(0x1a4); + } else { + romptr = SISGETROMW(0x124); + } + } + + if(romptr) { + temp1 <<= 1; + temp = ROMAddr[romptr + temp1 + index]; + } else { + temp = SiS310_TVEdge1[temp][index]; + } + temp <<= 5; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp); /* index 0A D[7:5] */ +} + +static void +SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT index, temp, i, j; + + if(ModeNo <= 0x13) { + index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex; + } else { + index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex; + } + + temp = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */ + + if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 1; /* NTSC-J uses PAL */ + else if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 3; /* PAL-M */ + else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 4; /* PAL-N */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1; /* HiVision uses PAL */ + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + for(i=0x35, j=0; i<=0x38; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]); + } + for(i=0x48; i<=0x4A; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]); + } + } else { + for(i=0x35, j=0; i<=0x38; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]); + } + } +} + +static void +SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT index,temp,i,j,resinfo,romptr=0; + ULONG lindex; + + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return; + + /* NTSC-J data not in BIOS, and already set in SetGroup2 */ + if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return; + + if((HwInfo->jChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) { + lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff; + lindex <<= 2; + for(j=0, i=0x31; i<=0x34; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS661_TVPhase[lindex + j]); + } + return; + } + + /* PAL-M, PAL-N not in BIOS, and already set in SetGroup2 */ + if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) return; + + if(ModeNo<=0x13) { + resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; + } else { + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + } + + temp = GetTVPtrIndex(SiS_Pr); + /* 0: NTSC Graphics, 1: NTSC Text, 2: PAL Graphics, + * 3: PAL Text, 4: HiTV Graphics 5: HiTV Text + */ + if(SiS_Pr->SiS_UseROM) { + romptr = SISGETROMW(0x116); + if(HwInfo->jChipType >= SIS_330) { + romptr = SISGETROMW(0x196); + } + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + romptr = SISGETROMW(0x11c); + if(HwInfo->jChipType >= SIS_330) { + romptr = SISGETROMW(0x19c); + } + if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) { + romptr = SISGETROMW(0x116); + if(HwInfo->jChipType >= SIS_330) { + romptr = SISGETROMW(0x196); + } + } + } + } + if(romptr) { + romptr += (temp << 2); + for(j=0, i=0x31; i<=0x34; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]); + } + } else { + index = temp % 2; + temp >>= 1; /* 0:NTSC, 1:PAL, 2:HiTV */ + for(j=0, i=0x31; i<=0x34; i++, j++) { + if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]); + else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]); + else + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]); + } + } + + if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) { + if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) { + if((resinfo == SIS_RI_640x480) || + (resinfo == SIS_RI_800x600)) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f); + } else if(resinfo == SIS_RI_1024x768) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb); + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b); + } + } + } +} + +static void +SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, + USHORT ModeIdIndex, USHORT RTI) +{ + USHORT delay = 0, romptr = 0, index, lcdpdcindex; + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + + if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC))) + return; + + /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */ + /* (If a custom mode is used, Pass1:1 is always set; hence we do this:) */ + + if(SiS_Pr->SiS_ROMNew) { + if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) || + ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) && + (SiS_Pr->SiS_LCDInfo & LCDPass11))) { + index = 25; + if(SiS_Pr->UseCustomMode) { + index = SiS_Pr->CSRClock; + } else if(ModeNo > 0x13) { + index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI,HwInfo); + index = SiS_Pr->SiS_VCLKData[index].CLOCK; + } + if(index < 25) index = 25; + index = ((index / 25) - 1) << 1; + if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) { + index++; + } + romptr = SISGETROMW(0x104); + delay = ROMAddr[romptr + index]; + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f)); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7)); + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0)); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6)); + } + return; + } + } + + /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */ + + if(SiS_Pr->UseCustomMode) delay = 0x04; + else if(ModeNo <= 0x13) delay = 0x04; + else delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4); + delay |= (delay << 8); + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + + /* 3. TV */ + + index = GetOEMTVPtr661(SiS_Pr); + if(SiS_Pr->SiS_ROMNew) { + romptr = SISGETROMW(0x106); + if(SiS_Pr->SiS_VBType & VB_UMC) romptr += 12; + delay = ROMAddr[romptr + index]; + } else { + delay = 0x04; + if(index > 3) delay = 0; + } + + } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + + /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */ + + if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) && + ((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) ) { + + lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12; + + /* For LVDS (and sometimes TMDS), the BIOS must know about the correct value */ + delay = ROMAddr[romptr + lcdpdcindex + 1]; /* LCD */ + delay |= (ROMAddr[romptr + lcdpdcindex] << 8); /* LCDA */ + + } else { + + /* TMDS: Set our own, since BIOS has no idea */ + /* (This is done on >=661 only, since <661 is calling this only for LVDS) */ + if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { + switch(SiS_Pr->SiS_LCDResInfo) { + case Panel_1024x768: delay = 0x0008; break; + case Panel_1280x720: delay = 0x0004; break; + case Panel_1280x768: + case Panel_1280x768_2:delay = 0x0004; break; + case Panel_1280x800: + case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */ + case Panel_1280x1024: delay = 0x1e04; break; + case Panel_1400x1050: delay = 0x0004; break; + case Panel_1600x1200: delay = 0x0400; break; + case Panel_1680x1050: delay = 0x0e04; break; + default: + if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) { + delay = 0x0008; + } else if((SiS_Pr->PanelXRes == 1280) && (SiS_Pr->PanelYRes == 1024)) { + delay = 0x1e04; + } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) { + delay = 0x0004; + } else if((SiS_Pr->PanelXRes <= 1600) && (SiS_Pr->PanelYRes <= 1200)) { + delay = 0x0400; + } else + delay = 0x0e04; + break; + } + } + + /* Override by detected or user-set values */ + /* (but only if, for some reason, we can't read value from BIOS) */ + if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) { + delay = SiS_Pr->PDC & 0x1f; + } + if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) { + delay = (SiS_Pr->PDCA & 0x1f) << 8; + } + + } + + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + delay >>= 8; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0)); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6)); + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f)); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7)); + } +} + +static void +SetCRT2SyncDither661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT RTI) +{ + USHORT infoflag; + UCHAR temp; + + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + + if(ModeNo <= 0x13) { + infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2); + } else if(SiS_Pr->UseCustomMode) { + infoflag = SiS_Pr->CInfoFlag; + } else { + infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag; + } + + if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { + infoflag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); /* No longer check D5 */ + } + + infoflag &= 0xc0; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + temp = (infoflag >> 6) | 0x0c; + if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) { + temp ^= 0x04; + if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x10; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp); + } else { + temp = 0x30; + if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp = 0x20; + temp |= infoflag; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp); + temp = 0; + if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) { + if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x80; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp); + } + + } +} + +static void +SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT romptr, temp1, temp2; + + if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) { + if(SiS_Pr->LVDSHL != -1) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL); + } + } + + if(SiS_Pr->SiS_ROMNew) { + + if((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) { + if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) { + temp1 = (ROMAddr[romptr] & 0x03) | 0x0c; + temp2 = 0xfc; + if(SiS_Pr->LVDSHL != -1) { + temp1 &= 0xfc; + temp2 = 0xf3; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1); + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1; + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1); + } + } + + } +} + +static void +SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex,USHORT RRTI) +{ + if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) { + SetDelayComp661(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,RRTI); + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + SetCRT2SyncDither661(SiS_Pr,HwInfo,ModeNo,RRTI); + SetPanelParms661(SiS_Pr,HwInfo); + } + } else { + SetDelayComp(SiS_Pr,HwInfo,ModeNo); + } + + if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) { + SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex); + SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex); + SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex); + if(SiS_Pr->SiS_VBType & VB_SIS301) { + SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex); + } + } +} + +static void +SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI) +{ + if(SiS_Pr->SiS_VBType & VB_SISVB) { + + SetDelayComp661(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,RRTI); + + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + SetCRT2SyncDither661(SiS_Pr,HwInfo,ModeNo,RRTI); + SetPanelParms661(SiS_Pr,HwInfo); + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex); + SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex); + SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex); + if(SiS_Pr->SiS_VBType & VB_SIS301) { + SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex); + } + } + } +} + +/* FinalizeLCD + * This finalizes some CRT2 registers for the very panel used. + * If we have a backup if these registers, we use it; otherwise + * we set the register according to most BIOSes. However, this + * function looks quite different in every BIOS, so you better + * pray that we have a backup... + */ +static void +SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_INFO HwInfo) +{ + USHORT tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp; + USHORT resinfo,modeflag; + + if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) return; + if(SiS_Pr->SiS_ROMNew) return; + + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(SiS_Pr->LVDSHL != -1) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL); + } + } + + if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return; + if(SiS_Pr->UseCustomMode) return; + + switch(SiS_Pr->SiS_CustomT) { + case CUT_COMPAQ1280: + case CUT_COMPAQ12802: + case CUT_CLEVO1400: + case CUT_CLEVO14002: + return; + } + + if(ModeNo <= 0x13) { + resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } else { + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } + + if(IS_SIS650) { + if(!(SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) { + if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x02); + } else { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03); + } + } + } + + if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + /* Maybe all panels? */ + if(SiS_Pr->LVDSHL == -1) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01); + } + return; + } + } + + if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + if(SiS_Pr->LVDSHL == -1) { + /* Maybe all panels? */ + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01); + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4; + if(tempch == 3) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b); + } + } + return; + } + } + } + + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) { + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00); +#ifdef SET_EMI + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c); +#endif + SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10); + } + } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) { + if(SiS_Pr->LVDSHL == -1) { + /* Maybe ACER only? */ + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01); + } + } + tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76); + } else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + if(tempch == 0x03) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b); + } + if((SiS_Pr->Backup == TRUE) && (SiS_Pr->Backup_Mode == ModeNo)) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,SiS_Pr->Backup_17); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,SiS_Pr->Backup_18); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,SiS_Pr->Backup_19); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,SiS_Pr->Backup_1a); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,SiS_Pr->Backup_1b); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,SiS_Pr->Backup_1c); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,SiS_Pr->Backup_1d); + } else if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) { /* 1.10.8w */ + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x90); + if(ModeNo <= 0x13) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x11); + if((resinfo == 0) || (resinfo == 2)) return; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x18); + if((resinfo == 1) || (resinfo == 3)) return; + } + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02); + if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02); /* 1.10.7u */ +#if 0 + tempbx = 806; /* 0x326 */ /* other older BIOSes */ + tempbx--; + temp = tempbx & 0xff; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp); + temp = (tempbx >> 8) & 0x03; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp); +#endif + } + } else if(ModeNo <= 0x13) { + if(ModeNo <= 1) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x70); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xff); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12); + } + if(!(modeflag & HalfDCLK)) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x20); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,0x1a); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,0x28); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,0x00); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x4c); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc); + if(ModeNo == 0x12) { + switch(tempch) { + case 0: + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,0x10); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x48); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12); + break; + case 2: + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95); + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48); + break; + case 3: + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95); + break; + } + } + } + } + } + } else { + tempcl = tempbh = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01); + tempcl &= 0x0f; + tempbh &= 0x70; + tempbh >>= 4; + tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04); + tempbx = (tempbh << 8) | tempbl; + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) { + if(SiS_Pr->SiS_SetFlag & LCDVESATiming) { + tempbx = 770; + } else { + if(tempbx > 770) tempbx = 770; + if(SiS_Pr->SiS_VGAVDE < 600) { + tempax = 768 - SiS_Pr->SiS_VGAVDE; + tempax >>= 4; /* 1.10.7w; 1.10.6s: 3; */ + if(SiS_Pr->SiS_VGAVDE <= 480) tempax >>= 4; /* 1.10.7w; 1.10.6s: < 480; >>=1; */ + tempbx -= tempax; + } + } + } else return; + } + temp = tempbx & 0xff; + SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp); + temp = ((tempbx & 0xff00) >> 4) | tempcl; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp); + } + } +} + +#endif + +/* ================= SiS 300 O.E.M. ================== */ + +#ifdef SIS300 + +static void +SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex, USHORT RefTabIndex) +{ + USHORT crt2crtc=0, modeflag, myindex=0; + UCHAR temp; + int i; + + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC; + } + + crt2crtc &= 0x3f; + + if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf); + } + + if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) { + if(modeflag & HalfDCLK) myindex = 1; + + if(SiS_Pr->SiS_SetFlag & LowModeTests) { + for(i=0; i<7; i++) { + if(barco_p1[myindex][crt2crtc][i][0]) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, + barco_p1[myindex][crt2crtc][i][0], + barco_p1[myindex][crt2crtc][i][2], + barco_p1[myindex][crt2crtc][i][1]); + } + } + } + temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00); + if(temp & 0x80) { + temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x18); + temp++; + SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp); + } + } +} + +static USHORT +GetOEMLCDPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, int Flag) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT tempbx=0,romptr=0; + UCHAR customtable300[] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff + }; + UCHAR customtable630[] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff + }; + + if(HwInfo->jChipType == SIS_300) { + + tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f; + if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07; + tempbx -= 2; + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4; + if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3; + } + if(SiS_Pr->SiS_UseROM) { + if(ROMAddr[0x235] & 0x80) { + tempbx = SiS_Pr->SiS_LCDTypeInfo; + if(Flag) { + romptr = SISGETROMW(0x255); + if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo]; + else tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo]; + if(tempbx == 0xFF) return 0xFFFF; + } + tempbx <<= 1; + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++; + } + } + + } else { + + if(Flag) { + if(SiS_Pr->SiS_UseROM) { + romptr = SISGETROMW(0x255); + if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo]; + else tempbx = 0xff; + } else { + tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo]; + } + if(tempbx == 0xFF) return 0xFFFF; + tempbx <<= 2; + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++; + return tempbx; + } + tempbx = SiS_Pr->SiS_LCDTypeInfo << 2; + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2; + if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++; + + } + + return tempbx; +} + +static void +SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT index,temp,romptr=0; + + if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return; + + if(SiS_Pr->SiS_UseROM) { + if(!(ROMAddr[0x237] & 0x01)) return; + if(!(ROMAddr[0x237] & 0x02)) return; + romptr = SISGETROMW(0x24b); + } + + /* The Panel Compensation Delay should be set according to tables + * here. Unfortunately, various BIOS versions don't case about + * a uniform way using eg. ROM byte 0x220, but use different + * hard coded delays (0x04, 0x20, 0x18) in SetGroup1(). + * Thus we don't set this if the user select a custom pdc or if + * we otherwise detected a valid pdc. + */ + if(SiS_Pr->PDC != -1) return; + + temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 0); + + if(SiS_Pr->UseCustomMode) + index = 0; + else + index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex; + + if(HwInfo->jChipType != SIS_300) { + if(romptr) { + romptr += (temp * 2); + romptr = SISGETROMW(romptr); + romptr += index; + temp = ROMAddr[romptr]; + } else { + if(SiS_Pr->SiS_VBType & VB_SISVB) { + temp = SiS300_OEMLCDDelay2[temp][index]; + } else { + temp = SiS300_OEMLCDDelay3[temp][index]; + } + } + } else { + if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) { + if(romptr) { + romptr += (temp * 2); + romptr = SISGETROMW(romptr); + romptr += index; + temp = ROMAddr[romptr]; + } else { + temp = SiS300_OEMLCDDelay5[temp][index]; + } + } else { + if(SiS_Pr->SiS_UseROM) { + romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8); + if(romptr) { + romptr += (temp * 2); + romptr = SISGETROMW(romptr); + romptr += index; + temp = ROMAddr[romptr]; + } else { + temp = SiS300_OEMLCDDelay4[temp][index]; + } + } else { + temp = SiS300_OEMLCDDelay4[temp][index]; + } + } + } + temp &= 0x3c; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* index 0A D[6:4] */ +} + +static void +SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex) +{ +#if 0 /* Unfinished; Data table missing */ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT index,temp; + + if((SiS_Pr->SiS_UseROM) { + if(!(ROMAddr[0x237] & 0x01)) return; + if(!(ROMAddr[0x237] & 0x04)) return; + /* No rom pointer in BIOS header! */ + } + + temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 1); + if(temp = 0xFFFF) return; + + index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex; + for(i=0x14, j=0; i<=0x17; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDHData[temp][index][j]); + } + SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1a, 0xf8, (SiS300_LCDHData[temp][index][j] & 0x07)); + + index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDVIndex; + SiS_SetReg(SiS_SiS_Part1Port,0x18, SiS300_LCDVData[temp][index][0]); + SiS_SetRegANDOR(SiS_SiS_Part1Port,0x19, 0xF0, SiS300_LCDVData[temp][index][1]); + SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1A, 0xC7, (SiS300_LCDVData[temp][index][2] & 0x38)); + for(i=0x1b, j=3; i<=0x1d; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]); + } +#endif +} + +static USHORT +GetOEMTVPtr(SiS_Private *SiS_Pr) +{ + USHORT index; + + index = 0; + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) index += 4; + if(SiS_Pr->SiS_VBType & VB_SISVB) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) index += 2; + else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index += 3; + else if(SiS_Pr->SiS_TVMode & TVSetPAL) index += 1; + } else { + if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) index += 2; + if(SiS_Pr->SiS_TVMode & TVSetPAL) index += 1; + } + return index; +} + +static void +SetOEMTVDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT index,temp,romptr=0; + + if(SiS_Pr->SiS_UseROM) { + if(!(ROMAddr[0x238] & 0x01)) return; + if(!(ROMAddr[0x238] & 0x02)) return; + romptr = SISGETROMW(0x241); + } + + temp = GetOEMTVPtr(SiS_Pr); + + index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex; + + if(romptr) { + romptr += (temp * 2); + romptr = SISGETROMW(romptr); + romptr += index; + temp = ROMAddr[romptr]; + } else { + if(SiS_Pr->SiS_VBType & VB_SISVB) { + temp = SiS300_OEMTVDelay301[temp][index]; + } else { + temp = SiS300_OEMTVDelayLVDS[temp][index]; + } + } + temp &= 0x3c; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); +} + +static void +SetOEMAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo, USHORT ModeIdIndex) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT index,temp,romptr=0; + + if(SiS_Pr->SiS_UseROM) { + if(!(ROMAddr[0x238] & 0x01)) return; + if(!(ROMAddr[0x238] & 0x04)) return; + romptr = SISGETROMW(0x243); + } + + temp = GetOEMTVPtr(SiS_Pr); + + index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex; + + if(romptr) { + romptr += (temp * 2); + romptr = SISGETROMW(romptr); + romptr += index; + temp = ROMAddr[romptr]; + } else { + temp = SiS300_OEMTVFlicker[temp][index]; + } + temp &= 0x70; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp); +} + +static void +SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT index,i,j,temp,romptr=0; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return; + + if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return; + + if(SiS_Pr->SiS_UseROM) { + if(!(ROMAddr[0x238] & 0x01)) return; + if(!(ROMAddr[0x238] & 0x08)) return; + romptr = SISGETROMW(0x245); + } + + temp = GetOEMTVPtr(SiS_Pr); + + index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex; + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + for(i=0x31, j=0; i<=0x34; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]); + } + } else { + if(romptr) { + romptr += (temp * 2); + romptr = SISGETROMW(romptr); + romptr += (index * 4); + for(i=0x31, j=0; i<=0x34; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]); + } + } else { + for(i=0x31, j=0; i<=0x34; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]); + } + } + } +} + +static void +SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex) +{ + UCHAR *ROMAddr = HwInfo->pjVirtualRomBase; + USHORT index,temp,i,j,romptr=0; + + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return; + + if(SiS_Pr->SiS_UseROM) { + if(!(ROMAddr[0x238] & 0x01)) return; + if(!(ROMAddr[0x238] & 0x10)) return; + romptr = SISGETROMW(0x247); + } + + temp = GetOEMTVPtr(SiS_Pr); + + if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8; + else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 9; + /* NTSCJ uses NTSC filters */ + + index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex; + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + for(i=0x35, j=0; i<=0x38; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]); + } + for(i=0x48; i<=0x4A; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]); + } + } else { + if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) { + romptr += (temp * 2); + romptr = SISGETROMW(romptr); + romptr += (index * 4); + for(i=0x35, j=0; i<=0x38; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]); + } + } else { + for(i=0x35, j=0; i<=0x38; i++, j++) { + SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]); + } + } + } +} + +static USHORT +SiS_SearchVBModeID(SiS_Private *SiS_Pr, USHORT *ModeNo) +{ + USHORT ModeIdIndex; + UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO; + + if(*ModeNo <= 5) *ModeNo |= 1; + + for(ModeIdIndex=0; ; ModeIdIndex++) { + if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break; + if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF) return 0; + } + + if(*ModeNo != 0x07) { + if(*ModeNo > 0x03) return ModeIdIndex; + if(VGAINFO & 0x80) return ModeIdIndex; + ModeIdIndex++; + } + + if(VGAINFO & 0x10) ModeIdIndex++; /* 400 lines */ + /* else 350 lines */ + return ModeIdIndex; +} + +static void +SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTableIndex) +{ + USHORT OEMModeIdIndex=0; + + if(!SiS_Pr->UseCustomMode) { + OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo); + if(!(OEMModeIdIndex)) return; + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + SetOEMLCDDelay(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex); + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + SetOEMLCDData(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex); + } + } + if(SiS_Pr->UseCustomMode) return; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + SetOEMTVDelay(SiS_Pr, HwInfo, ModeNo,OEMModeIdIndex); + if(SiS_Pr->SiS_VBType & VB_SISVB) { + SetOEMAntiFlicker(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex); + SetOEMPhaseIncr(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex); + SetOEMYFilter(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex); + } + } +} +#endif + diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h new file mode 100644 index 000000000000..f05aebc994b4 --- /dev/null +++ b/drivers/video/sis/init301.h @@ -0,0 +1,410 @@ +/* $XFree86$ */ +/* $XdotOrg$ */ +/* + * Data and prototypes for init301.c + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the named License, + * * or any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program; if not, write to the Free Software + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Otherwise, the following license terms apply: + * + * * Redistribution and use in source and binary forms, with or without + * * modification, are permitted provided that the following conditions + * * are met: + * * 1) Redistributions of source code must retain the above copyright + * * notice, this list of conditions and the following disclaimer. + * * 2) Redistributions in binary form must reproduce the above copyright + * * notice, this list of conditions and the following disclaimer in the + * * documentation and/or other materials provided with the distribution. + * * 3) The name of the author may not be used to endorse or promote products + * * derived from this software without specific prior written permission. + * * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + */ + +#ifndef _INIT301_ +#define _INIT301_ + +#include "osdef.h" +#include "initdef.h" + +#ifdef LINUX_XF86 +#include "sis.h" +#include "sis_regs.h" +#endif + +#ifdef LINUX_KERNEL +#include "vgatypes.h" +#include "vstruct.h" +#ifdef SIS_CP +#undef SIS_CP +#endif +#include <linux/config.h> +#include <linux/version.h> +#include <asm/io.h> +#include <linux/types.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include <linux/sisfb.h> +#else +#include <video/sisfb.h> +#endif +#endif + +static const UCHAR SiS_YPbPrTable[3][64] = { + { + 0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c, + 0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a, + 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b, + 0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17, + 0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02, + 0x03,0x0a,0x65,0x9d /*0x8d*/,0x08,0x92,0x8f,0x40, + 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x53 /*0x50*/, + 0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00 + }, + { + 0x1d,0x11,0x06,0x09,0x0b,0x0c,0x0c,0x0c, + 0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a, + 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f, + 0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4c /*0x4f*/,0x13, + 0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8, + 0x51,0x5e,0x60,0x57 /*0x49*/,0x7b /*0x7d*/,0x92,0x0f,0x40, + 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4b, + 0x43,0x41,0x11,0x00,0xfc,0xff,0x32,0x00 + }, + { +#if 1 + 0x13,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c, + 0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a, + 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f, + 0xed,0x50,0x70,0x9f,0x16,0x59,0x21 /*0x2b*/,0x13, + 0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0, + 0x4b,0x4b,0x65 /*0x6f*/,0x2f,0x63,0x92,0x0f,0x40, + 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x27, + 0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00 +#endif +#if 0 + 0x2a,0x14,0xe8,0x09,0x09,0xed,0x0c,0x0c, /* TEST (0.93) - BAD */ + 0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a, + 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f, + 0xed,0x50,0x70,0x9e,0x16,0x57,0x6c,0x13, + 0x27,0x0b,0x27,0xfb,0x30,0x27,0x15,0xb0, + 0x3b,0xdb,0x61,0x24,0x78,0x92,0x0f,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x14,0x6f, + 0x00,0x52,0xbb,0x00,0xd5,0xf7,0xa2,0x00 +#endif + } +}; + +static const UCHAR SiS_HiTVGroup3_1[] = { + 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x13, + 0xb1, 0x41, 0x62, 0x62, 0xff, 0xf4, 0x45, 0xa6, + 0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20, + 0xac, 0xda, 0x60, 0xfe, 0x6a, 0x9a, 0x06, 0x10, + 0xd1, 0x04, 0x18, 0x0a, 0xff, 0x80, 0x00, 0x80, + 0x3b, 0x77, 0x00, 0xef, 0xe0, 0x10, 0xb0, 0xe0, + 0x10, 0x4f, 0x0f, 0x0f, 0x05, 0x0f, 0x08, 0x6e, + 0x1a, 0x1f, 0x25, 0x2a, 0x4c, 0xaa, 0x01 +}; + +static const UCHAR SiS_HiTVGroup3_2[] = { + 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x7a, + 0x54, 0x41, 0xe7, 0xe7, 0xff, 0xf4, 0x45, 0xa6, + 0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20, + 0xac, 0x6a, 0x60, 0x2b, 0x52, 0xcd, 0x61, 0x10, + 0x51, 0x04, 0x18, 0x0a, 0x1f, 0x80, 0x00, 0x80, + 0xff, 0xa4, 0x04, 0x2b, 0x94, 0x21, 0x72, 0x94, + 0x26, 0x05, 0x01, 0x0f, 0xed, 0x0f, 0x0a, 0x64, + 0x18, 0x1d, 0x23, 0x28, 0x4c, 0xaa, 0x01 +}; + +/* 301C / 302ELV extended Part2 TV registers (4 tap scaler) */ + +static const UCHAR SiS_Part2CLVX_1[] = { + 0x00,0x00, + 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, + 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, + 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C,0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, + 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E +}; + +static const UCHAR SiS_Part2CLVX_2[] = { + 0x00,0x00, + 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, + 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, + 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C,0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, + 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E +}; + +static const UCHAR SiS_Part2CLVX_3[] = { /* NTSC, 525i, 525p */ + 0xE0,0x01, + 0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D,0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D, + 0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C,0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C, + 0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E, + 0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00,0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02, + 0x58,0x02, + 0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D,0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E, + 0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F,0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F, + 0x00,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01,0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03, + 0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04,0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06, + 0x00,0x03, + 0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00,0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01, + 0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02,0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03, + 0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05,0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06, + 0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07,0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08, + 0xFF,0xFF +}; + +static const UCHAR SiS_Part2CLVX_4[] = { /* PAL */ + 0x58,0x02, + 0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D, + 0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D, + 0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E,0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E, + 0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01,0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04, + 0x00,0x03, + 0x08,0x12,0x08,0x7E,0x07,0x12,0x09,0x7E,0x06,0x12,0x0A,0x7E,0x05,0x11,0x0B,0x7F, + 0x04,0x11,0x0C,0x7F,0x03,0x11,0x0C,0x00,0x03,0x10,0x0D,0x00,0x02,0x0F,0x0E,0x01, + 0x01,0x0F,0x0F,0x01,0x01,0x0E,0x0F,0x02,0x00,0x0D,0x10,0x03,0x7F,0x0C,0x11,0x04, + 0x7F,0x0C,0x11,0x04,0x7F,0x0B,0x11,0x05,0x7E,0x0A,0x12,0x06,0x7E,0x09,0x12,0x07, + 0x40,0x02, + 0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D, + 0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C, + 0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F, + 0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02, + 0xFF,0xFF +}; + +static const UCHAR SiS_Part2CLVX_5[] = { /* 750p */ + 0x00,0x03, + 0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D, + 0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D, + 0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E,0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E, + 0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01,0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04, + 0xFF,0xFF +}; + +static const UCHAR SiS_Part2CLVX_6[] = { /* 1080i */ + 0x00,0x04, + 0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D, + 0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C, + 0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F, + 0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02, + 0xFF,0xFF, +}; + +#ifdef SIS315H +/* 661 et al LCD data structure (2.03.00) */ +static const UCHAR SiS_LCDStruct661[] = { + /* 1024x768 */ +/* type|CR37| HDE | VDE | HT | VT | hss | hse */ + 0x02,0xC0,0x00,0x04,0x00,0x03,0x40,0x05,0x26,0x03,0x10,0x00,0x88, + 0x00,0x02,0x00,0x06,0x00,0x41,0x5A,0x64,0x00,0x00,0x00,0x00,0x04, + /* | vss | vse |clck| clock |CRT2DataP|CRT2DataP|idx */ + /* VESA non-VESA noscale */ + /* 1280x1024 */ + 0x03,0xC0,0x00,0x05,0x00,0x04,0x98,0x06,0x2A,0x04,0x30,0x00,0x70, + 0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x08, + /* 1400x1050 */ + 0x09,0x20,0x78,0x05,0x1A,0x04,0x98,0x06,0x2A,0x04,0x18,0x00,0x38, + 0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x09, + /* 1600x1200 */ + 0x0B,0xE0,0x40,0x06,0xB0,0x04,0x70,0x08,0xE2,0x04,0x40,0x00,0xC0, + 0x00,0x01,0x00,0x03,0x00,0xA2,0x70,0x24,0x00,0x00,0x00,0x00,0x0A, + /* 1280x768 (_2) */ + 0x0A,0xE0,0x00,0x05,0x00,0x03,0x7C,0x06,0x26,0x03,0x30,0x00,0x70, + 0x00,0x03,0x00,0x06,0x00,0x4D,0xC8,0x48,0x00,0x00,0x00,0x00,0x06, + /* 1280x720 */ + 0x0E,0xE0,0x00,0x05,0xD0,0x02,0x80,0x05,0x26,0x03,0x10,0x00,0x20, + 0x00,0x01,0x00,0x06,0x00,0x45,0x9C,0x62,0x00,0x00,0x00,0x00,0x05, + /* 1280x800 (_2) */ + 0x0C,0xE0,0x00,0x05,0x20,0x03,0x10,0x06,0x2C,0x03,0x30,0x00,0x70, + 0x00,0x04,0x00,0x03,0x00,0x49,0xCE,0x1E,0x00,0x00,0x00,0x00,0x09, + /* 1680x1050 */ + 0x0D,0xE0,0x90,0x06,0x1A,0x04,0x6C,0x07,0x2A,0x04,0x1A,0x00,0x4C, + 0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x00,0x00,0x00,0x00,0x06, +}; +#endif + +#ifdef SIS300 +static UCHAR SiS300_TrumpionData[7][80] = { + { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02, + 0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23, + 0x00,0x00,0x03,0x28,0x03,0x10,0x05,0x08,0x40,0x10,0x00,0x10,0x04,0x23,0x00,0x23, + 0x03,0x11,0x60,0xBC,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x09,0x04,0x04,0x05, + 0x04,0x0C,0x09,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5A,0x01,0xBE,0x01,0x00 }, + { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x27,0x00,0x80,0x02, + 0x20,0x03,0x07,0x00,0x5E,0x01,0x0D,0x02,0x60,0x0C,0x30,0x11,0x00,0x00,0x04,0x23, + 0x00,0x00,0x03,0x80,0x03,0x28,0x06,0x08,0x40,0x11,0x00,0x11,0x04,0x23,0x00,0x23, + 0x03,0x11,0x60,0x90,0x01,0xFF,0x0F,0xF4,0x19,0x01,0x00,0x05,0x01,0x00,0x04,0x05, + 0x04,0x0C,0x02,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEC,0x57,0x01,0xBE,0x01,0x00 }, + { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02, + 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23, + 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23, + 0x03,0x11,0x60,0xD9,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05, + 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x59,0x01,0xBE,0x01,0x00 }, + { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02, + 0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23, + 0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23, + 0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05, + 0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 }, + { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02, + 0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23, + 0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23, + 0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05, + 0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 }, + { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03, + 0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D, + 0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D, + 0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B, + 0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 }, + { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04, + 0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23, + 0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23, + 0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01, + 0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 } +}; +#endif + +void SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +void SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +void SiS_EnableCRT2(SiS_Private *SiS_Pr); +USHORT SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo); +void SiS_WaitRetrace1(SiS_Private *SiS_Pr); +BOOLEAN SiS_IsDualEdge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +BOOLEAN SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +void SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo); +void SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, + USHORT ModeIdIndex, PSIS_HW_INFO HwInfo, + int checkcrt2mode); +void SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +void SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo); +void SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo); +USHORT SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo); +USHORT SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex); +void SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +void SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +BOOLEAN SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo); +void SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +void SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); + +void SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempax); +USHORT SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempax); +void SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempax); +USHORT SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempax); +void SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempax); +USHORT SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempax); +void SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh); +#ifdef SIS315H +static void SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +static void SiS_Chrontel701xOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +static void SiS_ChrontelInitTVVSync(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +static void SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +void SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); +void SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr); +#endif /* 315 */ + +#ifdef SIS300 +#if 0 +static void SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx); +static USHORT SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx); +#endif +static BOOLEAN SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr); +#endif + +void SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime); +USHORT SiS_ReadDDC1Bit(SiS_Private *SiS_Pr); +USHORT SiS_HandleDDC(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine, + USHORT adaptnum, USHORT DDCdatatype, UCHAR *buffer); +#ifdef LINUX_XF86 +USHORT SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS); +USHORT SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS); +#endif + +static void SiS_SetSwitchDDC2(SiS_Private *SiS_Pr); +static USHORT SiS_SetStart(SiS_Private *SiS_Pr); +static USHORT SiS_SetStop(SiS_Private *SiS_Pr); +static USHORT SiS_SetSCLKLow(SiS_Private *SiS_Pr); +static USHORT SiS_SetSCLKHigh(SiS_Private *SiS_Pr); +static USHORT SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax); +static USHORT SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax); +static USHORT SiS_CheckACK(SiS_Private *SiS_Pr); +static USHORT SiS_InitDDCRegs(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine, + USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32); +static USHORT SiS_WriteDABDDC(SiS_Private *SiS_Pr); +static USHORT SiS_PrepareReadDDC(SiS_Private *SiS_Pr); +static USHORT SiS_PrepareDDC(SiS_Private *SiS_Pr); +static void SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno); +static USHORT SiS_DoProbeDDC(SiS_Private *SiS_Pr); +static USHORT SiS_ProbeDDC(SiS_Private *SiS_Pr); +static USHORT SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, UCHAR *buffer); + +#ifdef SIS315H +static void SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI); +static void SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI); +static void SiS_FinalizeLCD(SiS_Private *, USHORT, USHORT, PSIS_HW_INFO); +#endif +#ifdef SIS300 +static void SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTabindex); +static void SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, + USHORT ModeNo, USHORT ModeIdIndex,USHORT RefTableIndex); +#endif + +extern void SiS_SetReg(SISIOADDRESS, USHORT, USHORT); +extern void SiS_SetRegByte(SISIOADDRESS, USHORT); +extern void SiS_SetRegShort(SISIOADDRESS, USHORT); +extern void SiS_SetRegLong(SISIOADDRESS, ULONG); +extern UCHAR SiS_GetReg(SISIOADDRESS, USHORT); +extern UCHAR SiS_GetRegByte(SISIOADDRESS); +extern USHORT SiS_GetRegShort(SISIOADDRESS); +extern ULONG SiS_GetRegLong(SISIOADDRESS); +extern void SiS_SetRegANDOR(SISIOADDRESS, USHORT, USHORT, USHORT); +extern void SiS_SetRegOR(SISIOADDRESS, USHORT, USHORT); +extern void SiS_SetRegAND(SISIOADDRESS, USHORT, USHORT); +extern void SiS_DisplayOff(SiS_Private *SiS_Pr); +extern void SiS_DisplayOn(SiS_Private *SiS_Pr); +extern BOOLEAN SiS_SearchModeID(SiS_Private *, USHORT *, USHORT *); +extern UCHAR SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex); +extern USHORT SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex); +extern USHORT SiS_GetOffset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo); +extern void SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO, USHORT ModeNo, + USHORT ModeIdIndex); +extern void SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex); +#ifdef LINUX_XF86 +extern void SiS_MakeClockRegs(ScrnInfoPtr pScrn, int clock, UCHAR *p2b, UCHAR *p2c); +extern int SiS_FindPanelFromDB(SISPtr pSiS, USHORT panelvendor, USHORT panelproduct, + int *maxx, int *maxy, int *prefx, int *prefy); +#endif + +#endif diff --git a/drivers/video/sis/initdef.h b/drivers/video/sis/initdef.h new file mode 100644 index 000000000000..55a82d6dc4cf --- /dev/null +++ b/drivers/video/sis/initdef.h @@ -0,0 +1,671 @@ +/* $XFree86$ */ +/* $XdotOrg$ */ +/* + * Global definitions for init.c and init301.c + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the named License, + * * or any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program; if not, write to the Free Software + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Otherwise, the following license terms apply: + * + * * Redistribution and use in source and binary forms, with or without + * * modification, are permitted provided that the following conditions + * * are met: + * * 1) Redistributions of source code must retain the above copyright + * * notice, this list of conditions and the following disclaimer. + * * 2) Redistributions in binary form must reproduce the above copyright + * * notice, this list of conditions and the following disclaimer in the + * * documentation and/or other materials provided with the distribution. + * * 3) The name of the author may not be used to endorse or promote products + * * derived from this software without specific prior written permission. + * * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + */ + +#ifndef _INITDEF_ +#define _INITDEF_ + +#define IS_SIS330 (HwInfo->jChipType == SIS_330) +#define IS_SIS550 (HwInfo->jChipType == SIS_550) +#define IS_SIS650 (HwInfo->jChipType == SIS_650) /* All versions, incl 651, M65x */ +#define IS_SIS740 (HwInfo->jChipType == SIS_740) +#define IS_SIS651 (SiS_Pr->SiS_SysFlags & (SF_Is651 | SF_Is652)) +#define IS_SISM650 (SiS_Pr->SiS_SysFlags & (SF_IsM650 | SF_IsM652 | SF_IsM653)) +#define IS_SIS65x (IS_SIS651 || IS_SISM650) /* Only special versions of 65x */ +#define IS_SIS661 (HwInfo->jChipType == SIS_661) +#define IS_SIS741 (HwInfo->jChipType == SIS_741) +#define IS_SIS660 (HwInfo->jChipType == SIS_660) +#define IS_SIS760 (HwInfo->jChipType == SIS_760) +#define IS_SIS661741660760 (IS_SIS661 || IS_SIS741 || IS_SIS660 || IS_SIS760) +#define IS_SIS650740 ((HwInfo->jChipType >= SIS_650) && (HwInfo->jChipType < SIS_330)) +#define IS_SIS550650740 (IS_SIS550 || IS_SIS650740) +#define IS_SIS650740660 (IS_SIS650 || IS_SIS740 || IS_SIS661741660760) +#define IS_SIS550650740660 (IS_SIS550 || IS_SIS650740660) + +#define SISGETROMW(x) (ROMAddr[(x)] | (ROMAddr[(x)+1] << 8)) + +/* SiS_VBType */ +#define VB_SIS301 0x0001 +#define VB_SIS301B 0x0002 +#define VB_SIS302B 0x0004 +#define VB_SIS301LV 0x0008 +#define VB_SIS302LV 0x0010 +#define VB_SIS302ELV 0x0020 +#define VB_SIS301C 0x0040 +#define VB_UMC 0x4000 +#define VB_NoLCD 0x8000 +#define VB_SIS301BLV302BLV (VB_SIS301B|VB_SIS301C|VB_SIS302B|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV) +#define VB_SIS301B302B (VB_SIS301B|VB_SIS301C|VB_SIS302B) +#define VB_SIS301LV302LV (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV) +#define VB_SISVB (VB_SIS301 | VB_SIS301BLV302BLV) +#define VB_SISTMDS (VB_SIS301 | VB_SIS301B302B) +#define VB_SISLVDS VB_SIS301LV302LV +#define VB_SISLCDA (VB_SIS302B|VB_SIS301C|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV) +#define VB_SISYPBPR (VB_SIS301C|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV) +#define VB_SISHIVISION (VB_SIS301|VB_SIS301B|VB_SIS302B) + +/* VBInfo */ +#define SetSimuScanMode 0x0001 /* CR 30 */ +#define SwitchCRT2 0x0002 +#define SetCRT2ToAVIDEO 0x0004 +#define SetCRT2ToSVIDEO 0x0008 +#define SetCRT2ToSCART 0x0010 +#define SetCRT2ToLCD 0x0020 +#define SetCRT2ToRAMDAC 0x0040 +#define SetCRT2ToHiVision 0x0080 /* for SiS bridge */ +#define SetCRT2ToCHYPbPr SetCRT2ToHiVision /* for Chrontel */ +#define SetNTSCTV 0x0000 /* CR 31 */ +#define SetPALTV 0x0100 /* Deprecated here, now in TVMode */ +#define SetInSlaveMode 0x0200 +#define SetNotSimuMode 0x0400 +#define SetNotSimuTVMode SetNotSimuMode +#define SetDispDevSwitch 0x0800 +#define SetCRT2ToYPbPr525750 0x0800 +#define LoadDACFlag 0x1000 +#define DisableCRT2Display 0x2000 +#define DriverMode 0x4000 +#define HotKeySwitch 0x8000 +#define SetCRT2ToLCDA 0x8000 + +/* v-- Needs change in sis_vga.c if changed (GPIO) --v */ +#define SetCRT2ToTV (SetCRT2ToYPbPr525750|SetCRT2ToHiVision|SetCRT2ToSCART|SetCRT2ToSVIDEO|SetCRT2ToAVIDEO) +#define SetCRT2ToTVNoYPbPrHiVision (SetCRT2ToSCART | SetCRT2ToSVIDEO | SetCRT2ToAVIDEO) +#define SetCRT2ToTVNoHiVision (SetCRT2ToYPbPr525750 | SetCRT2ToSCART | SetCRT2ToSVIDEO | SetCRT2ToAVIDEO) + +/* SiS_ModeType */ +#define ModeText 0x00 +#define ModeCGA 0x01 +#define ModeEGA 0x02 +#define ModeVGA 0x03 +#define Mode15Bpp 0x04 +#define Mode16Bpp 0x05 +#define Mode24Bpp 0x06 +#define Mode32Bpp 0x07 + +#define ModeTypeMask 0x07 +#define IsTextMode 0x07 + +#define DACInfoFlag 0x0018 +#define MemoryInfoFlag 0x01E0 +#define MemorySizeShift 5 + +/* modeflag */ +#define Charx8Dot 0x0200 +#define LineCompareOff 0x0400 +#define CRT2Mode 0x0800 +#define HalfDCLK 0x1000 +#define NoSupportSimuTV 0x2000 +#define NoSupportLCDScale 0x4000 /* SiS bridge: No scaling possible (no matter what panel) */ +#define DoubleScanMode 0x8000 + +/* Infoflag */ +#define SupportTV 0x0008 +#define SupportTV1024 0x0800 +#define SupportCHTV 0x0800 +#define Support64048060Hz 0x0800 /* Special for 640x480 LCD */ +#define SupportHiVision 0x0010 +#define SupportYPbPr750p 0x1000 +#define SupportLCD 0x0020 +#define SupportRAMDAC2 0x0040 /* All (<= 100Mhz) */ +#define SupportRAMDAC2_135 0x0100 /* All except DH (<= 135Mhz) */ +#define SupportRAMDAC2_162 0x0200 /* B, C (<= 162Mhz) */ +#define SupportRAMDAC2_202 0x0400 /* C (<= 202Mhz) */ +#define InterlaceMode 0x0080 +#define SyncPP 0x0000 +#define SyncPN 0x4000 +#define SyncNP 0x8000 +#define SyncNN 0xc000 + +/* SetFlag */ +#define ProgrammingCRT2 0x0001 +#define LowModeTests 0x0002 +/* #define TVSimuMode 0x0002 - deprecated */ +/* #define RPLLDIV2XO 0x0004 - deprecated */ +#define LCDVESATiming 0x0008 +#define EnableLVDSDDA 0x0010 +#define SetDispDevSwitchFlag 0x0020 +#define CheckWinDos 0x0040 +#define SetDOSMode 0x0080 + +/* TVMode flag */ +#define TVSetPAL 0x0001 +#define TVSetNTSCJ 0x0002 +#define TVSetPALM 0x0004 +#define TVSetPALN 0x0008 +#define TVSetCHOverScan 0x0010 +#define TVSetYPbPr525i 0x0020 /* new 0x10 */ +#define TVSetYPbPr525p 0x0040 /* new 0x20 */ +#define TVSetYPbPr750p 0x0080 /* new 0x40 */ +#define TVSetHiVision 0x0100 /* new 0x80; = 1080i, software-wise identical */ +#define TVSetTVSimuMode 0x0200 /* new 0x200, prev. 0x800 */ +#define TVRPLLDIV2XO 0x0400 /* prev 0x1000 */ +#define TVSetNTSC1024 0x0800 /* new 0x100, prev. 0x2000 */ +#define TVAspect43 0x2000 +#define TVAspect169 0x4000 +#define TVAspect43LB 0x8000 + +/* YPbPr flag (>=315, <661; converted to TVMode) */ +#define YPbPr525p 0x0001 +#define YPbPr750p 0x0002 +#define YPbPr525i 0x0004 +#define YPbPrHiVision 0x0008 +#define YPbPrModeMask (YPbPr750p | YPbPr525p | YPbPr525i | YPbPrHiVision) + +/* SysFlags (to identify special versions) */ +#define SF_Is651 0x0001 +#define SF_IsM650 0x0002 +#define SF_Is652 0x0004 +#define SF_IsM652 0x0008 +#define SF_IsM653 0x0010 +#define SF_IsM661 0x0020 +#define SF_IsM741 0x0040 +#define SF_IsM760 0x0080 +#define SF_760LFB 0x8000 /* 760: We have LFB */ + +/* CR32 (Newer 630, and 315 series) + + [0] VB connected with CVBS + [1] VB connected with SVHS + [2] VB connected with SCART + [3] VB connected with LCD + [4] VB connected with CRT2 (secondary VGA) + [5] CRT1 monitor is connected + [6] VB connected with Hi-Vision TV + [7] <= 330: VB connected with DVI combo connector + >= 661: VB connected to YPbPr +*/ + +/* CR35 (300 series only) */ +#define TVOverScan 0x10 +#define TVOverScanShift 4 + +/* CR35 (661 series only) + + [0] 1 = PAL, 0 = NTSC + [1] 1 = NTSC-J (if D0 = 0) + [2] 1 = PALM (if D0 = 1) + [3] 1 = PALN (if D0 = 1) + [4] 1 = Overscan (Chrontel only) + [7:5] (only if D2 in CR38 is set) + 000 525i + 001 525p + 010 750p + 011 1080i (or HiVision on 301, 301B) + + These bits are being translated to TVMode flag. + +*/ + +/* + CR37 + + [0] Set 24/18 bit (0/1) RGB to LVDS/TMDS transmitter (set by BIOS) + [3:1] External chip + 300 series: + 001 SiS301 (never seen) + 010 LVDS + 011 LVDS + Tumpion Zurac + 100 LVDS + Chrontel 7005 + 110 Chrontel 7005 + 315/330 series + 001 SiS30x (never seen) + 010 LVDS + 011 LVDS + Chrontel 7019 + 660 series [2:1] only: + reserved (now in CR38) + All other combinations reserved + [3] 661 only: Pass 1:1 data + [4] LVDS: 0: Panel Link expands / 1: Panel Link does not expand + 30x: 0: Bridge scales / 1: Bridge does not scale = Panel scales (if possible) + [5] LCD polarity select + 0: VESA DMT Standard + 1: EDID 2.x defined + [6] LCD horizontal polarity select + 0: High active + 1: Low active + [7] LCD vertical polarity select + 0: High active + 1: Low active +*/ + +/* CR37: LCDInfo */ +#define LCDRGB18Bit 0x0001 +#define LCDNonExpanding 0x0010 +#define LCDSync 0x0020 +#define LCDPass11 0x0100 /* 0: center screen, 1: Pass 1:1 data */ +#define LCDDualLink 0x0200 + +#define DontExpandLCD LCDNonExpanding +#define LCDNonExpandingShift 4 +#define DontExpandLCDShift LCDNonExpandingShift +#define LCDSyncBit 0x00e0 +#define LCDSyncShift 6 + +/* CR38 (315 series) */ +#define EnableDualEdge 0x01 +#define SetToLCDA 0x02 /* LCD channel A (301C/302B/30x(E)LV and 650+LVDS only) */ +#define EnableCHScart 0x04 /* Scart on Ch7019 (unofficial definition - TW) */ +#define EnableCHYPbPr 0x08 /* YPbPr on Ch7019 (480i HDTV); only on 650/Ch7019 systems */ +#define EnableSiSYPbPr 0x08 /* Enable YPbPr mode (30xLV/301C only) */ +#define EnableYPbPr525i 0x00 /* Enable 525i YPbPr mode (30xLV/301C only) (mask 0x30) */ +#define EnableYPbPr525p 0x10 /* Enable 525p YPbPr mode (30xLV/301C only) (mask 0x30) */ +#define EnableYPbPr750p 0x20 /* Enable 750p YPbPr mode (30xLV/301C only) (mask 0x30) */ +#define EnableYPbPr1080i 0x30 /* Enable 1080i YPbPr mode (30xLV/301C only) (mask 0x30) */ +#define EnablePALM 0x40 /* 1 = Set PALM */ +#define EnablePALN 0x80 /* 1 = Set PALN */ +#define EnableNTSCJ EnablePALM /* Not BIOS */ + +/* CR38 (661 and later) + D[7:5] 000 No VB + 001 301 series VB + 010 LVDS + 011 Chrontel 7019 + 100 Conexant + D2 Enable YPbPr output (see CR35) + D[1:0] LCDA (like before) +*/ + +#define EnablePALMN 0x40 /* Romflag: 1 = Allow PALM/PALN */ + +/* CR39 (650 only) */ +#define LCDPass1_1 0x01 /* 0: center screen, 1: pass 1:1 data output */ +#define Enable302LV_DualLink 0x04 /* 302LV only; enable dual link */ + +/* CR39 (661 and later) + D[1:0] YPbPr Aspect Ratio + 00 4:3 letterbox + 01 4:3 + 10 16:9 + 11 4:3 +*/ + +/* CR3B (651+301C) + D[1:0] YPbPr Aspect Ratio + ? +*/ + +/* CR79 (315/330 series only; not 661 and later) + [3-0] Notify driver + 0001 Mode Switch event (set by BIOS) + 0010 Epansion On/Off event + 0011 TV UnderScan/OverScan event + 0100 Set Brightness event + 0101 Set Contrast event + 0110 Set Mute event + 0111 Set Volume Up/Down event + [4] Enable Backlight Control by BIOS/driver + (set by driver; set means that the BIOS should + not touch the backlight registers because eg. + the driver already switched off the backlight) + [5] PAL/NTSC (set by BIOS) + [6] Expansion On/Off (set by BIOS; copied to CR32[4]) + [7] TV UnderScan/OverScan (set by BIOS) +*/ + +/* LCDResInfo */ +#define Panel300_800x600 0x01 /* CR36 */ +#define Panel300_1024x768 0x02 +#define Panel300_1280x1024 0x03 +#define Panel300_1280x960 0x04 +#define Panel300_640x480 0x05 +#define Panel300_1024x600 0x06 +#define Panel300_1152x768 0x07 +#define Panel300_1280x768 0x0a +#define Panel300_320x480 0x0e /* fstn - This is fake, can be any */ +#define Panel300_Custom 0x0f +#define Panel300_Barco1366 0x10 + +#define Panel310_800x600 0x01 +#define Panel310_1024x768 0x02 +#define Panel310_1280x1024 0x03 +#define Panel310_640x480 0x04 +#define Panel310_1024x600 0x05 +#define Panel310_1152x864 0x06 +#define Panel310_1280x960 0x07 +#define Panel310_1152x768 0x08 /* LVDS only */ +#define Panel310_1400x1050 0x09 +#define Panel310_1280x768 0x0a +#define Panel310_1600x1200 0x0b +#define Panel310_640x480_2 0x0c +#define Panel310_640x480_3 0x0d +#define Panel310_320x480 0x0e /* fstn - TW: This is fake, can be any */ +#define Panel310_Custom 0x0f + +#define Panel661_800x600 0x01 +#define Panel661_1024x768 0x02 +#define Panel661_1280x1024 0x03 +#define Panel661_640x480 0x04 +#define Panel661_1024x600 0x05 +#define Panel661_1152x864 0x06 +#define Panel661_1280x960 0x07 +#define Panel661_1152x768 0x08 +#define Panel661_1400x1050 0x09 +#define Panel661_1280x768 0x0a +#define Panel661_1600x1200 0x0b +#define Panel661_1280x800 0x0c +#define Panel661_1680x1050 0x0d +#define Panel661_1280x720 0x0e +#define Panel661_Custom 0x0f + +#define Panel_800x600 0x01 /* Unified values */ +#define Panel_1024x768 0x02 /* MUST match BIOS values from 0-e */ +#define Panel_1280x1024 0x03 +#define Panel_640x480 0x04 +#define Panel_1024x600 0x05 +#define Panel_1152x864 0x06 +#define Panel_1280x960 0x07 +#define Panel_1152x768 0x08 /* LVDS only */ +#define Panel_1400x1050 0x09 +#define Panel_1280x768 0x0a /* 30xB/C and LVDS only (BIOS: all) */ +#define Panel_1600x1200 0x0b +#define Panel_1280x800 0x0c /* 661etc (TMDS) */ +#define Panel_1680x1050 0x0d /* 661etc */ +#define Panel_1280x720 0x0e /* 661etc */ +#define Panel_Custom 0x0f /* MUST BE 0x0f (for DVI DDC detection) */ +#define Panel_320x480 0x10 /* SiS 550 fstn - TW: This is fake, can be any */ +#define Panel_Barco1366 0x11 +#define Panel_848x480 0x12 +#define Panel_640x480_2 0x13 /* SiS 550 */ +#define Panel_640x480_3 0x14 /* SiS 550 */ +#define Panel_1280x768_2 0x15 /* 30xLV */ +#define Panel_1280x768_3 0x16 /* (unused) */ +#define Panel_1280x800_2 0x17 /* 30xLV */ + +/* Index in ModeResInfo table */ +#define SIS_RI_320x200 0 +#define SIS_RI_320x240 1 +#define SIS_RI_320x400 2 +#define SIS_RI_400x300 3 +#define SIS_RI_512x384 4 +#define SIS_RI_640x400 5 +#define SIS_RI_640x480 6 +#define SIS_RI_800x600 7 +#define SIS_RI_1024x768 8 +#define SIS_RI_1280x1024 9 +#define SIS_RI_1600x1200 10 +#define SIS_RI_1920x1440 11 +#define SIS_RI_2048x1536 12 +#define SIS_RI_720x480 13 +#define SIS_RI_720x576 14 +#define SIS_RI_1280x960 15 +#define SIS_RI_800x480 16 +#define SIS_RI_1024x576 17 +#define SIS_RI_1280x720 18 +#define SIS_RI_856x480 19 +#define SIS_RI_1280x768 20 +#define SIS_RI_1400x1050 21 +#define SIS_RI_1152x864 22 /* Up to here SiS conforming */ +#define SIS_RI_848x480 23 +#define SIS_RI_1360x768 24 +#define SIS_RI_1024x600 25 +#define SIS_RI_1152x768 26 +#define SIS_RI_768x576 27 +#define SIS_RI_1360x1024 28 +#define SIS_RI_1680x1050 29 +#define SIS_RI_1280x800 30 +#define SIS_RI_1920x1080 31 +#define SIS_RI_960x540 32 +#define SIS_RI_960x600 33 + +/* CR5F */ +#define IsM650 0x80 + +/* Timing data */ +#define NTSCHT 1716 +#define NTSC2HT 1920 +#define NTSCVT 525 +#define PALHT 1728 +#define PALVT 625 +#define StHiTVHT 892 +#define StHiTVVT 1126 +#define StHiTextTVHT 1000 +#define StHiTextTVVT 1126 +#define ExtHiTVHT 2100 +#define ExtHiTVVT 1125 + +/* Indices in (VB)VCLKData tables */ + +#define VCLK28 0x00 /* Index in VCLKData table (300 and 315) */ +#define VCLK40 0x04 /* Index in VCLKData table (300 and 315) */ +#define VCLK65_300 0x09 /* Index in VCLKData table (300) */ +#define VCLK108_2_300 0x14 /* Index in VCLKData table (300) */ +#define VCLK81_300 0x3f /* Index in VCLKData table (300) */ +#define VCLK108_3_300 0x42 /* Index in VCLKData table (300) */ +#define VCLK100_300 0x43 /* Index in VCLKData table (300) */ +#define VCLK34_300 0x3d /* Index in VCLKData table (300) */ +#define VCLK_CUSTOM_300 0x47 +#define VCLK65_315 0x0b /* Index in (VB)VCLKData table (315) */ +#define VCLK108_2_315 0x19 /* Index in (VB)VCLKData table (315) */ +#define VCLK81_315 0x5b /* Index in (VB)VCLKData table (315) */ +#define VCLK162_315 0x5e /* Index in (VB)VCLKData table (315) */ +#define VCLK108_3_315 0x45 /* Index in VBVCLKData table (315) */ +#define VCLK100_315 0x46 /* Index in VBVCLKData table (315) */ +#define VCLK34_315 0x55 +#define VCLK68_315 0x0d +#define VCLK_1280x800_315_2 0x5c /* Index in VBVCLKData table (315) */ +#define VCLK121_315 0x5d /* Index in VBVCLKData table (315) */ +#define VCLK_1280x720 0x5f +#define VCLK_1280x768_2 0x60 +#define VCLK_1280x768_3 0x61 /* (unused?) */ +#define VCLK_CUSTOM_315 0x62 +#define VCLK_1280x720_2 0x63 +#define VCLK_720x480 0x67 +#define VCLK_720x576 0x68 +#define VCLK_768x576 0x68 +#define VCLK_848x480 0x65 +#define VCLK_856x480 0x66 +#define VCLK_800x480 0x65 +#define VCLK_1024x576 0x51 +#define VCLK_1152x864 0x64 +#define VCLK_1360x768 0x58 +#define VCLK_1280x800_315 0x6c + +#define TVCLKBASE_300 0x21 /* Indices on TV clocks in VCLKData table (300) */ +#define TVCLKBASE_315 0x3a /* Indices on TV clocks in (VB)VCLKData table (315) */ +#define TVVCLKDIV2 0x00 /* Index relative to TVCLKBASE */ +#define TVVCLK 0x01 /* Index relative to TVCLKBASE */ +#define HiTVVCLKDIV2 0x02 /* Index relative to TVCLKBASE */ +#define HiTVVCLK 0x03 /* Index relative to TVCLKBASE */ +#define HiTVSimuVCLK 0x04 /* Index relative to TVCLKBASE */ +#define HiTVTextVCLK 0x05 /* Index relative to TVCLKBASE */ +#define YPbPr750pVCLK 0x25 /* Index relative to TVCLKBASE; was 0x0f NOT relative */ + +/* ------------------------------ */ + +#define SetSCARTOutput 0x01 + +#define HotPlugFunction 0x08 + +#define StStructSize 0x06 + +#define SIS_VIDEO_CAPTURE 0x00 - 0x30 +#define SIS_VIDEO_PLAYBACK 0x02 - 0x30 +#define SIS_CRT2_PORT_04 0x04 - 0x30 +#define SIS_CRT2_PORT_10 0x10 - 0x30 +#define SIS_CRT2_PORT_12 0x12 - 0x30 +#define SIS_CRT2_PORT_14 0x14 - 0x30 + +#define ADR_CRT2PtrData 0x20E +#define offset_Zurac 0x210 /* TW: Trumpion Zurac data pointer */ +#define ADR_LVDSDesPtrData 0x212 +#define ADR_LVDSCRT1DataPtr 0x214 +#define ADR_CHTVVCLKPtr 0x216 +#define ADR_CHTVRegDataPtr 0x218 + +#define LCDDataLen 8 +#define HiTVDataLen 12 +#define TVDataLen 16 + +#define LVDSDataLen 6 +#define LVDSDesDataLen 3 +#define ActiveNonExpanding 0x40 +#define ActiveNonExpandingShift 6 +#define ActivePAL 0x20 +#define ActivePALShift 5 +#define ModeSwitchStatus 0x0F +#define SoftTVType 0x40 +#define SoftSettingAddr 0x52 +#define ModeSettingAddr 0x53 + +#define _PanelType00 0x00 +#define _PanelType01 0x08 +#define _PanelType02 0x10 +#define _PanelType03 0x18 +#define _PanelType04 0x20 +#define _PanelType05 0x28 +#define _PanelType06 0x30 +#define _PanelType07 0x38 +#define _PanelType08 0x40 +#define _PanelType09 0x48 +#define _PanelType0A 0x50 +#define _PanelType0B 0x58 +#define _PanelType0C 0x60 +#define _PanelType0D 0x68 +#define _PanelType0E 0x70 +#define _PanelType0F 0x78 + +#define PRIMARY_VGA 0 /* 1: SiS is primary vga 0:SiS is secondary vga */ + +#define BIOSIDCodeAddr 0x235 /* Offsets to ptrs in BIOS image */ +#define OEMUtilIDCodeAddr 0x237 +#define VBModeIDTableAddr 0x239 +#define OEMTVPtrAddr 0x241 +#define PhaseTableAddr 0x243 +#define NTSCFilterTableAddr 0x245 +#define PALFilterTableAddr 0x247 +#define OEMLCDPtr_1Addr 0x249 +#define OEMLCDPtr_2Addr 0x24B +#define LCDHPosTable_1Addr 0x24D +#define LCDHPosTable_2Addr 0x24F +#define LCDVPosTable_1Addr 0x251 +#define LCDVPosTable_2Addr 0x253 +#define OEMLCDPIDTableAddr 0x255 + +#define VBModeStructSize 5 +#define PhaseTableSize 4 +#define FilterTableSize 4 +#define LCDHPosTableSize 7 +#define LCDVPosTableSize 5 +#define OEMLVDSPIDTableSize 4 +#define LVDSHPosTableSize 4 +#define LVDSVPosTableSize 6 + +#define VB_ModeID 0 +#define VB_TVTableIndex 1 +#define VB_LCDTableIndex 2 +#define VB_LCDHIndex 3 +#define VB_LCDVIndex 4 + +#define OEMLCDEnable 0x0001 +#define OEMLCDDelayEnable 0x0002 +#define OEMLCDPOSEnable 0x0004 +#define OEMTVEnable 0x0100 +#define OEMTVDelayEnable 0x0200 +#define OEMTVFlickerEnable 0x0400 +#define OEMTVPhaseEnable 0x0800 +#define OEMTVFilterEnable 0x1000 + +#define OEMLCDPanelIDSupport 0x0080 + +/* + ============================================================= + for 315 series (old data layout) + ============================================================= +*/ +#define SoftDRAMType 0x80 +#define SoftSetting_OFFSET 0x52 +#define SR07_OFFSET 0x7C +#define SR15_OFFSET 0x7D +#define SR16_OFFSET 0x81 +#define SR17_OFFSET 0x85 +#define SR19_OFFSET 0x8D +#define SR1F_OFFSET 0x99 +#define SR21_OFFSET 0x9A +#define SR22_OFFSET 0x9B +#define SR23_OFFSET 0x9C +#define SR24_OFFSET 0x9D +#define SR25_OFFSET 0x9E +#define SR31_OFFSET 0x9F +#define SR32_OFFSET 0xA0 +#define SR33_OFFSET 0xA1 + +#define CR40_OFFSET 0xA2 +#define SR25_1_OFFSET 0xF6 +#define CR49_OFFSET 0xF7 + +#define VB310Data_1_2_Offset 0xB6 +#define VB310Data_4_D_Offset 0xB7 +#define VB310Data_4_E_Offset 0xB8 +#define VB310Data_4_10_Offset 0xBB + +#define RGBSenseDataOffset 0xBD +#define YCSenseDataOffset 0xBF +#define VideoSenseDataOffset 0xC1 +#define OutputSelectOffset 0xF3 + +#define ECLK_MCLK_DISTANCE 0x14 +#define VBIOSTablePointerStart 0x100 +#define StandTablePtrOffset VBIOSTablePointerStart+0x02 +#define EModeIDTablePtrOffset VBIOSTablePointerStart+0x04 +#define CRT1TablePtrOffset VBIOSTablePointerStart+0x06 +#define ScreenOffsetPtrOffset VBIOSTablePointerStart+0x08 +#define VCLKDataPtrOffset VBIOSTablePointerStart+0x0A +#define MCLKDataPtrOffset VBIOSTablePointerStart+0x0E +#define CRT2PtrDataPtrOffset VBIOSTablePointerStart+0x10 +#define TVAntiFlickPtrOffset VBIOSTablePointerStart+0x12 +#define TVDelayPtr1Offset VBIOSTablePointerStart+0x14 +#define TVPhaseIncrPtr1Offset VBIOSTablePointerStart+0x16 +#define TVYFilterPtr1Offset VBIOSTablePointerStart+0x18 +#define LCDDelayPtr1Offset VBIOSTablePointerStart+0x20 +#define TVEdgePtr1Offset VBIOSTablePointerStart+0x24 +#define CRT2Delay1Offset VBIOSTablePointerStart+0x28 + +#endif diff --git a/drivers/video/sis/oem300.h b/drivers/video/sis/oem300.h new file mode 100644 index 000000000000..b1358b750f53 --- /dev/null +++ b/drivers/video/sis/oem300.h @@ -0,0 +1,859 @@ +/* $XFree86$ */ +/* $XdotOrg$ */ +/* + * OEM Data for 300 series + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the named License, + * * or any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program; if not, write to the Free Software + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Otherwise, the following license terms apply: + * + * * Redistribution and use in source and binary forms, with or without + * * modification, are permitted provided that the following conditions + * * are met: + * * 1) Redistributions of source code must retain the above copyright + * * notice, this list of conditions and the following disclaimer. + * * 2) Redistributions in binary form must reproduce the above copyright + * * notice, this list of conditions and the following disclaimer in the + * * documentation and/or other materials provided with the distribution. + * * 3) The name of the author may not be used to endorse or promote products + * * derived from this software without specific prior written permission. + * * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + */ + +static const UCHAR SiS300_OEMTVDelay301[8][4] = +{ + {0x08,0x08,0x08,0x08}, + {0x08,0x08,0x08,0x08}, + {0x08,0x08,0x08,0x08}, + {0x2c,0x2c,0x2c,0x2c}, + {0x08,0x08,0x08,0x08}, + {0x08,0x08,0x08,0x08}, + {0x08,0x08,0x08,0x08}, + {0x20,0x20,0x20,0x20} +}; + +static const UCHAR SiS300_OEMTVDelayLVDS[8][4] = +{ + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20} +}; + +static const UCHAR SiS300_OEMTVFlicker[8][4] = +{ + {0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00} +}; + +#if 0 /* TW: Not used */ +static const UCHAR SiS300_OEMLCDDelay1[12][4]={ + {0x2c,0x2c,0x2c,0x2c}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x2c,0x2c,0x2c,0x2c}, + {0x2c,0x2c,0x2c,0x2c}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x24,0x24,0x24,0x24}, + {0x24,0x24,0x24,0x24}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x24,0x24,0x24,0x24} +}; +#endif + +/* From 630/301B BIOS */ +static const UCHAR SiS300_OEMLCDDelay2[64][4] = /* for 301/301b/302b/301LV/302LV */ +{ + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20} +}; + +/* From 300/301LV BIOS */ +static const UCHAR SiS300_OEMLCDDelay4[12][4] = +{ + {0x2c,0x2c,0x2c,0x2c}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x2c,0x2c,0x2c,0x2c}, + {0x2c,0x2c,0x2c,0x2c}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x24,0x24,0x24,0x24}, + {0x24,0x24,0x24,0x24}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x24,0x24,0x24,0x24} +}; + +/* From 300/301LV BIOS */ +static const UCHAR SiS300_OEMLCDDelay5[32][4] = +{ + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, +}; + +/* Added for LVDS */ +static const UCHAR SiS300_OEMLCDDelay3[64][4] = { /* For LVDS */ + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20}, + {0x20,0x20,0x20,0x20} +}; + +static const UCHAR SiS300_Phase1[8][5][4] = +{ + { + {0x21,0xed,0x00,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + }, + { + {0x21,0xed,0x00,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + } +}; + + +static const UCHAR SiS300_Phase2[8][5][4] = +{ + { + {0x21,0xed,0x00,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + }, + { + {0x21,0xed,0x00,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + } +}; + +static const UCHAR SiS300_Filter1[10][16][4] = +{ + { + {0x00,0xf4,0x10,0x38}, + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x10,0x18}, + {0xf7,0x06,0x19,0x14}, + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x15,0x25,0xf6}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18} + }, + { + {0x00,0xf4,0x10,0x38}, + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x10,0x32}, + {0xf3,0x00,0x1d,0x20}, + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xfc,0xfb,0x14,0x2a}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32} + }, + { + {0x00,0xf4,0x10,0x38}, + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x10,0x32}, + {0xf3,0x00,0x1d,0x20}, + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xfc,0xfb,0x14,0x2a}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32} + }, + { + {0x00,0xf4,0x10,0x38}, + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x10,0x32}, + {0xf3,0x00,0x1d,0x20}, + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xfc,0xfb,0x14,0x2a}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32} + }, + { + {0x00,0xf4,0x10,0x38}, + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x10,0x18}, + {0xf7,0x06,0x19,0x14}, + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x15,0x25,0xf6}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18} + }, + { + {0x00,0xf4,0x10,0x38}, + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x10,0x32}, + {0xf3,0x00,0x1d,0x20}, + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xfc,0xfb,0x14,0x2a}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32} + }, + { + {0x00,0xf4,0x10,0x38}, + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x10,0x32}, + {0xf3,0x00,0x1d,0x20}, + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xfc,0xfb,0x14,0x2a}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32} + }, + { + {0x00,0xf4,0x10,0x38}, + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x10,0x32}, + {0xf3,0x00,0x1d,0x20}, + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xfc,0xfb,0x14,0x2a}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32}, + {0xf1,0xf7,0x1f,0x32} + }, + { + {0x00,0xf4,0x10,0x38}, + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x10,0x18}, + {0xf7,0x06,0x19,0x14}, + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x15,0x25,0xf6}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18} + }, + { + {0x00,0xf4,0x10,0x38}, + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x10,0x18}, + {0xf7,0x06,0x19,0x14}, + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x15,0x25,0xf6}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18} + }, +}; + +static const UCHAR SiS300_Filter2[10][9][7] = +{ + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + }, + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + }, + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + }, + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + }, + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + }, + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + }, + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + }, + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + }, + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + }, + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + } +}; + +/* Custom data for Barco iQ Pro R300 */ +static const UCHAR barco_p1[2][9][7][3] = { + { + { { 0x16, 0xcf, 0x00 }, + { 0x18, 0x00, 0x00 }, + { 0x1a, 0xe7, 0x00 }, + { 0x1b, 0x26, 0x00 }, + { 0x1c, 0xff, 0x00 }, + { 0x1d, 0x1c, 0x00 }, + { 0x1e, 0x19, 0x00 } + }, + { + { 0x16, 0xcf, 0x00 }, + { 0x18, 0x00, 0x00 }, + { 0x1a, 0xe7, 0x00 }, + { 0x1b, 0x1e, 0x00 }, + { 0x1c, 0xff, 0x00 }, + { 0x1d, 0x1c, 0x00 }, + { 0x1e, 0x16, 0x00 } + }, + { + { 0x16, 0xcf, 0x00 }, + { 0x1a, 0xe7, 0x00 }, + { 0x1b, 0x26, 0x00 }, + { 0x1c, 0xff, 0x00 }, + { 0x1d, 0x1c, 0x00 }, + { 0x1e, 0x19, 0x00 }, + { 0, 0, 0 } + }, + { + { 0, 0, 0 } + }, + { + { 0x16, 0xcf, 0x00 }, + { 0x1a, 0xe7, 0x00 }, + { 0x1b, 0x26, 0x00 }, + { 0x1c, 0xff, 0x00 }, + { 0x1d, 0x1c, 0x00 }, + { 0x1e, 0x1e, 0x00 }, + { 0, 0, 0 } + }, + { + { 0x16, 0xd1, 0x00 }, + { 0x18, 0x00, 0x00 }, + { 0x1a, 0xe7, 0x00 }, + { 0x1b, 0x11, 0x00 }, + { 0x1c, 0xff, 0x00 }, + { 0x1d, 0x1c, 0x00 }, + { 0x1e, 0x26, 0x00 } + }, + { + { 0x16, 0xd1, 0x00 }, + { 0x1a, 0xe7, 0x00 }, + { 0x1b, 0x26, 0x00 }, + { 0x1c, 0xff, 0x00 }, + { 0x1d, 0x1c, 0x00 }, + { 0x1e, 0x30, 0x00 }, + { 0, 0, 0 } + }, + { + { 0x16, 0x00, 0x00 }, + { 0x17, 0xa0, 0x00 }, + { 0x1a, 0xa0, 0x00 }, + { 0x1b, 0x2a, 0x00 }, + { 0x1c, 0xff, 0x00 }, + { 0x1d, 0x1c, 0x00 }, + { 0, 0, 0 } + }, + { + { 0x16, 0x00, 0x00 }, + { 0x17, 0xaa, 0x00 }, + { 0x1a, 0xa0, 0x00 }, + { 0x1b, 0x2a, 0x00 }, + { 0x1c, 0xff, 0x00 }, + { 0x1d, 0x1c, 0x00 }, + { 0, 0, 0 } + } + }, + { + { + { 0x16, 0xcf, 0x00 }, + { 0x18, 0x00, 0x00 }, + { 0x1a, 0xe7, 0x00 }, + { 0x1b, 0x26, 0x00 }, + { 0x1c, 0xff, 0x00 }, + { 0x1d, 0x1c, 0x00 }, + { 0x1e, 0x19, 0x00 } + }, + { + { 0, 0, 0 } + }, + { + { 0x16, 0xcf, 0x00 }, + { 0x18, 0x00, 0x00 }, + { 0x1a, 0xe7, 0x00 }, + { 0x1b, 0x26, 0x00 }, + { 0x1c, 0xff, 0x00 }, + { 0x1d, 0x1c, 0x00 }, + { 0x1e, 0x19, 0x00 }, + }, + { + { 0, 0, 0 } + }, + { + { 0x16, 0xcf, 0x00 }, + { 0x18, 0x00, 0x00 }, + { 0x1a, 0xe7, 0x00 }, + { 0x1b, 0x26, 0x00 }, + { 0x1c, 0xff, 0x00 }, + { 0x1d, 0x1c, 0x00 }, + { 0x1e, 0x1e, 0x00 } + }, + { + { 0x16, 0xd1, 0x00 }, + { 0x18, 0x00, 0x00 }, + { 0x1a, 0xe6, 0x00 }, + { 0x1b, 0x11, 0x00 }, + { 0x1c, 0xff, 0x00 }, + { 0x1d, 0x1c, 0x00 }, + { 0x1e, 0x26, 0x00 } + }, + { + { 0x18, 0x00, 0x00 }, + { 0x1a, 0xe0, 0x00 }, + { 0x1b, 0x26, 0x00 }, + { 0x1c, 0xff, 0x00 }, + { 0x1d, 0x1c, 0x00 }, + { 0x1e, 0x30, 0x00 }, + { 0, 0, 0 } + }, + { + { 0, 0, 0 } + }, + { + { 0, 0, 0 } + } + } +}; + + + + + + diff --git a/drivers/video/sis/oem310.h b/drivers/video/sis/oem310.h new file mode 100644 index 000000000000..2b7db916b7e7 --- /dev/null +++ b/drivers/video/sis/oem310.h @@ -0,0 +1,449 @@ +/* $XFree86$ */ +/* $XdotOrg$ */ +/* + * OEM Data for 315/330 series + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the named License, + * * or any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program; if not, write to the Free Software + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Otherwise, the following license terms apply: + * + * * Redistribution and use in source and binary forms, with or without + * * modification, are permitted provided that the following conditions + * * are met: + * * 1) Redistributions of source code must retain the above copyright + * * notice, this list of conditions and the following disclaimer. + * * 2) Redistributions in binary form must reproduce the above copyright + * * notice, this list of conditions and the following disclaimer in the + * * documentation and/or other materials provided with the distribution. + * * 3) The name of the author may not be used to endorse or promote products + * * derived from this software without specific prior written permission. + * * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + */ + +static const UCHAR SiS310_LCDDelayCompensation_301[] = /* 301 */ +{ + 0x00,0x00,0x00, /* 800x600 */ + 0x0b,0x0b,0x0b, /* 1024x768 */ + 0x08,0x08,0x08, /* 1280x1024 */ + 0x00,0x00,0x00, /* 640x480 (unknown) */ + 0x00,0x00,0x00, /* 1024x600 (unknown) */ + 0x00,0x00,0x00, /* 1152x864 (unknown) */ + 0x08,0x08,0x08, /* 1280x960 (guessed) */ + 0x00,0x00,0x00, /* 1152x768 (unknown) */ + 0x08,0x08,0x08, /* 1400x1050 */ + 0x08,0x08,0x08, /* 1280x768 (guessed) */ + 0x00,0x00,0x00, /* 1600x1200 */ + 0x00,0x00,0x00, /* 320x480 (unknown) */ + 0x00,0x00,0x00, + 0x00,0x00,0x00, + 0x00,0x00,0x00 +}; + +/* This is contained in 650+301B BIOSes, but it is wrong - so we don't use it */ +static const UCHAR SiS310_LCDDelayCompensation_650301LV[] = /* 650 + 30xLV */ +{ + 0x01,0x01,0x01, /* 800x600 */ + 0x01,0x01,0x01, /* 1024x768 */ + 0x01,0x01,0x01, /* 1280x1024 */ + 0x01,0x01,0x01, /* 640x480 (unknown) */ + 0x01,0x01,0x01, /* 1024x600 (unknown) */ + 0x01,0x01,0x01, /* 1152x864 (unknown) */ + 0x01,0x01,0x01, /* 1280x960 (guessed) */ + 0x01,0x01,0x01, /* 1152x768 (unknown) */ + 0x01,0x01,0x01, /* 1400x1050 */ + 0x01,0x01,0x01, /* 1280x768 (guessed) */ + 0x01,0x01,0x01, /* 1600x1200 */ + 0x02,0x02,0x02, + 0x02,0x02,0x02, + 0x02,0x02,0x02, + 0x02,0x02,0x02 +}; + +static const UCHAR SiS310_LCDDelayCompensation_651301LV[] = /* M650/651 301LV */ +{ + 0x33,0x33,0x33, /* 800x600 (guessed) - new: PanelType, not PanelRes ! */ + 0x33,0x33,0x33, /* 1024x768 */ + 0x33,0x33,0x33, /* 1280x1024 */ + 0x33,0x33,0x33, /* 640x480 (unknown) */ + 0x33,0x33,0x33, /* 1024x600 (unknown) */ + 0x33,0x33,0x33, /* 1152x864 (unknown) */ + 0x33,0x33,0x33, /* 1280x960 (guessed) */ + 0x33,0x33,0x33, /* 1152x768 (unknown) */ + 0x33,0x33,0x33, /* 1400x1050 */ + 0x33,0x33,0x33, /* 1280x768 (guessed) */ + 0x33,0x33,0x33, /* 1600x1200 */ + 0x33,0x33,0x33, + 0x33,0x33,0x33, + 0x33,0x33,0x33, + 0x33,0x33,0x33 +}; + +static const UCHAR SiS310_LCDDelayCompensation_651302LV[] = /* M650/651 302LV */ +{ + 0x33,0x33,0x33, /* 800x600 (guessed) */ + 0x33,0x33,0x33, /* 1024x768 */ + 0x33,0x33,0x33, /* 1280x1024 */ + 0x33,0x33,0x33, /* 640x480 (unknown) */ + 0x33,0x33,0x33, /* 1024x600 (unknown) */ + 0x33,0x33,0x33, /* 1152x864 (unknown) */ + 0x33,0x33,0x33, /* 1280x960 (guessed) */ + 0x33,0x33,0x33, /* 1152x768 (unknown) */ + 0x33,0x33,0x33, /* 1400x1050 */ + 0x33,0x33,0x33, /* 1280x768 (guessed) */ + 0x33,0x33,0x33, /* 1600x1200 */ + 0x33,0x33,0x33, + 0x33,0x33,0x33, + 0x33,0x33,0x33, + 0x33,0x33,0x33 +}; + +static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] = /* 30xB */ +{ + 0x01,0x01,0x01, /* 800x600 */ + 0x0C,0x0C,0x0C, /* 1024x768 */ + 0x0C,0x0C,0x0C, /* 1280x1024 */ + 0x08,0x08,0x08, /* 640x480 */ + 0x0C,0x0C,0x0C, /* 1024x600 (guessed) */ + 0x0C,0x0C,0x0C, /* 1152x864 (guessed) */ + 0x0C,0x0C,0x0C, /* 1280x960 (guessed) */ + 0x0C,0x0C,0x0C, /* 1152x768 (guessed) */ + 0x0C,0x0C,0x0C, /* 1400x1050 (guessed) */ + 0x0C,0x0C,0x0C, /* 1280x768 (guessed) */ + 0x0C,0x0C,0x0C, /* 1600x1200 (guessed) */ + 0x02,0x02,0x02, + 0x02,0x02,0x02, + 0x02,0x02,0x02, + 0x02,0x02,0x02 +}; + +static const UCHAR SiS310_LCDDelayCompensation_3xx301LV[] = /* 315+30xLV */ +{ + 0x01,0x01,0x01, /* 800x600 */ + 0x04,0x04,0x04, /* 1024x768 (A531/BIOS 1.14.05f: 4 - works with 6 */ + 0x0C,0x0C,0x0C, /* 1280x1024 */ + 0x08,0x08,0x08, /* 640x480 */ + 0x0C,0x0C,0x0C, /* 1024x600 (guessed) */ + 0x0C,0x0C,0x0C, /* 1152x864 (guessed) */ + 0x0C,0x0C,0x0C, /* 1280x960 (guessed) */ + 0x0C,0x0C,0x0C, /* 1152x768 (guessed) */ + 0x0C,0x0C,0x0C, /* 1400x1050 (guessed) */ + 0x0C,0x0C,0x0C, /* 1280x768 (guessed) */ + 0x0C,0x0C,0x0C, /* 1600x1200 (guessed) */ + 0x02,0x02,0x02, + 0x02,0x02,0x02, + 0x02,0x02,0x02, + 0x02,0x02,0x02 +}; + +static const UCHAR SiS310_TVDelayCompensation_301[] = /* 301 */ +{ + 0x02,0x02, /* NTSC Enhanced, Standard */ + 0x02,0x02, /* PAL */ + 0x08,0x0b /* HiVision */ +}; + +static const UCHAR SiS310_TVDelayCompensation_301B[] = /* 30xB, 30xLV */ +{ + 0x03,0x03, + 0x03,0x03, + 0x03,0x03 +}; + +static const UCHAR SiS310_TVDelayCompensation_740301B[] = /* 740 + 30xB (30xLV?) */ +{ + 0x05,0x05, + 0x05,0x05, + 0x05,0x05 +}; + +static const UCHAR SiS310_TVDelayCompensation_651301LV[] = /* M650, 651, 301LV */ +{ + 0x33,0x33, + 0x33,0x33, + 0x33,0x33 +}; + +static const UCHAR SiS310_TVDelayCompensation_651302LV[] = /* M650, 651, 302LV */ +{ + 0x33,0x33, + 0x33,0x33, + 0x33,0x33 +}; + +static const UCHAR SiS_TVDelay661_301[] = /* 661, 301 */ +{ + 0x44,0x44, + 0x44,0x44, + 0x00,0x00, + 0x44,0x44, + 0x44,0x44, + 0x44,0x44 +}; + +static const UCHAR SiS_TVDelay661_301B[] = /* 661, 301B et al */ +{ + 0x44,0x44, + 0x44,0x44, + 0x00,0x00, + 0x44,0x44, + 0x44,0x44, + 0x44,0x44 +}; + +static const UCHAR SiS310_TVDelayCompensation_LVDS[] = /* LVDS */ +{ + 0x0a,0x0a, + 0x0a,0x0a, + 0x0a,0x0a +}; + +static const UCHAR SiS310_TVAntiFlick1[6][2] = +{ + {0x4,0x0}, + {0x4,0x8}, + {0x0,0x0}, + {0x0,0x0}, + {0x0,0x0}, + {0x0,0x0} +}; + +static const UCHAR SiS310_TVEdge1[6][2] = +{ + {0x0,0x4}, + {0x0,0x4}, + {0x0,0x0}, + {0x0,0x0}, + {0x0,0x0}, + {0x0,0x0} +}; + +static const UCHAR SiS310_TVYFilter1[5][8][4] = +{ + { + {0x00,0xf4,0x10,0x38}, /* NTSC */ + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x25,0x18}, + {0xf1,0x04,0x1f,0x18}, + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x25,0x18}, + {0xee,0x0c,0x22,0x08}, + {0xeb,0x15,0x25,0xf6} + }, + { + {0x00,0xf4,0x10,0x38}, /* PAL */ + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x1f,0x32}, + {0xf3,0x00,0x1d,0x20}, + {0x00,0xf4,0x10,0x38}, + {0xf1,0xf7,0x1f,0x32}, + {0xf3,0x00,0x1d,0x20}, + {0xfc,0xfb,0x14,0x2a} + }, + { + {0x00,0x00,0x00,0x00}, /* HiVision */ + {0x00,0xf4,0x10,0x38}, + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x25,0x18}, + {0xf7,0x06,0x19,0x14}, + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x25,0x18}, + {0xee,0x0c,0x22,0x08} + }, + { + {0x00,0xf4,0x10,0x38}, /* PAL-M */ + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x10,0x18}, + {0xf7,0x06,0x19,0x14}, + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x15,0x25,0xf6} + }, + { + {0x00,0xf4,0x10,0x38}, /* PAL-N */ + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x10,0x18}, + {0xf7,0x06,0x19,0x14}, + {0x00,0xf4,0x10,0x38}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x04,0x25,0x18}, + {0xeb,0x15,0x25,0xf6} + } +}; + +static const UCHAR SiS310_TVYFilter2[5][9][7] = +{ + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* NTSC */ + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + }, + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* PAL */ + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + }, + { + {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}, /* HiVision */ + {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}, + {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}, + {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}, + {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}, + {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}, + {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}, + {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}, + {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22} + }, + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* PAL-M */ + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + }, + { + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, /* PAL-N */ + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46}, + {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C}, + {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38}, + {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28} + } +}; + +static const UCHAR SiS310_TVPhaseIncr1[3][2][4] = +{ + { + {0x21,0xed,0xba,0x08}, + {0x21,0xed,0xba,0x08} + }, + { + {0x2a,0x05,0xe3,0x00}, + {0x2a,0x05,0xe3,0x00} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + } +}; + +static const UCHAR SiS310_TVPhaseIncr2[3][2][4] = +{ + { + {0x21,0xf0,0x7b,0xd6}, + {0x21,0xf0,0x7b,0xd6} + }, + { + {0x2a,0x0a,0x41,0xe9}, + {0x2a,0x0a,0x41,0xe9} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + } +}; + +static const UCHAR SiS661_TVPhase[] = { + 0x21,0xED,0xBA,0x08, + 0x2A,0x05,0xE3,0x00, + 0x21,0xE4,0x2E,0x9B, + 0x21,0xF4,0x3E,0xBA, + 0x1E,0x8B,0xA2,0xA7, + 0x1E,0x83,0x0A,0xE0, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x21,0xF0,0x7B,0xD6, + 0x2A,0x09,0x86,0xE9, + 0x21,0xE6,0xEF,0xA4, + 0x21,0xF6,0x94,0x46, + 0x1E,0x8B,0xA2,0xA7, + 0x1E,0x83,0x0A,0xE0, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00 +}; + +/**************************************************************/ +/* CUSTOM TIMING DATA --------------------------------------- */ +/**************************************************************/ + +/* Inventec / Compaq Presario 3045US, 3017 */ + +static const SiS_LCDDataStruct SiS310_ExtCompaq1280x1024Data[] = +{ + { 211, 60,1024, 501,1688,1066}, + { 211, 60,1024, 508,1688,1066}, + { 211, 60,1024, 501,1688,1066}, + { 211, 60,1024, 508,1688,1066}, + { 32, 15,1696, 501,1696,1066}, + { 212, 75,1024, 621,1696,1066}, + { 4, 3,1696, 810,1696,1066}, + { 1, 1,1696,1066,1696,1066} +}; + +/* Asus A2xxxH _2 */ + +static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Asus1024x768_3[] = +{ + {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x38,0x13,0x16,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}} +}; + + + + diff --git a/drivers/video/sis/osdef.h b/drivers/video/sis/osdef.h new file mode 100644 index 000000000000..15939b057713 --- /dev/null +++ b/drivers/video/sis/osdef.h @@ -0,0 +1,131 @@ +/* $XFree86$ */ +/* $XdotOrg$ */ +/* + * OS depending defines + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the named License, + * * or any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program; if not, write to the Free Software + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Otherwise, the following license terms apply: + * + * * Redistribution and use in source and binary forms, with or without + * * modification, are permitted provided that the following conditions + * * are met: + * * 1) Redistributions of source code must retain the above copyright + * * notice, this list of conditions and the following disclaimer. + * * 2) Redistributions in binary form must reproduce the above copyright + * * notice, this list of conditions and the following disclaimer in the + * * documentation and/or other materials provided with the distribution. + * * 3) The name of the author may not be used to endorse or promote products + * * derived from this software without specific prior written permission. + * * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * Silicon Integrated Systems, Inc. (used by permission) + * + */ + +#ifndef _SIS_OSDEF_H_ +#define _SIS_OSDEF_H_ + +/* The choices are: */ +#define LINUX_KERNEL /* Linux kernel framebuffer */ +/* #define LINUX_XF86 */ /* XFree86/X.org */ + +#ifdef OutPortByte +#undef OutPortByte +#endif + +#ifdef OutPortWord +#undef OutPortWord +#endif + +#ifdef OutPortLong +#undef OutPortLong +#endif + +#ifdef InPortByte +#undef InPortByte +#endif + +#ifdef InPortWord +#undef InPortWord +#endif + +#ifdef InPortLong +#undef InPortLong +#endif + +/**********************************************************************/ +/* LINUX KERNEL */ +/**********************************************************************/ + +#ifdef LINUX_KERNEL +#include <linux/config.h> + +#ifdef CONFIG_FB_SIS_300 +#define SIS300 +#endif + +#ifdef CONFIG_FB_SIS_315 +#define SIS315H +#endif + +#if !defined(SIS300) && !defined(SIS315H) +#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set +#warning sisfb will not work! +#endif + +#define OutPortByte(p,v) outb((u8)(v),(SISIOADDRESS)(p)) +#define OutPortWord(p,v) outw((u16)(v),(SISIOADDRESS)(p)) +#define OutPortLong(p,v) outl((u32)(v),(SISIOADDRESS)(p)) +#define InPortByte(p) inb((SISIOADDRESS)(p)) +#define InPortWord(p) inw((SISIOADDRESS)(p)) +#define InPortLong(p) inl((SISIOADDRESS)(p)) +#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset_io(MemoryAddress, value, MemorySize) +#endif + +/**********************************************************************/ +/* XFree86/X.org */ +/**********************************************************************/ + +#ifdef LINUX_XF86 +#define SIS300 +#define SIS315H + +#define OutPortByte(p,v) outSISREG((IOADDRESS)(p),(CARD8)(v)) +#define OutPortWord(p,v) outSISREGW((IOADDRESS)(p),(CARD16)(v)) +#define OutPortLong(p,v) outSISREGL((IOADDRESS)(p),(CARD32)(v)) +#define InPortByte(p) inSISREG((IOADDRESS)(p)) +#define InPortWord(p) inSISREGW((IOADDRESS)(p)) +#define InPortLong(p) inSISREGL((IOADDRESS)(p)) +#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize) +#endif + +#endif /* _OSDEF_H_ */ diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h new file mode 100644 index 000000000000..d0103c162e43 --- /dev/null +++ b/drivers/video/sis/sis.h @@ -0,0 +1,573 @@ +/* + * SiS 300/630/730/540/315/550/[M]650/651/[M]661[FM]X/740/[M]741[GX]/330/[M]760[GX] + * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3 + * + * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the named License, + * or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef _SIS_H +#define _SIS_H + +#include <linux/config.h> +#include <linux/version.h> + +#include "osdef.h" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#include <video/sisfb.h> +#else +#include <linux/sisfb.h> +#endif + +#include "vgatypes.h" +#include "vstruct.h" + +#define VER_MAJOR 1 +#define VER_MINOR 7 +#define VER_LEVEL 17 + +#undef SIS_CONFIG_COMPAT + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#include <linux/spinlock.h> +#ifdef CONFIG_COMPAT +#include <linux/ioctl32.h> +#define SIS_CONFIG_COMPAT +#endif +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19) +#ifdef __x86_64__ +/* Shouldn't we check for CONFIG_IA32_EMULATION here? */ +#include <asm/ioctl32.h> +#define SIS_CONFIG_COMPAT +#endif +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) +#define SIS_IOTYPE1 void __iomem +#define SIS_IOTYPE2 __iomem +#define SISINITSTATIC static +#else +#define SIS_IOTYPE1 unsigned char +#define SIS_IOTYPE2 +#define SISINITSTATIC +#endif + +#undef SISFBDEBUG + +#ifdef SISFBDEBUG +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +#define TWDEBUG(x) printk(KERN_INFO x "\n"); +#else +#define DPRINTK(fmt, args...) +#define TWDEBUG(x) +#endif + +#define SISFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0) + +/* To be included in pci_ids.h */ +#ifndef PCI_DEVICE_ID_SI_650_VGA +#define PCI_DEVICE_ID_SI_650_VGA 0x6325 +#endif +#ifndef PCI_DEVICE_ID_SI_650 +#define PCI_DEVICE_ID_SI_650 0x0650 +#endif +#ifndef PCI_DEVICE_ID_SI_651 +#define PCI_DEVICE_ID_SI_651 0x0651 +#endif +#ifndef PCI_DEVICE_ID_SI_740 +#define PCI_DEVICE_ID_SI_740 0x0740 +#endif +#ifndef PCI_DEVICE_ID_SI_330 +#define PCI_DEVICE_ID_SI_330 0x0330 +#endif +#ifndef PCI_DEVICE_ID_SI_660_VGA +#define PCI_DEVICE_ID_SI_660_VGA 0x6330 +#endif +#ifndef PCI_DEVICE_ID_SI_661 +#define PCI_DEVICE_ID_SI_661 0x0661 +#endif +#ifndef PCI_DEVICE_ID_SI_741 +#define PCI_DEVICE_ID_SI_741 0x0741 +#endif +#ifndef PCI_DEVICE_ID_SI_660 +#define PCI_DEVICE_ID_SI_660 0x0660 +#endif +#ifndef PCI_DEVICE_ID_SI_760 +#define PCI_DEVICE_ID_SI_760 0x0760 +#endif + +/* To be included in fb.h */ +#ifndef FB_ACCEL_SIS_GLAMOUR_2 +#define FB_ACCEL_SIS_GLAMOUR_2 40 /* SiS 315, 65x, 740, 661, 741 */ +#endif +#ifndef FB_ACCEL_SIS_XABRE +#define FB_ACCEL_SIS_XABRE 41 /* SiS 330 ("Xabre"), 760 */ +#endif + +#define MAX_ROM_SCAN 0x10000 + +/* ivideo->caps */ +#define HW_CURSOR_CAP 0x80 +#define TURBO_QUEUE_CAP 0x40 +#define AGP_CMD_QUEUE_CAP 0x20 +#define VM_CMD_QUEUE_CAP 0x10 +#define MMIO_CMD_QUEUE_CAP 0x08 + +/* For 300 series */ +#define TURBO_QUEUE_AREA_SIZE 0x80000 /* 512K */ +#define HW_CURSOR_AREA_SIZE_300 0x1000 /* 4K */ + +/* For 315/Xabre series */ +#define COMMAND_QUEUE_AREA_SIZE 0x80000 /* 512K */ +#define COMMAND_QUEUE_THRESHOLD 0x1F +#define HW_CURSOR_AREA_SIZE_315 0x4000 /* 16K */ + +#define SIS_OH_ALLOC_SIZE 4000 +#define SENTINEL 0x7fffffff + +#define SEQ_ADR 0x14 +#define SEQ_DATA 0x15 +#define DAC_ADR 0x18 +#define DAC_DATA 0x19 +#define CRTC_ADR 0x24 +#define CRTC_DATA 0x25 +#define DAC2_ADR (0x16-0x30) +#define DAC2_DATA (0x17-0x30) +#define VB_PART1_ADR (0x04-0x30) +#define VB_PART1_DATA (0x05-0x30) +#define VB_PART2_ADR (0x10-0x30) +#define VB_PART2_DATA (0x11-0x30) +#define VB_PART3_ADR (0x12-0x30) +#define VB_PART3_DATA (0x13-0x30) +#define VB_PART4_ADR (0x14-0x30) +#define VB_PART4_DATA (0x15-0x30) + +#define SISSR ivideo->SiS_Pr.SiS_P3c4 +#define SISCR ivideo->SiS_Pr.SiS_P3d4 +#define SISDACA ivideo->SiS_Pr.SiS_P3c8 +#define SISDACD ivideo->SiS_Pr.SiS_P3c9 +#define SISPART1 ivideo->SiS_Pr.SiS_Part1Port +#define SISPART2 ivideo->SiS_Pr.SiS_Part2Port +#define SISPART3 ivideo->SiS_Pr.SiS_Part3Port +#define SISPART4 ivideo->SiS_Pr.SiS_Part4Port +#define SISPART5 ivideo->SiS_Pr.SiS_Part5Port +#define SISDAC2A SISPART5 +#define SISDAC2D (SISPART5 + 1) +#define SISMISCR (ivideo->SiS_Pr.RelIO + 0x1c) +#define SISMISCW ivideo->SiS_Pr.SiS_P3c2 +#define SISINPSTAT (ivideo->SiS_Pr.RelIO + 0x2a) +#define SISPEL ivideo->SiS_Pr.SiS_P3c6 + +#define IND_SIS_PASSWORD 0x05 /* SRs */ +#define IND_SIS_COLOR_MODE 0x06 +#define IND_SIS_RAMDAC_CONTROL 0x07 +#define IND_SIS_DRAM_SIZE 0x14 +#define IND_SIS_MODULE_ENABLE 0x1E +#define IND_SIS_PCI_ADDRESS_SET 0x20 +#define IND_SIS_TURBOQUEUE_ADR 0x26 +#define IND_SIS_TURBOQUEUE_SET 0x27 +#define IND_SIS_POWER_ON_TRAP 0x38 +#define IND_SIS_POWER_ON_TRAP2 0x39 +#define IND_SIS_CMDQUEUE_SET 0x26 +#define IND_SIS_CMDQUEUE_THRESHOLD 0x27 + +#define IND_SIS_AGP_IO_PAD 0x48 + +#define SIS_CRT2_WENABLE_300 0x24 /* Part1 */ +#define SIS_CRT2_WENABLE_315 0x2F + +#define SIS_PASSWORD 0x86 /* SR05 */ + +#define SIS_INTERLACED_MODE 0x20 /* SR06 */ +#define SIS_8BPP_COLOR_MODE 0x0 +#define SIS_15BPP_COLOR_MODE 0x1 +#define SIS_16BPP_COLOR_MODE 0x2 +#define SIS_32BPP_COLOR_MODE 0x4 + +#define SIS_ENABLE_2D 0x40 /* SR1E */ + +#define SIS_MEM_MAP_IO_ENABLE 0x01 /* SR20 */ +#define SIS_PCI_ADDR_ENABLE 0x80 + +#define SIS_AGP_CMDQUEUE_ENABLE 0x80 /* 315/330 series SR26 */ +#define SIS_VRAM_CMDQUEUE_ENABLE 0x40 +#define SIS_MMIO_CMD_ENABLE 0x20 +#define SIS_CMD_QUEUE_SIZE_512k 0x00 +#define SIS_CMD_QUEUE_SIZE_1M 0x04 +#define SIS_CMD_QUEUE_SIZE_2M 0x08 +#define SIS_CMD_QUEUE_SIZE_4M 0x0C +#define SIS_CMD_QUEUE_RESET 0x01 +#define SIS_CMD_AUTO_CORR 0x02 + +#define SIS_SIMULTANEOUS_VIEW_ENABLE 0x01 /* CR30 */ +#define SIS_MODE_SELECT_CRT2 0x02 +#define SIS_VB_OUTPUT_COMPOSITE 0x04 +#define SIS_VB_OUTPUT_SVIDEO 0x08 +#define SIS_VB_OUTPUT_SCART 0x10 +#define SIS_VB_OUTPUT_LCD 0x20 +#define SIS_VB_OUTPUT_CRT2 0x40 +#define SIS_VB_OUTPUT_HIVISION 0x80 + +#define SIS_VB_OUTPUT_DISABLE 0x20 /* CR31 */ +#define SIS_DRIVER_MODE 0x40 + +#define SIS_VB_COMPOSITE 0x01 /* CR32 */ +#define SIS_VB_SVIDEO 0x02 +#define SIS_VB_SCART 0x04 +#define SIS_VB_LCD 0x08 +#define SIS_VB_CRT2 0x10 +#define SIS_CRT1 0x20 +#define SIS_VB_HIVISION 0x40 +#define SIS_VB_YPBPR 0x80 +#define SIS_VB_TV (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \ + SIS_VB_SCART | SIS_VB_HIVISION | SIS_VB_YPBPR) + +#define SIS_EXTERNAL_CHIP_MASK 0x0E /* CR37 (< SiS 660) */ +#define SIS_EXTERNAL_CHIP_SIS301 0x01 /* in CR37 << 1 ! */ +#define SIS_EXTERNAL_CHIP_LVDS 0x02 +#define SIS_EXTERNAL_CHIP_TRUMPION 0x03 +#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL 0x04 +#define SIS_EXTERNAL_CHIP_CHRONTEL 0x05 +#define SIS310_EXTERNAL_CHIP_LVDS 0x02 +#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03 + +#define SIS_AGP_2X 0x20 /* CR48 */ + +#define HW_DEVICE_EXTENSION SIS_HW_INFO +#define PHW_DEVICE_EXTENSION PSIS_HW_INFO + +/* I/O port access macros */ +#define inSISREG(base) inb(base) + +#define outSISREG(base,val) outb(val,base) + +#define orSISREG(base,val) \ + do { \ + u8 __Temp = inSISREG(base); \ + outSISREG(base, __Temp | (val)); \ + } while (0) + +#define andSISREG(base,val) \ + do { \ + u8 __Temp = inSISREG(base); \ + outSISREG(base, __Temp & (val)); \ + } while (0) + +#define inSISIDXREG(base,idx,var) \ + do { \ + outSISREG(base, idx); \ + var = inSISREG((base)+1); \ + } while (0) + +#define outSISIDXREG(base,idx,val) \ + do { \ + outSISREG(base, idx); \ + outSISREG((base)+1, val); \ + } while (0) + +#define orSISIDXREG(base,idx,val) \ + do { \ + u8 __Temp; \ + outSISREG(base, idx); \ + __Temp = inSISREG((base)+1) | (val); \ + outSISREG((base)+1, __Temp); \ + } while (0) + +#define andSISIDXREG(base,idx,and) \ + do { \ + u8 __Temp; \ + outSISREG(base, idx); \ + __Temp = inSISREG((base)+1) & (and); \ + outSISREG((base)+1, __Temp); \ + } while (0) + +#define setSISIDXREG(base,idx,and,or) \ + do { \ + u8 __Temp; \ + outSISREG(base, idx); \ + __Temp = (inSISREG((base)+1) & (and)) | (or); \ + outSISREG((base)+1, __Temp); \ + } while (0) + +/* MMIO access macros */ +#define MMIO_IN8(base, offset) readb((base+offset)) +#define MMIO_IN16(base, offset) readw((base+offset)) +#define MMIO_IN32(base, offset) readl((base+offset)) + +#define MMIO_OUT8(base, offset, val) writeb(((u8)(val)), (base+offset)) +#define MMIO_OUT16(base, offset, val) writew(((u16)(val)), (base+offset)) +#define MMIO_OUT32(base, offset, val) writel(((u32)(val)), (base+offset)) + +/* Queue control MMIO registers */ +#define Q_BASE_ADDR 0x85C0 /* Base address of software queue */ +#define Q_WRITE_PTR 0x85C4 /* Current write pointer */ +#define Q_READ_PTR 0x85C8 /* Current read pointer */ +#define Q_STATUS 0x85CC /* queue status */ + +#define MMIO_QUEUE_PHYBASE Q_BASE_ADDR +#define MMIO_QUEUE_WRITEPORT Q_WRITE_PTR +#define MMIO_QUEUE_READPORT Q_READ_PTR + +#ifndef FB_BLANK_UNBLANK +#define FB_BLANK_UNBLANK 0 +#endif +#ifndef FB_BLANK_NORMAL +#define FB_BLANK_NORMAL 1 +#endif +#ifndef FB_BLANK_VSYNC_SUSPEND +#define FB_BLANK_VSYNC_SUSPEND 2 +#endif +#ifndef FB_BLANK_HSYNC_SUSPEND +#define FB_BLANK_HSYNC_SUSPEND 3 +#endif +#ifndef FB_BLANK_POWERDOWN +#define FB_BLANK_POWERDOWN 4 +#endif + +enum _SIS_LCD_TYPE { + LCD_INVALID = 0, + LCD_800x600, + LCD_1024x768, + LCD_1280x1024, + LCD_1280x960, + LCD_640x480, + LCD_1600x1200, + LCD_1920x1440, + LCD_2048x1536, + LCD_320x480, /* FSTN */ + LCD_1400x1050, + LCD_1152x864, + LCD_1152x768, + LCD_1280x768, + LCD_1024x600, + LCD_640x480_2, /* DSTN */ + LCD_640x480_3, /* DSTN */ + LCD_848x480, + LCD_1280x800, + LCD_1680x1050, + LCD_1280x720, + LCD_CUSTOM, + LCD_UNKNOWN +}; + +enum _SIS_CMDTYPE { + MMIO_CMD = 0, + AGP_CMD_QUEUE, + VM_CMD_QUEUE, +}; +typedef unsigned int SIS_CMDTYPE; + +/* Our "par" */ +struct sis_video_info { + int cardnumber; + struct fb_info *memyselfandi; + + SIS_HW_INFO sishw_ext; + SiS_Private SiS_Pr; + + sisfb_info sisfbinfo; /* For ioctl SISFB_GET_INFO */ + + struct fb_var_screeninfo default_var; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + struct fb_fix_screeninfo sisfb_fix; + u32 pseudo_palette[17]; +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + struct display sis_disp; + struct display_switch sisfb_sw; + struct { + u16 red, green, blue, pad; + } sis_palette[256]; + union { +#ifdef FBCON_HAS_CFB16 + u16 cfb16[16]; +#endif +#ifdef FBCON_HAS_CFB32 + u32 cfb32[16]; +#endif + } sis_fbcon_cmap; +#endif + + struct sisfb_monitor { + u16 hmin; + u16 hmax; + u16 vmin; + u16 vmax; + u32 dclockmax; + u8 feature; + BOOLEAN datavalid; + } sisfb_thismonitor; + + int chip_id; + char myid[40]; + + struct pci_dev *nbridge; + + int mni; /* Mode number index */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + int currcon; +#endif + + unsigned long video_size; + unsigned long video_base; + unsigned long mmio_size; + unsigned long mmio_base; + unsigned long vga_base; + + SIS_IOTYPE1 *video_vbase; + SIS_IOTYPE1 *mmio_vbase; + + unsigned char *bios_abase; + + int mtrr; + + u32 sisfb_mem; + + u32 sisfb_parm_mem; + int sisfb_accel; + int sisfb_ypan; + int sisfb_max; + int sisfb_userom; + int sisfb_useoem; + int sisfb_mode_idx; + int sisfb_parm_rate; + int sisfb_crt1off; + int sisfb_forcecrt1; + int sisfb_crt2type; + int sisfb_crt2flags; + int sisfb_dstn; + int sisfb_fstn; + int sisfb_tvplug; + int sisfb_tvstd; + int sisfb_filter; + int sisfb_nocrt2rate; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + int sisfb_inverse; +#endif + + u32 heapstart; /* offset */ + SIS_IOTYPE1 *sisfb_heap_start; /* address */ + SIS_IOTYPE1 *sisfb_heap_end; /* address */ + u32 sisfb_heap_size; + int havenoheap; +#if 0 + SIS_HEAP sisfb_heap; +#endif + + + int video_bpp; + int video_cmap_len; + int video_width; + int video_height; + unsigned int refresh_rate; + + unsigned int chip; + u8 revision_id; + + int video_linelength; /* real pitch */ + int scrnpitchCRT1; /* pitch regarding interlace */ + + u16 DstColor; /* For 2d acceleration */ + u32 SiS310_AccelDepth; + u32 CommandReg; + int cmdqueuelength; + + spinlock_t lockaccel; /* Do not use outside of kernel! */ + + unsigned int pcibus; + unsigned int pcislot; + unsigned int pcifunc; + + int accel; + + u16 subsysvendor; + u16 subsysdevice; + + u32 vbflags; /* Replacing deprecated stuff from above */ + u32 currentvbflags; + + int lcdxres, lcdyres; + int lcddefmodeidx, tvdefmodeidx, defmodeidx; + u32 CRT2LCDType; /* defined in "SIS_LCD_TYPE" */ + + int current_bpp; + int current_width; + int current_height; + int current_htotal; + int current_vtotal; + int current_linelength; + __u32 current_pixclock; + int current_refresh_rate; + + u8 mode_no; + u8 rate_idx; + int modechanged; + unsigned char modeprechange; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + u8 sisfb_lastrates[128]; +#endif + + int newrom; + int registered; + int warncount; + + int sisvga_engine; + int hwcursor_size; + int CRT2_write_enable; + u8 caps; + + u8 detectedpdc; + u8 detectedpdca; + u8 detectedlcda; + + SIS_IOTYPE1 *hwcursor_vbase; + + int chronteltype; + int tvxpos, tvypos; + u8 p2_1f,p2_20,p2_2b,p2_42,p2_43,p2_01,p2_02; + int tvx, tvy; + + u8 sisfblocked; + + struct sis_video_info *next; +}; + +typedef struct _SIS_OH { + struct _SIS_OH *poh_next; + struct _SIS_OH *poh_prev; + u32 offset; + u32 size; +} SIS_OH; + +typedef struct _SIS_OHALLOC { + struct _SIS_OHALLOC *poha_next; + SIS_OH aoh[1]; +} SIS_OHALLOC; + +typedef struct _SIS_HEAP { + SIS_OH oh_free; + SIS_OH oh_used; + SIS_OH *poh_freelist; + SIS_OHALLOC *poha_chain; + u32 max_freesize; + struct sis_video_info *vinfo; +} SIS_HEAP; + +#endif diff --git a/drivers/video/sis/sis_accel.c b/drivers/video/sis/sis_accel.c new file mode 100644 index 000000000000..30e90a553e80 --- /dev/null +++ b/drivers/video/sis/sis_accel.c @@ -0,0 +1,678 @@ +/* + * SiS 300/630/730/540/315/550/65x/74x/330/760 frame buffer driver + * for Linux kernels 2.4.x and 2.6.x + * + * 2D acceleration part + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the named License, + * or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Based on the XFree86/X.org driver which is + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * (see http://www.winischhofer.net/ + * for more information and updates) + */ + +#include <linux/config.h> +#include <linux/version.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/fb.h> +#include <linux/console.h> +#include <linux/selection.h> +#include <linux/ioport.h> +#include <linux/capability.h> +#include <linux/fs.h> +#include <linux/types.h> + +#include <asm/io.h> + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include <video/fbcon.h> +#include <video/fbcon-cfb8.h> +#include <video/fbcon-cfb16.h> +#include <video/fbcon-cfb24.h> +#include <video/fbcon-cfb32.h> +#endif + +#include "sis.h" +#include "sis_accel.h" + +static const u8 sisALUConv[] = +{ + 0x00, /* dest = 0; 0, GXclear, 0 */ + 0x88, /* dest &= src; DSa, GXand, 0x1 */ + 0x44, /* dest = src & ~dest; SDna, GXandReverse, 0x2 */ + 0xCC, /* dest = src; S, GXcopy, 0x3 */ + 0x22, /* dest &= ~src; DSna, GXandInverted, 0x4 */ + 0xAA, /* dest = dest; D, GXnoop, 0x5 */ + 0x66, /* dest = ^src; DSx, GXxor, 0x6 */ + 0xEE, /* dest |= src; DSo, GXor, 0x7 */ + 0x11, /* dest = ~src & ~dest; DSon, GXnor, 0x8 */ + 0x99, /* dest ^= ~src ; DSxn, GXequiv, 0x9 */ + 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ + 0xDD, /* dest = src|~dest ; SDno, GXorReverse, 0xB */ + 0x33, /* dest = ~src; Sn, GXcopyInverted, 0xC */ + 0xBB, /* dest |= ~src; DSno, GXorInverted, 0xD */ + 0x77, /* dest = ~src|~dest; DSan, GXnand, 0xE */ + 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ +}; +/* same ROP but with Pattern as Source */ +static const u8 sisPatALUConv[] = +{ + 0x00, /* dest = 0; 0, GXclear, 0 */ + 0xA0, /* dest &= src; DPa, GXand, 0x1 */ + 0x50, /* dest = src & ~dest; PDna, GXandReverse, 0x2 */ + 0xF0, /* dest = src; P, GXcopy, 0x3 */ + 0x0A, /* dest &= ~src; DPna, GXandInverted, 0x4 */ + 0xAA, /* dest = dest; D, GXnoop, 0x5 */ + 0x5A, /* dest = ^src; DPx, GXxor, 0x6 */ + 0xFA, /* dest |= src; DPo, GXor, 0x7 */ + 0x05, /* dest = ~src & ~dest; DPon, GXnor, 0x8 */ + 0xA5, /* dest ^= ~src ; DPxn, GXequiv, 0x9 */ + 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ + 0xF5, /* dest = src|~dest ; PDno, GXorReverse, 0xB */ + 0x0F, /* dest = ~src; Pn, GXcopyInverted, 0xC */ + 0xAF, /* dest |= ~src; DPno, GXorInverted, 0xD */ + 0x5F, /* dest = ~src|~dest; DPan, GXnand, 0xE */ + 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ +}; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) +static const int myrops[] = { + 3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 +}; +#endif + +/* 300 series ----------------------------------------------------- */ +#ifdef CONFIG_FB_SIS_300 +static void +SiS300Sync(struct sis_video_info *ivideo) +{ + SiS300Idle +} + +static void +SiS300SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int xdir, int ydir, + int rop, int trans_color) +{ + SiS300SetupDSTColorDepth(ivideo->DstColor); + SiS300SetupSRCPitch(ivideo->video_linelength) + SiS300SetupDSTRect(ivideo->video_linelength, 0xffff) + + if(trans_color != -1) { + SiS300SetupROP(0x0A) + SiS300SetupSRCTrans(trans_color) + SiS300SetupCMDFlag(TRANSPARENT_BITBLT) + } else { + SiS300SetupROP(sisALUConv[rop]) + } + if(xdir > 0) { + SiS300SetupCMDFlag(X_INC) + } + if(ydir > 0) { + SiS300SetupCMDFlag(Y_INC) + } +} + +static void +SiS300SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, + int src_y, int dst_x, int dst_y, int width, int height) +{ + u32 srcbase = 0, dstbase = 0; + + if(src_y >= 2048) { + srcbase = ivideo->video_linelength * src_y; + src_y = 0; + } + if(dst_y >= 2048) { + dstbase = ivideo->video_linelength * dst_y; + dst_y = 0; + } + + SiS300SetupSRCBase(srcbase); + SiS300SetupDSTBase(dstbase); + + if(!(ivideo->CommandReg & X_INC)) { + src_x += width-1; + dst_x += width-1; + } + if(!(ivideo->CommandReg & Y_INC)) { + src_y += height-1; + dst_y += height-1; + } + SiS300SetupRect(width, height) + SiS300SetupSRCXY(src_x, src_y) + SiS300SetupDSTXY(dst_x, dst_y) + SiS300DoCMD +} + +static void +SiS300SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop) +{ + SiS300SetupPATFG(color) + SiS300SetupDSTRect(ivideo->video_linelength, 0xffff) + SiS300SetupDSTColorDepth(ivideo->DstColor); + SiS300SetupROP(sisPatALUConv[rop]) + SiS300SetupCMDFlag(PATFG) +} + +static void +SiS300SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h) +{ + u32 dstbase = 0; + + if(y >= 2048) { + dstbase = ivideo->video_linelength * y; + y = 0; + } + SiS300SetupDSTBase(dstbase) + SiS300SetupDSTXY(x,y) + SiS300SetupRect(w,h) + SiS300SetupCMDFlag(X_INC | Y_INC | BITBLT) + SiS300DoCMD +} +#endif + +/* 315/330 series ------------------------------------------------- */ + +#ifdef CONFIG_FB_SIS_315 +static void +SiS310Sync(struct sis_video_info *ivideo) +{ + SiS310Idle +} + +static void +SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int trans_color) +{ + SiS310SetupDSTColorDepth(ivideo->DstColor); + SiS310SetupSRCPitch(ivideo->video_linelength) + SiS310SetupDSTRect(ivideo->video_linelength, 0xffff) + if(trans_color != -1) { + SiS310SetupROP(0x0A) + SiS310SetupSRCTrans(trans_color) + SiS310SetupCMDFlag(TRANSPARENT_BITBLT) + } else { + SiS310SetupROP(sisALUConv[rop]) + /* Set command - not needed, both 0 */ + /* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */ + } + SiS310SetupCMDFlag(ivideo->SiS310_AccelDepth) + /* The 315 series is smart enough to know the direction */ +} + +static void +SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int src_y, + int dst_x, int dst_y, int width, int height) +{ + u32 srcbase = 0, dstbase = 0; + int mymin = min(src_y, dst_y); + int mymax = max(src_y, dst_y); + + /* Although the chip knows the direction to use + * if the source and destination areas overlap, + * that logic fails if we fiddle with the bitmap + * addresses. Therefore, we check if the source + * and destination blitting areas overlap and + * adapt the bitmap addresses synchronously + * if the coordinates exceed the valid range. + * The the areas do not overlap, we do our + * normal check. + */ + if((mymax - mymin) < height) { + if((src_y >= 2048) || (dst_y >= 2048)) { + srcbase = ivideo->video_linelength * mymin; + dstbase = ivideo->video_linelength * mymin; + src_y -= mymin; + dst_y -= mymin; + } + } else { + if(src_y >= 2048) { + srcbase = ivideo->video_linelength * src_y; + src_y = 0; + } + if(dst_y >= 2048) { + dstbase = ivideo->video_linelength * dst_y; + dst_y = 0; + } + } + + SiS310SetupSRCBase(srcbase); + SiS310SetupDSTBase(dstbase); + SiS310SetupRect(width, height) + SiS310SetupSRCXY(src_x, src_y) + SiS310SetupDSTXY(dst_x, dst_y) + SiS310DoCMD +} + +static void +SiS310SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop) +{ + SiS310SetupPATFG(color) + SiS310SetupDSTRect(ivideo->video_linelength, 0xffff) + SiS310SetupDSTColorDepth(ivideo->DstColor); + SiS310SetupROP(sisPatALUConv[rop]) + SiS310SetupCMDFlag(PATFG | ivideo->SiS310_AccelDepth) +} + +static void +SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h) +{ + u32 dstbase = 0; + + if(y >= 2048) { + dstbase = ivideo->video_linelength * y; + y = 0; + } + SiS310SetupDSTBase(dstbase) + SiS310SetupDSTXY(x,y) + SiS310SetupRect(w,h) + SiS310SetupCMDFlag(BITBLT) + SiS310DoCMD +} +#endif + +/* --------------------------------------------------------------------- */ + +/* The exported routines */ + +int sisfb_initaccel(struct sis_video_info *ivideo) +{ +#ifdef SISFB_USE_SPINLOCKS + spin_lock_init(&ivideo->lockaccel); +#endif + return(0); +} + +void sisfb_syncaccel(struct sis_video_info *ivideo) +{ + if(ivideo->sisvga_engine == SIS_300_VGA) { +#ifdef CONFIG_FB_SIS_300 + SiS300Sync(ivideo); +#endif + } else { +#ifdef CONFIG_FB_SIS_315 + SiS310Sync(ivideo); +#endif + } +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* --------------- 2.5 --------------- */ + +int fbcon_sis_sync(struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + CRITFLAGS + + if(!ivideo->accel) + return 0; + + if(ivideo->sisvga_engine == SIS_300_VGA) { +#ifdef CONFIG_FB_SIS_300 + SiS300Sync(ivideo); +#endif + } else { +#ifdef CONFIG_FB_SIS_315 + SiS310Sync(ivideo); +#endif + } + CRITEND + return 0; +} + +void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + u32 col = 0; + u32 vxres = info->var.xres_virtual; + u32 vyres = info->var.yres_virtual; + int width, height; + CRITFLAGS + + if(info->state != FBINFO_STATE_RUNNING) { + return; + } + + if(!ivideo->accel) { + cfb_fillrect(info, rect); + return; + } + + if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres) { + return; + } + + /* Clipping */ + width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width; + height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height; + + switch(info->var.bits_per_pixel) { + case 8: col = rect->color; + break; + case 16: + case 32: col = ((u32 *)(info->pseudo_palette))[rect->color]; + break; + } + + if(ivideo->sisvga_engine == SIS_300_VGA) { +#ifdef CONFIG_FB_SIS_300 + CRITBEGIN + SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]); + SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height); + CRITEND + SiS300Sync(ivideo); +#endif + } else { +#ifdef CONFIG_FB_SIS_315 + CRITBEGIN + SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]); + SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height); + CRITEND + SiS310Sync(ivideo); +#endif + } + +} + +void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + u32 vxres = info->var.xres_virtual; + u32 vyres = info->var.yres_virtual; + int width = area->width; + int height = area->height; + CRITFLAGS + + if(info->state != FBINFO_STATE_RUNNING) { + return; + } + + if(!ivideo->accel) { + cfb_copyarea(info, area); + return; + } + + if(!width || !height || + area->sx >= vxres || area->sy >= vyres || + area->dx >= vxres || area->dy >= vyres) { + return; + } + + /* Clipping */ + if((area->sx + width) > vxres) width = vxres - area->sx; + if((area->dx + width) > vxres) width = vxres - area->dx; + if((area->sy + height) > vyres) height = vyres - area->sy; + if((area->dy + height) > vyres) height = vyres - area->dy; + + if(ivideo->sisvga_engine == SIS_300_VGA) { +#ifdef CONFIG_FB_SIS_300 + int xdir, ydir; + + if(area->sx < area->dx) xdir = 0; + else xdir = 1; + if(area->sy < area->dy) ydir = 0; + else ydir = 1; + + CRITBEGIN + SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1); + SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy, + width, height); + CRITEND + SiS300Sync(ivideo); +#endif + } else { +#ifdef CONFIG_FB_SIS_315 + CRITBEGIN + SiS310SetupForScreenToScreenCopy(ivideo, 3, -1); + SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy, + width, height); + CRITEND + SiS310Sync(ivideo); +#endif + } +} + +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* -------------- 2.4 --------------- */ + +void fbcon_sis_bmove(struct display *p, int srcy, int srcx, + int dsty, int dstx, int height, int width) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par; + + CRITFLAGS + + if(!ivideo->accel) { + switch(ivideo->video_bpp) { + case 8: +#ifdef FBCON_HAS_CFB8 + fbcon_cfb8_bmove(p, srcy, srcx, dsty, dstx, height, width); +#endif + break; + case 16: +#ifdef FBCON_HAS_CFB16 + fbcon_cfb16_bmove(p, srcy, srcx, dsty, dstx, height, width); +#endif + break; + case 32: +#ifdef FBCON_HAS_CFB32 + fbcon_cfb32_bmove(p, srcy, srcx, dsty, dstx, height, width); +#endif + break; + } + return; + } + + srcx *= fontwidth(p); + srcy *= fontheight(p); + dstx *= fontwidth(p); + dsty *= fontheight(p); + width *= fontwidth(p); + height *= fontheight(p); + + if(ivideo->sisvga_engine == SIS_300_VGA) { +#ifdef CONFIG_FB_SIS_300 + int xdir, ydir; + + if(srcx < dstx) xdir = 0; + else xdir = 1; + if(srcy < dsty) ydir = 0; + else ydir = 1; + + CRITBEGIN + SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1); + SiS300SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height); + CRITEND + SiS300Sync(ivideo); +#endif + } else { +#ifdef CONFIG_FB_SIS_315 + CRITBEGIN + SiS310SetupForScreenToScreenCopy(ivideo, 3, -1); + SiS310SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height); + CRITEND + SiS310Sync(ivideo); +#endif + } +} + +static void fbcon_sis_clear(struct vc_data *conp, struct display *p, + int srcy, int srcx, int height, int width, int color) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par; + CRITFLAGS + + srcx *= fontwidth(p); + srcy *= fontheight(p); + width *= fontwidth(p); + height *= fontheight(p); + + if(ivideo->sisvga_engine == SIS_300_VGA) { +#ifdef CONFIG_FB_SIS_300 + CRITBEGIN + SiS300SetupForSolidFill(ivideo, color, 3); + SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, width, height); + CRITEND + SiS300Sync(ivideo); +#endif + } else { +#ifdef CONFIG_FB_SIS_315 + CRITBEGIN + SiS310SetupForSolidFill(ivideo, color, 3); + SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, width, height); + CRITEND + SiS310Sync(ivideo); +#endif + } +} + +void fbcon_sis_clear8(struct vc_data *conp, struct display *p, + int srcy, int srcx, int height, int width) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par; + u32 bgx; + + if(!ivideo->accel) { +#ifdef FBCON_HAS_CFB8 + fbcon_cfb8_clear(conp, p, srcy, srcx, height, width); +#endif + return; + } + + bgx = attr_bgcol_ec(p, conp); + fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx); +} + +void fbcon_sis_clear16(struct vc_data *conp, struct display *p, + int srcy, int srcx, int height, int width) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par; + u32 bgx; + + if(!ivideo->accel) { +#ifdef FBCON_HAS_CFB16 + fbcon_cfb16_clear(conp, p, srcy, srcx, height, width); +#endif + return; + } + + bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)]; + fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx); +} + +void fbcon_sis_clear32(struct vc_data *conp, struct display *p, + int srcy, int srcx, int height, int width) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par; + u32 bgx; + + if(!ivideo->accel) { +#ifdef FBCON_HAS_CFB32 + fbcon_cfb32_clear(conp, p, srcy, srcx, height, width); +#endif + return; + } + + bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)]; + fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx); +} + +void fbcon_sis_revc(struct display *p, int srcx, int srcy) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par; + CRITFLAGS + + if(!ivideo->accel) { + switch(ivideo->video_bpp) { + case 16: +#ifdef FBCON_HAS_CFB16 + fbcon_cfb16_revc(p, srcx, srcy); +#endif + break; + case 32: +#ifdef FBCON_HAS_CFB32 + fbcon_cfb32_revc(p, srcx, srcy); +#endif + break; + } + return; + } + + srcx *= fontwidth(p); + srcy *= fontheight(p); + + if(ivideo->sisvga_engine == SIS_300_VGA) { +#ifdef CONFIG_FB_SIS_300 + CRITBEGIN + SiS300SetupForSolidFill(ivideo, 0, 0x0a); + SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p)); + CRITEND + SiS300Sync(ivideo); +#endif + } else { +#ifdef CONFIG_FB_SIS_315 + CRITBEGIN + SiS310SetupForSolidFill(ivideo, 0, 0x0a); + SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p)); + CRITEND + SiS310Sync(ivideo); +#endif + } +} + +#ifdef FBCON_HAS_CFB8 +struct display_switch fbcon_sis8 = { + .setup = fbcon_cfb8_setup, + .bmove = fbcon_sis_bmove, + .clear = fbcon_sis_clear8, + .putc = fbcon_cfb8_putc, + .putcs = fbcon_cfb8_putcs, + .revc = fbcon_cfb8_revc, + .clear_margins = fbcon_cfb8_clear_margins, + .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif +#ifdef FBCON_HAS_CFB16 +struct display_switch fbcon_sis16 = { + .setup = fbcon_cfb16_setup, + .bmove = fbcon_sis_bmove, + .clear = fbcon_sis_clear16, + .putc = fbcon_cfb16_putc, + .putcs = fbcon_cfb16_putcs, + .revc = fbcon_sis_revc, + .clear_margins = fbcon_cfb16_clear_margins, + .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif +#ifdef FBCON_HAS_CFB32 +struct display_switch fbcon_sis32 = { + .setup = fbcon_cfb32_setup, + .bmove = fbcon_sis_bmove, + .clear = fbcon_sis_clear32, + .putc = fbcon_cfb32_putc, + .putcs = fbcon_cfb32_putcs, + .revc = fbcon_sis_revc, + .clear_margins = fbcon_cfb32_clear_margins, + .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif + +#endif /* KERNEL VERSION */ + + diff --git a/drivers/video/sis/sis_accel.h b/drivers/video/sis/sis_accel.h new file mode 100644 index 000000000000..bb28f331d60d --- /dev/null +++ b/drivers/video/sis/sis_accel.h @@ -0,0 +1,409 @@ +/* + * SiS 300/630/730/540/315/550/650/740 frame buffer driver + * for Linux kernels 2.4.x and 2.5.x + * + * 2D acceleration part + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the named License, + * or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Based on the X driver's sis300_accel.h which is + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * and sis310_accel.h which is + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * Author: Thomas Winischhofer <thomas@winischhofer.net>: + * (see http://www.winischhofer.net/ + * for more information and updates) + */ + +#ifndef _SISFB_ACCEL_H +#define _SISFB_ACCEL_H + +/* Guard accelerator accesses with spin_lock_irqsave? Works well without. */ +#undef SISFB_USE_SPINLOCKS + +#ifdef SISFB_USE_SPINLOCKS +#include <linux/spinlock.h> +#define CRITBEGIN spin_lock_irqsave(&ivideo->lockaccel, critflags); +#define CRITEND spin_unlock_irqrestore(&ivideo->lockaccel, critflags); +#define CRITFLAGS unsigned long critflags; +#else +#define CRITBEGIN +#define CRITEND +#define CRITFLAGS +#endif + +/* Definitions for the SIS engine communication. */ + +#define PATREGSIZE 384 /* Pattern register size. 384 bytes @ 0x8300 */ +#define BR(x) (0x8200 | (x) << 2) +#define PBR(x) (0x8300 | (x) << 2) + +/* SiS300 engine commands */ +#define BITBLT 0x00000000 /* Blit */ +#define COLOREXP 0x00000001 /* Color expand */ +#define ENCOLOREXP 0x00000002 /* Enhanced color expand */ +#define MULTIPLE_SCANLINE 0x00000003 /* ? */ +#define LINE 0x00000004 /* Draw line */ +#define TRAPAZOID_FILL 0x00000005 /* Fill trapezoid */ +#define TRANSPARENT_BITBLT 0x00000006 /* Transparent Blit */ + +/* Additional engine commands for 315 */ +#define ALPHA_BLEND 0x00000007 /* Alpha blend ? */ +#define A3D_FUNCTION 0x00000008 /* 3D command ? */ +#define CLEAR_Z_BUFFER 0x00000009 /* ? */ +#define GRADIENT_FILL 0x0000000A /* Gradient fill */ + +/* source select */ +#define SRCVIDEO 0x00000000 /* source is video RAM */ +#define SRCSYSTEM 0x00000010 /* source is system memory */ +#define SRCCPUBLITBUF SRCSYSTEM /* source is CPU-driven BitBuffer (for color expand) */ +#define SRCAGP 0x00000020 /* source is AGP memory (?) */ + +/* Pattern flags */ +#define PATFG 0x00000000 /* foreground color */ +#define PATPATREG 0x00000040 /* pattern in pattern buffer (0x8300) */ +#define PATMONO 0x00000080 /* mono pattern */ + +/* blitting direction (300 series only) */ +#define X_INC 0x00010000 +#define X_DEC 0x00000000 +#define Y_INC 0x00020000 +#define Y_DEC 0x00000000 + +/* Clipping flags */ +#define NOCLIP 0x00000000 +#define NOMERGECLIP 0x04000000 +#define CLIPENABLE 0x00040000 +#define CLIPWITHOUTMERGE 0x04040000 + +/* Transparency */ +#define OPAQUE 0x00000000 +#define TRANSPARENT 0x00100000 + +/* ? */ +#define DSTAGP 0x02000000 +#define DSTVIDEO 0x02000000 + +/* Subfunctions for Color/Enhanced Color Expansion (315 only) */ +#define COLOR_TO_MONO 0x00100000 +#define AA_TEXT 0x00200000 + +/* Some general registers for 315 series */ +#define SRC_ADDR 0x8200 +#define SRC_PITCH 0x8204 +#define AGP_BASE 0x8206 /* color-depth dependent value */ +#define SRC_Y 0x8208 +#define SRC_X 0x820A +#define DST_Y 0x820C +#define DST_X 0x820E +#define DST_ADDR 0x8210 +#define DST_PITCH 0x8214 +#define DST_HEIGHT 0x8216 +#define RECT_WIDTH 0x8218 +#define RECT_HEIGHT 0x821A +#define PAT_FGCOLOR 0x821C +#define PAT_BGCOLOR 0x8220 +#define SRC_FGCOLOR 0x8224 +#define SRC_BGCOLOR 0x8228 +#define MONO_MASK 0x822C +#define LEFT_CLIP 0x8234 +#define TOP_CLIP 0x8236 +#define RIGHT_CLIP 0x8238 +#define BOTTOM_CLIP 0x823A +#define COMMAND_READY 0x823C +#define FIRE_TRIGGER 0x8240 + +#define PATTERN_REG 0x8300 /* 384 bytes pattern buffer */ + +/* Transparent bitblit registers */ +#define TRANS_DST_KEY_HIGH PAT_FGCOLOR +#define TRANS_DST_KEY_LOW PAT_BGCOLOR +#define TRANS_SRC_KEY_HIGH SRC_FGCOLOR +#define TRANS_SRC_KEY_LOW SRC_BGCOLOR + +/* Store queue length in par */ +#define CmdQueLen ivideo->cmdqueuelength + +/* ------------- SiS 300 series -------------- */ + +/* BR(16) (0x8240): + + bit 31 2D engine: 1 is idle, + bit 30 3D engine: 1 is idle, + bit 29 Command queue: 1 is empty + bits 28:24: Current CPU driven BitBlt buffer stage bit[4:0] + bits 15:0: Current command queue length + +*/ + +#define SiS300Idle \ + { \ + while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \ + while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \ + while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \ + CmdQueLen = MMIO_IN16(ivideo->mmio_vbase, 0x8240); \ + } +/* (do three times, because 2D engine seems quite unsure about whether or not it's idle) */ + +#define SiS300SetupSRCBase(base) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(0), base);\ + CmdQueLen--; + +#define SiS300SetupSRCPitch(pitch) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT16(ivideo->mmio_vbase, BR(1), pitch);\ + CmdQueLen--; + +#define SiS300SetupSRCXY(x,y) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(2), (x)<<16 | (y) );\ + CmdQueLen--; + +#define SiS300SetupDSTBase(base) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(4), base);\ + CmdQueLen--; + +#define SiS300SetupDSTXY(x,y) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(3), (x)<<16 | (y) );\ + CmdQueLen--; + +#define SiS300SetupDSTRect(x,y) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(5), (y)<<16 | (x) );\ + CmdQueLen--; + +#define SiS300SetupDSTColorDepth(bpp) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT16(ivideo->mmio_vbase, BR(1)+2, bpp);\ + CmdQueLen--; + +#define SiS300SetupRect(w,h) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(6), (h)<<16 | (w) );\ + CmdQueLen--; + +#define SiS300SetupPATFG(color) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(7), color);\ + CmdQueLen--; + +#define SiS300SetupPATBG(color) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(8), color);\ + CmdQueLen--; + +#define SiS300SetupSRCFG(color) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(9), color);\ + CmdQueLen--; + +#define SiS300SetupSRCBG(color) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(10), color);\ + CmdQueLen--; + +/* 0x8224 src colorkey high */ +/* 0x8228 src colorkey low */ +/* 0x821c dest colorkey high */ +/* 0x8220 dest colorkey low */ +#define SiS300SetupSRCTrans(color) \ + if(CmdQueLen <= 1) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, 0x8224, color);\ + MMIO_OUT32(ivideo->mmio_vbase, 0x8228, color);\ + CmdQueLen -= 2; + +#define SiS300SetupDSTTrans(color) \ + if(CmdQueLen <= 1) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, 0x821C, color); \ + MMIO_OUT32(ivideo->mmio_vbase, 0x8220, color); \ + CmdQueLen -= 2; + +#define SiS300SetupMONOPAT(p0,p1) \ + if(CmdQueLen <= 1) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(11), p0);\ + MMIO_OUT32(ivideo->mmio_vbase, BR(12), p1);\ + CmdQueLen -= 2; + +#define SiS300SetupClipLT(left,top) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\ + CmdQueLen--; + +#define SiS300SetupClipRB(right,bottom) \ + if(CmdQueLen <= 0) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\ + CmdQueLen--; + +/* General */ +#define SiS300SetupROP(rop) \ + ivideo->CommandReg = (rop) << 8; + +#define SiS300SetupCMDFlag(flags) \ + ivideo->CommandReg |= (flags); + +#define SiS300DoCMD \ + if(CmdQueLen <= 1) SiS300Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, BR(15), ivideo->CommandReg); \ + MMIO_OUT32(ivideo->mmio_vbase, BR(16), 0);\ + CmdQueLen -= 2; + +/* -------------- SiS 315/330 series --------------- */ + +/* Q_STATUS: + bit 31 = 1: All engines idle and all queues empty + bit 30 = 1: Hardware Queue (=HW CQ, 2D queue, 3D queue) empty + bit 29 = 1: 2D engine is idle + bit 28 = 1: 3D engine is idle + bit 27 = 1: HW command queue empty + bit 26 = 1: 2D queue empty + bit 25 = 1: 3D queue empty + bit 24 = 1: SW command queue empty + bits 23:16: 2D counter 3 + bits 15:8: 2D counter 2 + bits 7:0: 2D counter 1 +*/ + +#define SiS310Idle \ + { \ + while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \ + while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \ + CmdQueLen = 0; \ + } + +#define SiS310SetupSRCBase(base) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, SRC_ADDR, base);\ + CmdQueLen--; + +#define SiS310SetupSRCPitch(pitch) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT16(ivideo->mmio_vbase, SRC_PITCH, pitch);\ + CmdQueLen--; + +#define SiS310SetupSRCXY(x,y) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, SRC_Y, (x)<<16 | (y) );\ + CmdQueLen--; + +#define SiS310SetupDSTBase(base) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, DST_ADDR, base);\ + CmdQueLen--; + +#define SiS310SetupDSTXY(x,y) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, DST_Y, (x)<<16 | (y) );\ + CmdQueLen--; + +#define SiS310SetupDSTRect(x,y) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, DST_PITCH, (y)<<16 | (x) );\ + CmdQueLen--; + +#define SiS310SetupDSTColorDepth(bpp) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT16(ivideo->mmio_vbase, AGP_BASE, bpp);\ + CmdQueLen--; + +#define SiS310SetupRect(w,h) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\ + CmdQueLen--; + +#define SiS310SetupPATFG(color) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, PAT_FGCOLOR, color);\ + CmdQueLen--; + +#define SiS310SetupPATBG(color) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, PAT_BGCOLOR, color);\ + CmdQueLen--; + +#define SiS310SetupSRCFG(color) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, SRC_FGCOLOR, color);\ + CmdQueLen--; + +#define SiS310SetupSRCBG(color) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, SRC_BGCOLOR, color);\ + CmdQueLen--; + +#define SiS310SetupSRCTrans(color) \ + if(CmdQueLen <= 1) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_HIGH, color);\ + MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_LOW, color);\ + CmdQueLen -= 2; + +#define SiS310SetupDSTTrans(color) \ + if(CmdQueLen <= 1) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_HIGH, color); \ + MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_LOW, color); \ + CmdQueLen -= 2; + +#define SiS310SetupMONOPAT(p0,p1) \ + if(CmdQueLen <= 1) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK, p0);\ + MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK+4, p1);\ + CmdQueLen -= 2; + +#define SiS310SetupClipLT(left,top) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\ + CmdQueLen--; + +#define SiS310SetupClipRB(right,bottom) \ + if(CmdQueLen <= 0) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\ + CmdQueLen--; + +#define SiS310SetupROP(rop) \ + ivideo->CommandReg = (rop) << 8; + +#define SiS310SetupCMDFlag(flags) \ + ivideo->CommandReg |= (flags); + +#define SiS310DoCMD \ + if(CmdQueLen <= 1) SiS310Idle;\ + MMIO_OUT32(ivideo->mmio_vbase, COMMAND_READY, ivideo->CommandReg); \ + MMIO_OUT32(ivideo->mmio_vbase, FIRE_TRIGGER, 0); \ + CmdQueLen -= 2; + + +int sisfb_initaccel(struct sis_video_info *ivideo); +void sisfb_syncaccel(struct sis_video_info *ivideo); + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) +void fbcon_sis_bmove(struct display *p, int srcy, int srcx, int dsty, + int dstx, int height, int width); +void fbcon_sis_revc(struct display *p, int srcy, int srcx); +void fbcon_sis_clear8(struct vc_data *conp, struct display *p, int srcy, + int srcx, int height, int width); +void fbcon_sis_clear16(struct vc_data *conp, struct display *p, int srcy, + int srcx, int height, int width); +void fbcon_sis_clear32(struct vc_data *conp, struct display *p, int srcy, + int srcx, int height, int width); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) +void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect); +void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area); +#endif + +#endif diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c new file mode 100644 index 000000000000..b773c98f6513 --- /dev/null +++ b/drivers/video/sis/sis_main.c @@ -0,0 +1,6027 @@ +/* + * SiS 300/305/540/630(S)/730(S) + * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760 + * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3 + * + * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the named License, + * or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + * Author of (practically wiped) code base: + * SiS (www.sis.com) + * Copyright (C) 1999 Silicon Integrated Systems, Inc. + * + * See http://www.winischhofer.net/ for more information and updates + * + * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver, + * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> + * + */ + +#include <linux/config.h> +#include <linux/version.h> +#include <linux/module.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#include <linux/moduleparam.h> +#endif +#include <linux/kernel.h> +#include <linux/smp_lock.h> +#include <linux/spinlock.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/console.h> +#include <linux/selection.h> +#include <linux/smp_lock.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/vmalloc.h> +#include <linux/vt_kern.h> +#include <linux/capability.h> +#include <linux/fs.h> +#include <linux/types.h> +#include <asm/uaccess.h> +#include <asm/io.h> +#ifdef CONFIG_MTRR +#include <asm/mtrr.h> +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include <video/fbcon.h> +#include <video/fbcon-cfb8.h> +#include <video/fbcon-cfb16.h> +#include <video/fbcon-cfb24.h> +#include <video/fbcon-cfb32.h> +#endif + +#include "sis.h" +#include "sis_main.h" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) +#error "This version of sisfb requires at least 2.6.3" +#endif +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#ifdef FBCON_HAS_CFB8 +extern struct display_switch fbcon_sis8; +#endif +#ifdef FBCON_HAS_CFB16 +extern struct display_switch fbcon_sis16; +#endif +#ifdef FBCON_HAS_CFB32 +extern struct display_switch fbcon_sis32; +#endif +#endif + +/* ------------------ Internal helper routines ----------------- */ + +static void __init +sisfb_setdefaultparms(void) +{ + sisfb_off = 0; + sisfb_parm_mem = 0; + sisfb_accel = -1; + sisfb_ypan = -1; + sisfb_max = -1; + sisfb_userom = -1; + sisfb_useoem = -1; +#ifdef MODULE + /* Module: "None" for 2.4, default mode for 2.5+ */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + sisfb_mode_idx = -1; +#else + sisfb_mode_idx = MODE_INDEX_NONE; +#endif +#else + /* Static: Default mode */ + sisfb_mode_idx = -1; +#endif + sisfb_parm_rate = -1; + sisfb_crt1off = 0; + sisfb_forcecrt1 = -1; + sisfb_crt2type = -1; + sisfb_crt2flags = 0; + sisfb_pdc = 0xff; + sisfb_pdca = 0xff; + sisfb_scalelcd = -1; + sisfb_specialtiming = CUT_NONE; + sisfb_lvdshl = -1; + sisfb_dstn = 0; + sisfb_fstn = 0; + sisfb_tvplug = -1; + sisfb_tvstd = -1; + sisfb_tvxposoffset = 0; + sisfb_tvyposoffset = 0; + sisfb_filter = -1; + sisfb_nocrt2rate = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + sisfb_inverse = 0; + sisfb_fontname[0] = 0; +#endif +#if !defined(__i386__) && !defined(__x86_64__) + sisfb_resetcard = 0; + sisfb_videoram = 0; +#endif +} + +static void __devinit +sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet) +{ + int i = 0, j = 0; + + /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ + + if(vesamode == 0) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + sisfb_mode_idx = MODE_INDEX_NONE; +#else + if(!quiet) { + printk(KERN_ERR "sisfb: Invalid mode. Using default.\n"); + } + sisfb_mode_idx = DEFAULT_MODE; +#endif + return; + } + + vesamode &= 0x1dff; /* Clean VESA mode number from other flags */ + + while(sisbios_mode[i++].mode_no[0] != 0) { + if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) || + (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) { + if(sisfb_fstn) { + if(sisbios_mode[i-1].mode_no[1] == 0x50 || + sisbios_mode[i-1].mode_no[1] == 0x56 || + sisbios_mode[i-1].mode_no[1] == 0x53) continue; + } else { + if(sisbios_mode[i-1].mode_no[1] == 0x5a || + sisbios_mode[i-1].mode_no[1] == 0x5b) continue; + } + sisfb_mode_idx = i - 1; + j = 1; + break; + } + } + if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode); +} + +static void +sisfb_search_mode(char *name, BOOLEAN quiet) +{ + int i = 0; + unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0; + char strbuf[16], strbuf1[20]; + char *nameptr = name; + + /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ + + if(name == NULL) { + if(!quiet) { + printk(KERN_ERR "sisfb: Internal error, using default mode.\n"); + } + sisfb_mode_idx = DEFAULT_MODE; + return; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) { + if(!quiet) { + printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n"); + } + sisfb_mode_idx = DEFAULT_MODE; + return; + } +#endif + if(strlen(name) <= 19) { + strcpy(strbuf1, name); + for(i=0; i<strlen(strbuf1); i++) { + if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' '; + } + + /* This does some fuzzy mode naming detection */ + if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) { + if((rate <= 32) || (depth > 32)) { + j = rate; rate = depth; depth = j; + } + sprintf(strbuf, "%ux%ux%u", xres, yres, depth); + nameptr = strbuf; + sisfb_parm_rate = rate; + } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) { + sprintf(strbuf, "%ux%ux%u", xres, yres, depth); + nameptr = strbuf; + } else { + xres = 0; + if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) { + sprintf(strbuf, "%ux%ux8", xres, yres); + nameptr = strbuf; + } else { + sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet); + return; + } + } + } + + i = 0; j = 0; + while(sisbios_mode[i].mode_no[0] != 0) { + if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) { + if(sisfb_fstn) { + if(sisbios_mode[i-1].mode_no[1] == 0x50 || + sisbios_mode[i-1].mode_no[1] == 0x56 || + sisbios_mode[i-1].mode_no[1] == 0x53) continue; + } else { + if(sisbios_mode[i-1].mode_no[1] == 0x5a || + sisbios_mode[i-1].mode_no[1] == 0x5b) continue; + } + sisfb_mode_idx = i - 1; + j = 1; + break; + } + } + if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr); +} + +#ifndef MODULE +static void __devinit +sisfb_get_vga_mode_from_kernel(void) +{ +#if (defined(__i386__) || defined(__x86_64__)) && defined(CONFIG_VIDEO_SELECT) + char mymode[32]; + int mydepth = screen_info.lfb_depth; + + if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return; + + if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) && + (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) && + (mydepth >= 8) && (mydepth <= 32) ) { + + if(mydepth == 24) mydepth = 32; + + sprintf(mymode, "%ux%ux%u", screen_info.lfb_width, + screen_info.lfb_height, + mydepth); + + printk(KERN_DEBUG "sisfb: Using vga mode %s pre-set by kernel as default\n", mymode); + + sisfb_search_mode(mymode, TRUE); + } +#endif + return; +} +#endif + +static void __init +sisfb_search_crt2type(const char *name) +{ + int i = 0; + + /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ + + if(name == NULL) return; + + while(sis_crt2type[i].type_no != -1) { + if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) { + sisfb_crt2type = sis_crt2type[i].type_no; + sisfb_tvplug = sis_crt2type[i].tvplug_no; + sisfb_crt2flags = sis_crt2type[i].flags; + break; + } + i++; + } + + sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0; + sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0; + + if(sisfb_crt2type < 0) { + printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name); + } +} + +static void __init +sisfb_search_tvstd(const char *name) +{ + int i = 0; + + /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ + + if(name == NULL) return; + + while(sis_tvtype[i].type_no != -1) { + if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) { + sisfb_tvstd = sis_tvtype[i].type_no; + break; + } + i++; + } +} + +static void __init +sisfb_search_specialtiming(const char *name) +{ + int i = 0; + BOOLEAN found = FALSE; + + /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ + + if(name == NULL) return; + + if(!strnicmp(name, "none", 4)) { + sisfb_specialtiming = CUT_FORCENONE; + printk(KERN_DEBUG "sisfb: Special timing disabled\n"); + } else { + while(mycustomttable[i].chipID != 0) { + if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) { + sisfb_specialtiming = mycustomttable[i].SpecialID; + found = TRUE; + printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n", + mycustomttable[i].vendorName, mycustomttable[i].cardName, + mycustomttable[i].optionName); + break; + } + i++; + } + if(!found) { + printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:"); + printk(KERN_WARNING "\t\"none\" (to disable special timings)\n"); + i = 0; + while(mycustomttable[i].chipID != 0) { + printk(KERN_WARNING "\t\"%s\" (for %s %s)\n", + mycustomttable[i].optionName, + mycustomttable[i].vendorName, + mycustomttable[i].cardName); + i++; + } + } + } +} + +static BOOLEAN __devinit +sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer) +{ + int i, j, xres, yres, refresh, index; + u32 emodes; + + if(buffer[0] != 0x00 || buffer[1] != 0xff || + buffer[2] != 0xff || buffer[3] != 0xff || + buffer[4] != 0xff || buffer[5] != 0xff || + buffer[6] != 0xff || buffer[7] != 0x00) { + printk(KERN_DEBUG "sisfb: Bad EDID header\n"); + return FALSE; + } + + if(buffer[0x12] != 0x01) { + printk(KERN_INFO "sisfb: EDID version %d not supported\n", + buffer[0x12]); + return FALSE; + } + + monitor->feature = buffer[0x18]; + + if(!buffer[0x14] & 0x80) { + if(!(buffer[0x14] & 0x08)) { + printk(KERN_INFO "sisfb: WARNING: Monitor does not support separate syncs\n"); + } + } + + if(buffer[0x13] >= 0x01) { + /* EDID V1 rev 1 and 2: Search for monitor descriptor + * to extract ranges + */ + j = 0x36; + for(i=0; i<4; i++) { + if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 && + buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd && + buffer[j + 4] == 0x00) { + monitor->hmin = buffer[j + 7]; + monitor->hmax = buffer[j + 8]; + monitor->vmin = buffer[j + 5]; + monitor->vmax = buffer[j + 6]; + monitor->dclockmax = buffer[j + 9] * 10 * 1000; + monitor->datavalid = TRUE; + break; + } + j += 18; + } + } + + if(!monitor->datavalid) { + /* Otherwise: Get a range from the list of supported + * Estabished Timings. This is not entirely accurate, + * because fixed frequency monitors are not supported + * that way. + */ + monitor->hmin = 65535; monitor->hmax = 0; + monitor->vmin = 65535; monitor->vmax = 0; + monitor->dclockmax = 0; + emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16); + for(i = 0; i < 13; i++) { + if(emodes & sisfb_ddcsmodes[i].mask) { + if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h; + if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1; + if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v; + if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v; + if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d; + } + } + index = 0x26; + for(i = 0; i < 8; i++) { + xres = (buffer[index] + 31) * 8; + switch(buffer[index + 1] & 0xc0) { + case 0xc0: yres = (xres * 9) / 16; break; + case 0x80: yres = (xres * 4) / 5; break; + case 0x40: yres = (xres * 3) / 4; break; + default: yres = xres; break; + } + refresh = (buffer[index + 1] & 0x3f) + 60; + if((xres >= 640) && (yres >= 480)) { + for(j = 0; j < 8; j++) { + if((xres == sisfb_ddcfmodes[j].x) && + (yres == sisfb_ddcfmodes[j].y) && + (refresh == sisfb_ddcfmodes[j].v)) { + if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h; + if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1; + if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v; + if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v; + if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[i].d; + } + } + } + index += 2; + } + if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) { + monitor->datavalid = TRUE; + } + } + + return(monitor->datavalid); +} + +static void __devinit +sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno) +{ + USHORT temp, i, realcrtno = crtno; + u8 buffer[256]; + + monitor->datavalid = FALSE; + + if(crtno) { + if(ivideo->vbflags & CRT2_LCD) realcrtno = 1; + else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2; + else return; + } + + if((ivideo->sisfb_crt1off) && (!crtno)) return; + + temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, + realcrtno, 0, &buffer[0]); + if((!temp) || (temp == 0xffff)) { + printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1); + return; + } else { + printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1); + printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n", + crtno + 1, + (temp & 0x1a) ? "" : "[none of the supported]", + (temp & 0x02) ? "2 " : "", + (temp & 0x08) ? "D&P" : "", + (temp & 0x10) ? "FPDI-2" : ""); + if(temp & 0x02) { + i = 3; /* Number of retrys */ + do { + temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, + realcrtno, 1, &buffer[0]); + } while((temp) && i--); + if(!temp) { + if(sisfb_interpret_edid(monitor, &buffer[0])) { + printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n", + monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax, + monitor->dclockmax / 1000); + } else { + printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1); + } + } else { + printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1); + } + } else { + printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n"); + } + } +} + +static BOOLEAN +sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, + int mode_idx, int rate_idx, int rate) +{ + int htotal, vtotal; + unsigned int dclock, hsync; + + if(!monitor->datavalid) return TRUE; + + if(mode_idx < 0) return FALSE; + + /* Skip for 320x200, 320x240, 640x400 */ + switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) { + case 0x59: + case 0x41: + case 0x4f: + case 0x50: + case 0x56: + case 0x53: + case 0x2f: + case 0x5d: + case 0x5e: + return TRUE; +#ifdef CONFIG_FB_SIS_315 + case 0x5a: + case 0x5b: + if(ivideo->sisvga_engine == SIS_315_VGA) return TRUE; +#endif + } + + if(rate < (monitor->vmin - 1)) return FALSE; + if(rate > (monitor->vmax + 1)) return FALSE; + + if(sisfb_gettotalfrommode(&ivideo->SiS_Pr, &ivideo->sishw_ext, + sisbios_mode[mode_idx].mode_no[ivideo->mni], + &htotal, &vtotal, rate_idx)) { + dclock = (htotal * vtotal * rate) / 1000; + if(dclock > (monitor->dclockmax + 1000)) return FALSE; + hsync = dclock / htotal; + if(hsync < (monitor->hmin - 1)) return FALSE; + if(hsync > (monitor->hmax + 1)) return FALSE; + } else { + return FALSE; + } + return TRUE; +} + +static int +sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags) +{ + u16 xres=0, yres, myres; + +#ifdef CONFIG_FB_SIS_300 + if(ivideo->sisvga_engine == SIS_300_VGA) { + if(!(sisbios_mode[myindex].chipset & MD_SIS300)) return(-1); + } +#endif +#ifdef CONFIG_FB_SIS_315 + if(ivideo->sisvga_engine == SIS_315_VGA) { + if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return(-1); + } +#endif + + myres = sisbios_mode[myindex].yres; + + switch(vbflags & VB_DISPTYPE_DISP2) { + + case CRT2_LCD: + + xres = ivideo->lcdxres; yres = ivideo->lcdyres; + + if(ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) { + if(sisbios_mode[myindex].xres > xres) return(-1); + if(myres > yres) return(-1); + } + + if(vbflags & (VB_LVDS | VB_30xBDH)) { + if(sisbios_mode[myindex].xres == 320) { + if((myres == 240) || (myres == 480)) { + if(!ivideo->sisfb_fstn) { + if(sisbios_mode[myindex].mode_no[1] == 0x5a || + sisbios_mode[myindex].mode_no[1] == 0x5b) + return(-1); + } else { + if(sisbios_mode[myindex].mode_no[1] == 0x50 || + sisbios_mode[myindex].mode_no[1] == 0x56 || + sisbios_mode[myindex].mode_no[1] == 0x53) + return(-1); + } + } + } + } + + if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, + sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn, + ivideo->SiS_Pr.SiS_CustomT, xres, yres) < 0x14) { + return(-1); + } + break; + + case CRT2_TV: + if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, + sisbios_mode[myindex].yres, 0) < 0x14) { + return(-1); + } + break; + + case CRT2_VGA: + if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, + sisbios_mode[myindex].yres, 0) < 0x14) { + return(-1); + } + break; + } + + return(myindex); +} + +static u8 +sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx) +{ + u16 xres, yres; + int i = 0; + + xres = sisbios_mode[mode_idx].xres; + yres = sisbios_mode[mode_idx].yres; + + ivideo->rate_idx = 0; + while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) { + if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) { + if(sisfb_vrate[i].refresh == rate) { + ivideo->rate_idx = sisfb_vrate[i].idx; + break; + } else if(sisfb_vrate[i].refresh > rate) { + if((sisfb_vrate[i].refresh - rate) <= 3) { + DPRINTK("sisfb: Adjusting rate from %d up to %d\n", + rate, sisfb_vrate[i].refresh); + ivideo->rate_idx = sisfb_vrate[i].idx; + ivideo->refresh_rate = sisfb_vrate[i].refresh; + } else if(((rate - sisfb_vrate[i-1].refresh) <= 2) + && (sisfb_vrate[i].idx != 1)) { + DPRINTK("sisfb: Adjusting rate from %d down to %d\n", + rate, sisfb_vrate[i-1].refresh); + ivideo->rate_idx = sisfb_vrate[i-1].idx; + ivideo->refresh_rate = sisfb_vrate[i-1].refresh; + } + break; + } else if((rate - sisfb_vrate[i].refresh) <= 2) { + DPRINTK("sisfb: Adjusting rate from %d down to %d\n", + rate, sisfb_vrate[i].refresh); + ivideo->rate_idx = sisfb_vrate[i].idx; + break; + } + } + i++; + } + if(ivideo->rate_idx > 0) { + return ivideo->rate_idx; + } else { + printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n", + rate, xres, yres); + return 0; + } +} + +static BOOLEAN +sisfb_bridgeisslave(struct sis_video_info *ivideo) +{ + unsigned char P1_00; + + if(!(ivideo->vbflags & VB_VIDEOBRIDGE)) return FALSE; + + inSISIDXREG(SISPART1,0x00,P1_00); + if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) || + ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) { + return TRUE; + } else { + return FALSE; + } +} + +static BOOLEAN +sisfballowretracecrt1(struct sis_video_info *ivideo) +{ + u8 temp; + + inSISIDXREG(SISCR,0x17,temp); + if(!(temp & 0x80)) return FALSE; + + inSISIDXREG(SISSR,0x1f,temp); + if(temp & 0xc0) return FALSE; + + return TRUE; +} + +static BOOLEAN +sisfbcheckvretracecrt1(struct sis_video_info *ivideo) +{ + if(!sisfballowretracecrt1(ivideo)) return FALSE; + + if(inSISREG(SISINPSTAT) & 0x08) return TRUE; + else return FALSE; +} + +static void +sisfbwaitretracecrt1(struct sis_video_info *ivideo) +{ + int watchdog; + + if(!sisfballowretracecrt1(ivideo)) return; + + watchdog = 65536; + while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); + watchdog = 65536; + while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); +} + +static BOOLEAN +sisfbcheckvretracecrt2(struct sis_video_info *ivideo) +{ + unsigned char temp, reg; + + switch(ivideo->sisvga_engine) { + case SIS_300_VGA: reg = 0x25; break; + case SIS_315_VGA: reg = 0x30; break; + default: return FALSE; + } + + inSISIDXREG(SISPART1, reg, temp); + if(temp & 0x02) return TRUE; + else return FALSE; +} + +static BOOLEAN +sisfb_CheckVBRetrace(struct sis_video_info *ivideo) +{ + if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { + if(sisfb_bridgeisslave(ivideo)) { + return(sisfbcheckvretracecrt1(ivideo)); + } else { + return(sisfbcheckvretracecrt2(ivideo)); + } + } + return(sisfbcheckvretracecrt1(ivideo)); +} + +static u32 +sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount) +{ + u8 idx, reg1, reg2, reg3, reg4; + u32 ret = 0; + + (*vcount) = (*hcount) = 0; + + if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) { + ret |= (FB_VBLANK_HAVE_VSYNC | + FB_VBLANK_HAVE_HBLANK | + FB_VBLANK_HAVE_VBLANK | + FB_VBLANK_HAVE_VCOUNT | + FB_VBLANK_HAVE_HCOUNT); + switch(ivideo->sisvga_engine) { + case SIS_300_VGA: idx = 0x25; break; + default: + case SIS_315_VGA: idx = 0x30; break; + } + inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */ + inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */ + inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */ + inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */ + if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; + if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING; + if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING; + (*vcount) = reg3 | ((reg4 & 0x70) << 4); + (*hcount) = reg2 | ((reg4 & 0x0f) << 8); + } else if(sisfballowretracecrt1(ivideo)) { + ret |= (FB_VBLANK_HAVE_VSYNC | + FB_VBLANK_HAVE_VBLANK | + FB_VBLANK_HAVE_VCOUNT | + FB_VBLANK_HAVE_HCOUNT); + reg1 = inSISREG(SISINPSTAT); + if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING; + if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; + inSISIDXREG(SISCR,0x20,reg1); + inSISIDXREG(SISCR,0x1b,reg1); + inSISIDXREG(SISCR,0x1c,reg2); + inSISIDXREG(SISCR,0x1d,reg3); + (*vcount) = reg2 | ((reg3 & 0x07) << 8); + (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3; + } + return ret; +} + +static int +sisfb_myblank(struct sis_video_info *ivideo, int blank) +{ + u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13; + BOOLEAN backlight = TRUE; + + switch(blank) { + case FB_BLANK_UNBLANK: /* on */ + sr01 = 0x00; + sr11 = 0x00; + sr1f = 0x00; + cr63 = 0x00; + p2_0 = 0x20; + p1_13 = 0x00; + backlight = TRUE; + break; + case FB_BLANK_NORMAL: /* blank */ + sr01 = 0x20; + sr11 = 0x00; + sr1f = 0x00; + cr63 = 0x00; + p2_0 = 0x20; + p1_13 = 0x00; + backlight = TRUE; + break; + case FB_BLANK_VSYNC_SUSPEND: /* no vsync */ + sr01 = 0x20; + sr11 = 0x08; + sr1f = 0x80; + cr63 = 0x40; + p2_0 = 0x40; + p1_13 = 0x80; + backlight = FALSE; + break; + case FB_BLANK_HSYNC_SUSPEND: /* no hsync */ + sr01 = 0x20; + sr11 = 0x08; + sr1f = 0x40; + cr63 = 0x40; + p2_0 = 0x80; + p1_13 = 0x40; + backlight = FALSE; + break; + case FB_BLANK_POWERDOWN: /* off */ + sr01 = 0x20; + sr11 = 0x08; + sr1f = 0xc0; + cr63 = 0x40; + p2_0 = 0xc0; + p1_13 = 0xc0; + backlight = FALSE; + break; + default: + return 1; + } + + if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) { + + if( (!ivideo->sisfb_thismonitor.datavalid) || + ((ivideo->sisfb_thismonitor.datavalid) && + (ivideo->sisfb_thismonitor.feature & 0xe0))) { + + if(ivideo->sisvga_engine == SIS_315_VGA) { + setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63); + } + + if(!(sisfb_bridgeisslave(ivideo))) { + setSISIDXREG(SISSR, 0x01, ~0x20, sr01); + setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f); + } + } + + } + + if(ivideo->currentvbflags & CRT2_LCD) { + + if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) { + if(backlight) { + SiS_SiS30xBLOn(&ivideo->SiS_Pr, &ivideo->sishw_ext); + } else { + SiS_SiS30xBLOff(&ivideo->SiS_Pr, &ivideo->sishw_ext); + } + } else if(ivideo->sisvga_engine == SIS_315_VGA) { + if(ivideo->vbflags & VB_CHRONTEL) { + if(backlight) { + SiS_Chrontel701xBLOn(&ivideo->SiS_Pr,&ivideo->sishw_ext); + } else { + SiS_Chrontel701xBLOff(&ivideo->SiS_Pr); + } + } + } + + if(((ivideo->sisvga_engine == SIS_300_VGA) && + (ivideo->vbflags & (VB_301|VB_30xBDH|VB_LVDS))) || + ((ivideo->sisvga_engine == SIS_315_VGA) && + ((ivideo->vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) { + setSISIDXREG(SISSR, 0x11, ~0x0c, sr11); + } + + if(ivideo->sisvga_engine == SIS_300_VGA) { + if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) && + (!(ivideo->vbflags & VB_30xBDH))) { + setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); + } + } else if(ivideo->sisvga_engine == SIS_315_VGA) { + if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) && + (!(ivideo->vbflags & VB_30xBDH))) { + setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); + } + } + + } else if(ivideo->currentvbflags & CRT2_VGA) { + + if(ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) { + setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); + } + + } + + return(0); +} + +/* ----------- FBDev related routines for all series ----------- */ + +static int +sisfb_get_cmap_len(const struct fb_var_screeninfo *var) +{ + return (var->bits_per_pixel == 8) ? 256 : 16; +} + +static void +sisfb_set_vparms(struct sis_video_info *ivideo) +{ + switch(ivideo->video_bpp) { + case 8: + ivideo->DstColor = 0x0000; + ivideo->SiS310_AccelDepth = 0x00000000; + ivideo->video_cmap_len = 256; + break; + case 16: + ivideo->DstColor = 0x8000; + ivideo->SiS310_AccelDepth = 0x00010000; + ivideo->video_cmap_len = 16; + break; + case 32: + ivideo->DstColor = 0xC000; + ivideo->SiS310_AccelDepth = 0x00020000; + ivideo->video_cmap_len = 16; + break; + default: + ivideo->video_cmap_len = 16; + printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp); + ivideo->accel = 0; + break; + } +} + +static int +sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) +{ + int maxyres = ivideo->heapstart / (var->xres_virtual * (var->bits_per_pixel >> 3)); + + if(maxyres > 32767) maxyres = 32767; + + return maxyres; +} + +static void +sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) +{ + ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3); + ivideo->scrnpitchCRT1 = ivideo->video_linelength; + if(!(ivideo->currentvbflags & CRT1_LCDA)) { + if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { + ivideo->scrnpitchCRT1 <<= 1; + } + } + +} + +static void +sisfb_set_pitch(struct sis_video_info *ivideo) +{ + BOOLEAN isslavemode = FALSE; + unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3; + unsigned short HDisplay2 = ivideo->video_linelength >> 3; + + if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE; + + /* We need to set pitch for CRT1 if bridge is in slave mode, too */ + if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) { + outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF)); + setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8)); + } + + /* We must not set the pitch for CRT2 if bridge is in slave mode */ + if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) { + orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01); + outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF)); + setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8)); + } +} + +static void +sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) +{ + ivideo->video_cmap_len = sisfb_get_cmap_len(var); + + switch(var->bits_per_pixel) { + case 8: + var->red.offset = var->green.offset = var->blue.offset = 0; + var->red.length = var->green.length = var->blue.length = 6; + break; + case 16: + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 32: + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 24; + var->transp.length = 8; + break; + } +} + +static int +sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + unsigned int htotal = 0, vtotal = 0; + unsigned int drate = 0, hrate = 0; + int found_mode = 0; + int old_mode; + u32 pixclock; + + htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len; + + vtotal = var->upper_margin + var->lower_margin + var->vsync_len; + + pixclock = var->pixclock; + + if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) { + vtotal += var->yres; + vtotal <<= 1; + } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { + vtotal += var->yres; + vtotal <<= 2; + } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { + vtotal += var->yres; + vtotal <<= 1; + } else vtotal += var->yres; + + if(!(htotal) || !(vtotal)) { + DPRINTK("sisfb: Invalid 'var' information\n"); + return -EINVAL; + } + + if(pixclock && htotal && vtotal) { + drate = 1000000000 / pixclock; + hrate = (drate * 1000) / htotal; + ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal); + } else { + ivideo->refresh_rate = 60; + } + + old_mode = ivideo->sisfb_mode_idx; + ivideo->sisfb_mode_idx = 0; + + while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) && + (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) { + if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) && + (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) && + (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) { + ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; + found_mode = 1; + break; + } + ivideo->sisfb_mode_idx++; + } + + if(found_mode) { + ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo, + ivideo->sisfb_mode_idx, ivideo->currentvbflags); + } else { + ivideo->sisfb_mode_idx = -1; + } + + if(ivideo->sisfb_mode_idx < 0) { + printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres, + var->yres, var->bits_per_pixel); + ivideo->sisfb_mode_idx = old_mode; + return -EINVAL; + } + + if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) { + ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx; + ivideo->refresh_rate = 60; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + if(ivideo->sisfb_thismonitor.datavalid) { + if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx, + ivideo->rate_idx, ivideo->refresh_rate)) { + printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); + } + } +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + if(((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) { +#else + if(isactive) { +#endif + sisfb_pre_setmode(ivideo); + + if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) { + printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no); + return -EINVAL; + } + + outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); + + sisfb_post_setmode(ivideo); + + ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp; + ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres; + ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres; + + sisfb_calc_pitch(ivideo, var); + sisfb_set_pitch(ivideo); + + ivideo->accel = 0; +#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN) +#ifdef STUPID_ACCELF_TEXT_SHIT + if(var->accel_flags & FB_ACCELF_TEXT) { + info->flags &= ~FBINFO_HWACCEL_DISABLED; + } else { + info->flags |= FBINFO_HWACCEL_DISABLED; + } +#endif + if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1; +#else + if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1; +#endif + + sisfb_set_vparms(ivideo); + + ivideo->current_width = ivideo->video_width; + ivideo->current_height = ivideo->video_height; + ivideo->current_bpp = ivideo->video_bpp; + ivideo->current_htotal = htotal; + ivideo->current_vtotal = vtotal; + ivideo->current_linelength = ivideo->video_linelength; + ivideo->current_pixclock = var->pixclock; + ivideo->current_refresh_rate = ivideo->refresh_rate; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate; +#endif + } + + return 0; +} + +static int +sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) +{ + unsigned int base; + + if(var->xoffset > (var->xres_virtual - var->xres)) { + return -EINVAL; + } + if(var->yoffset > (var->yres_virtual - var->yres)) { + return -EINVAL; + } + + base = (var->yoffset * var->xres_virtual) + var->xoffset; + + /* calculate base bpp dep. */ + switch(var->bits_per_pixel) { + case 32: + break; + case 16: + base >>= 1; + break; + case 8: + default: + base >>= 2; + break; + } + + outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); + + outSISIDXREG(SISCR, 0x0D, base & 0xFF); + outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); + outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); + if(ivideo->sisvga_engine == SIS_315_VGA) { + setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); + } + if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { + orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01); + outSISIDXREG(SISPART1, 0x06, (base & 0xFF)); + outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF)); + outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF)); + if(ivideo->sisvga_engine == SIS_315_VGA) { + setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); + } + } + return 0; +} + +/* ------------ FBDev related routines for 2.4 series ----------- */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + +static void +sisfb_crtc_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) +{ + u16 VRE, VBE, VRS, VBS, VDE, VT; + u16 HRE, HBE, HRS, HBS, HDE, HT; + u8 sr_data, cr_data, cr_data2, cr_data3, mr_data; + int A, B, C, D, E, F, temp; + unsigned int hrate, drate, maxyres; + + inSISIDXREG(SISSR, IND_SIS_COLOR_MODE, sr_data); + + if(sr_data & SIS_INTERLACED_MODE) + var->vmode = FB_VMODE_INTERLACED; + else + var->vmode = FB_VMODE_NONINTERLACED; + + switch((sr_data & 0x1C) >> 2) { + case SIS_8BPP_COLOR_MODE: + var->bits_per_pixel = 8; + break; + case SIS_16BPP_COLOR_MODE: + var->bits_per_pixel = 16; + break; + case SIS_32BPP_COLOR_MODE: + var->bits_per_pixel = 32; + break; + } + + sisfb_bpp_to_var(ivideo, var); + + inSISIDXREG(SISSR, 0x0A, sr_data); + inSISIDXREG(SISCR, 0x06, cr_data); + inSISIDXREG(SISCR, 0x07, cr_data2); + + VT = (cr_data & 0xFF) | + ((u16) (cr_data2 & 0x01) << 8) | + ((u16) (cr_data2 & 0x20) << 4) | + ((u16) (sr_data & 0x01) << 10); + A = VT + 2; + + inSISIDXREG(SISCR, 0x12, cr_data); + + VDE = (cr_data & 0xff) | + ((u16) (cr_data2 & 0x02) << 7) | + ((u16) (cr_data2 & 0x40) << 3) | + ((u16) (sr_data & 0x02) << 9); + E = VDE + 1; + + inSISIDXREG(SISCR, 0x10, cr_data); + + VRS = (cr_data & 0xff) | + ((u16) (cr_data2 & 0x04) << 6) | + ((u16) (cr_data2 & 0x80) << 2) | + ((u16) (sr_data & 0x08) << 7); + F = VRS + 1 - E; + + inSISIDXREG(SISCR, 0x15, cr_data); + inSISIDXREG(SISCR, 0x09, cr_data3); + + if(cr_data3 & 0x80) var->vmode = FB_VMODE_DOUBLE; + + VBS = (cr_data & 0xff) | + ((u16) (cr_data2 & 0x08) << 5) | + ((u16) (cr_data3 & 0x20) << 4) | + ((u16) (sr_data & 0x04) << 8); + + inSISIDXREG(SISCR, 0x16, cr_data); + + VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4); + temp = VBE - ((E - 1) & 511); + B = (temp > 0) ? temp : (temp + 512); + + inSISIDXREG(SISCR, 0x11, cr_data); + + VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1); + temp = VRE - ((E + F - 1) & 31); + C = (temp > 0) ? temp : (temp + 32); + + D = B - F - C; + + var->yres = E; + var->upper_margin = D; + var->lower_margin = F; + var->vsync_len = C; + + if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { + var->yres <<= 1; + var->upper_margin <<= 1; + var->lower_margin <<= 1; + var->vsync_len <<= 1; + } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { + var->yres >>= 1; + var->upper_margin >>= 1; + var->lower_margin >>= 1; + var->vsync_len >>= 1; + } + + inSISIDXREG(SISSR, 0x0b, sr_data); + inSISIDXREG(SISCR, 0x00, cr_data); + + HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8); + A = HT + 5; + + inSISIDXREG(SISCR, 0x01, cr_data); + + HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6); + E = HDE + 1; + + inSISIDXREG(SISCR, 0x04, cr_data); + + HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2); + F = HRS - E - 3; + + inSISIDXREG(SISCR, 0x02, cr_data); + + HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4); + + inSISIDXREG(SISSR, 0x0c, sr_data); + inSISIDXREG(SISCR, 0x03, cr_data); + inSISIDXREG(SISCR, 0x05, cr_data2); + + HBE = (cr_data & 0x1f) | + ((u16) (cr_data2 & 0x80) >> 2) | + ((u16) (sr_data & 0x03) << 6); + HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3); + + temp = HBE - ((E - 1) & 255); + B = (temp > 0) ? temp : (temp + 256); + + temp = HRE - ((E + F + 3) & 63); + C = (temp > 0) ? temp : (temp + 64); + + D = B - F - C; + + var->xres = E * 8; + if(var->xres_virtual < var->xres) { + var->xres_virtual = var->xres; + } + + if((var->xres == 320) && + (var->yres == 200 || var->yres == 240)) { + /* Terrible hack, but the correct CRTC data for + * these modes only produces a black screen... + */ + var->left_margin = (400 - 376); + var->right_margin = (328 - 320); + var->hsync_len = (376 - 328); + } else { + var->left_margin = D * 8; + var->right_margin = F * 8; + var->hsync_len = C * 8; + } + var->activate = FB_ACTIVATE_NOW; + + var->sync = 0; + + mr_data = inSISREG(SISMISCR); + if(mr_data & 0x80) + var->sync &= ~FB_SYNC_VERT_HIGH_ACT; + else + var->sync |= FB_SYNC_VERT_HIGH_ACT; + + if(mr_data & 0x40) + var->sync &= ~FB_SYNC_HOR_HIGH_ACT; + else + var->sync |= FB_SYNC_HOR_HIGH_ACT; + + VT += 2; + VT <<= 1; + HT = (HT + 5) * 8; + + if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { + VT <<= 1; + } + hrate = ivideo->refresh_rate * VT / 2; + drate = (hrate * HT) / 1000; + var->pixclock = (u32) (1000000000 / drate); + + if(ivideo->sisfb_ypan) { + maxyres = sisfb_calc_maxyres(ivideo, var); + if(ivideo->sisfb_max) { + var->yres_virtual = maxyres; + } else { + if(var->yres_virtual > maxyres) { + var->yres_virtual = maxyres; + } + } + if(var->yres_virtual <= var->yres) { + var->yres_virtual = var->yres; + } + } else { + var->yres_virtual = var->yres; + } + +} + +static int +sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, + unsigned *transp, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + + if(regno >= ivideo->video_cmap_len) return 1; + + *red = ivideo->sis_palette[regno].red; + *green = ivideo->sis_palette[regno].green; + *blue = ivideo->sis_palette[regno].blue; + *transp = 0; + + return 0; +} + +static int +sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + + if(regno >= ivideo->video_cmap_len) return 1; + + ivideo->sis_palette[regno].red = red; + ivideo->sis_palette[regno].green = green; + ivideo->sis_palette[regno].blue = blue; + + switch(ivideo->video_bpp) { +#ifdef FBCON_HAS_CFB8 + case 8: + outSISREG(SISDACA, regno); + outSISREG(SISDACD, (red >> 10)); + outSISREG(SISDACD, (green >> 10)); + outSISREG(SISDACD, (blue >> 10)); + if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { + outSISREG(SISDAC2A, regno); + outSISREG(SISDAC2D, (red >> 8)); + outSISREG(SISDAC2D, (green >> 8)); + outSISREG(SISDAC2D, (blue >> 8)); + } + break; +#endif +#ifdef FBCON_HAS_CFB16 + case 16: + ivideo->sis_fbcon_cmap.cfb16[regno] = + ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); + break; +#endif +#ifdef FBCON_HAS_CFB32 + case 32: + red >>= 8; + green >>= 8; + blue >>= 8; + ivideo->sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue); + break; +#endif + } + + return 0; +} + +static void +sisfb_set_disp(int con, struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + struct display *display; + struct display_switch *sw; + struct fb_fix_screeninfo fix; + long flags; + + display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp; + + sisfb_get_fix(&fix, con, info); + + display->var = *var; + display->screen_base = (char *)ivideo->video_vbase; + display->visual = fix.visual; + display->type = fix.type; + display->type_aux = fix.type_aux; + display->ypanstep = fix.ypanstep; + display->ywrapstep = fix.ywrapstep; + display->line_length = fix.line_length; + display->can_soft_blank = 1; + display->inverse = ivideo->sisfb_inverse; + display->next_line = fix.line_length; + + save_flags(flags); + + switch(ivideo->video_bpp) { +#ifdef FBCON_HAS_CFB8 + case 8: sw = ivideo->accel ? &fbcon_sis8 : &fbcon_cfb8; + break; +#endif +#ifdef FBCON_HAS_CFB16 + case 16:sw = ivideo->accel ? &fbcon_sis16 : &fbcon_cfb16; + display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb16; + break; +#endif +#ifdef FBCON_HAS_CFB32 + case 32:sw = ivideo->accel ? &fbcon_sis32 : &fbcon_cfb32; + display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb32; + break; +#endif + default:sw = &fbcon_dummy; + break; + } + memcpy(&ivideo->sisfb_sw, sw, sizeof(*sw)); + display->dispsw = &ivideo->sisfb_sw; + + restore_flags(flags); + + if(ivideo->sisfb_ypan) { + /* display->scrollmode = 0; */ + } else { + display->scrollmode = SCROLL_YREDRAW; + ivideo->sisfb_sw.bmove = fbcon_redraw_bmove; + } +} + +static void +sisfb_do_install_cmap(int con, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + + if(con != ivideo->currcon) return; + + if(fb_display[con].cmap.len) { + fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info); + } else { + int size = sisfb_get_cmap_len(&fb_display[con].var); + fb_set_cmap(fb_default_cmap(size), 1, sisfb_setcolreg, info); + } +} + +static int +sisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + + if(con == -1) { + memcpy(var, &ivideo->default_var, sizeof(struct fb_var_screeninfo)); + } else { + *var = fb_display[con].var; + } + + if(ivideo->sisfb_fstn) { + if(var->xres == 320 && var->yres == 480) var->yres = 240; + } + + return 0; +} + +static int +sisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + int err; + + fb_display[con].var.activate = FB_ACTIVATE_NOW; + + if(sisfb_do_set_var(var, con == ivideo->currcon, info)) { + sisfb_crtc_to_var(ivideo, var); + return -EINVAL; + } + + sisfb_crtc_to_var(ivideo, var); + + sisfb_set_disp(con, var, info); + + if(info->changevar) { + (*info->changevar)(con); + } + + if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) { + return err; + } + + sisfb_do_install_cmap(con, info); + +#if 0 /* Why was this called here? */ + unsigned int cols, rows; + cols = sisbios_mode[ivideo->sisfb_mode_idx].cols; + rows = sisbios_mode[ivideo->sisfb_mode_idx].rows; + vc_resize_con(rows, cols, fb_display[con].conp->vc_num); +#endif + return 0; +} + +static int +sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + struct display *display; + + display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp; + + if(con == ivideo->currcon) { + + return fb_get_cmap(cmap, kspc, sis_getcolreg, info); + + } else if(display->cmap.len) { + + fb_copy_cmap(&display->cmap, cmap, kspc ? 0 : 2); + + } else { + + int size = sisfb_get_cmap_len(&display->var); + fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); + + } + + return 0; +} + +static int +sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + struct display *display; + int err, size; + + display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp; + + size = sisfb_get_cmap_len(&display->var); + if(display->cmap.len != size) { + err = fb_alloc_cmap(&display->cmap, size, 0); + if(err) return err; + } + + if(con == ivideo->currcon) { + return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info); + } else { + fb_copy_cmap(cmap, &display->cmap, kspc ? 0 : 1); + } + + return 0; +} + +static int +sisfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info* info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + int err; + + if(var->vmode & FB_VMODE_YWRAP) return -EINVAL; + + if((var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual) || + (var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)) { + return -EINVAL; + } + + if(con == ivideo->currcon) { + if((err = sisfb_pan_var(ivideo, var)) < 0) return err; + } + + fb_display[con].var.xoffset = var->xoffset; + fb_display[con].var.yoffset = var->yoffset; + + return 0; +} + +static int +sisfb_update_var(int con, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + + return(sisfb_pan_var(ivideo, &fb_display[con].var)); +} + +static int +sisfb_switch(int con, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + int cols, rows; + + if(fb_display[ivideo->currcon].cmap.len) { + fb_get_cmap(&fb_display[ivideo->currcon].cmap, 1, sis_getcolreg, info); + } + + fb_display[con].var.activate = FB_ACTIVATE_NOW; + + if(!memcmp(&fb_display[con].var, &fb_display[ivideo->currcon].var, + sizeof(struct fb_var_screeninfo))) { + ivideo->currcon = con; + return 1; + } + + ivideo->currcon = con; + + sisfb_do_set_var(&fb_display[con].var, 1, info); + + sisfb_set_disp(con, &fb_display[con].var, info); + + sisfb_do_install_cmap(con, info); + + cols = sisbios_mode[ivideo->sisfb_mode_idx].cols; + rows = sisbios_mode[ivideo->sisfb_mode_idx].rows; + vc_resize_con(rows, cols, fb_display[con].conp->vc_num); + + sisfb_update_var(con, info); + + return 1; +} + +static void +sisfb_blank(int blank, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + + sisfb_myblank(ivideo, blank); +} +#endif + +/* ------------ FBDev related routines for 2.6 series ----------- */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + +static int +sisfb_open(struct fb_info *info, int user) +{ + return 0; +} + +static int +sisfb_release(struct fb_info *info, int user) +{ + return 0; +} + +static int +sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + + if(regno >= sisfb_get_cmap_len(&info->var)) return 1; + + switch(info->var.bits_per_pixel) { + case 8: + outSISREG(SISDACA, regno); + outSISREG(SISDACD, (red >> 10)); + outSISREG(SISDACD, (green >> 10)); + outSISREG(SISDACD, (blue >> 10)); + if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { + outSISREG(SISDAC2A, regno); + outSISREG(SISDAC2D, (red >> 8)); + outSISREG(SISDAC2D, (green >> 8)); + outSISREG(SISDAC2D, (blue >> 8)); + } + break; + case 16: + ((u32 *)(info->pseudo_palette))[regno] = + ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); + break; + case 32: + red >>= 8; + green >>= 8; + blue >>= 8; + ((u32 *)(info->pseudo_palette))[regno] = + (red << 16) | (green << 8) | (blue); + break; + } + return 0; +} + +static int +sisfb_set_par(struct fb_info *info) +{ + int err; + + if((err = sisfb_do_set_var(&info->var, 1, info))) { + return err; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) + sisfb_get_fix(&info->fix, info->currcon, info); +#else + sisfb_get_fix(&info->fix, -1, info); +#endif + return 0; +} + +static int +sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + unsigned int htotal = 0, vtotal = 0, myrateindex = 0; + unsigned int drate = 0, hrate = 0, maxyres; + int found_mode = 0; + int refresh_rate, search_idx; + BOOLEAN recalc_clock = FALSE; + u32 pixclock; + + htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len; + + vtotal = var->upper_margin + var->lower_margin + var->vsync_len; + + pixclock = var->pixclock; + + if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) { + vtotal += var->yres; + vtotal <<= 1; + } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { + vtotal += var->yres; + vtotal <<= 2; + } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { + vtotal += var->yres; + vtotal <<= 1; + } else vtotal += var->yres; + + if(!(htotal) || !(vtotal)) { + SISFAIL("sisfb: no valid timing data"); + } + + search_idx = 0; + while( (sisbios_mode[search_idx].mode_no[0] != 0) && + (sisbios_mode[search_idx].xres <= var->xres) ) { + if( (sisbios_mode[search_idx].xres == var->xres) && + (sisbios_mode[search_idx].yres == var->yres) && + (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) { + if(sisfb_validate_mode(ivideo, search_idx, ivideo->currentvbflags) > 0) { + found_mode = 1; + break; + } + } + search_idx++; + } + + if(!found_mode) { + search_idx = 0; + while(sisbios_mode[search_idx].mode_no[0] != 0) { + if( (var->xres <= sisbios_mode[search_idx].xres) && + (var->yres <= sisbios_mode[search_idx].yres) && + (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) { + if(sisfb_validate_mode(ivideo,search_idx, ivideo->currentvbflags) > 0) { + found_mode = 1; + break; + } + } + search_idx++; + } + if(found_mode) { + printk(KERN_DEBUG "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n", + var->xres, var->yres, var->bits_per_pixel, + sisbios_mode[search_idx].xres, + sisbios_mode[search_idx].yres, + var->bits_per_pixel); + var->xres = sisbios_mode[search_idx].xres; + var->yres = sisbios_mode[search_idx].yres; + + + } else { + printk(KERN_ERR "sisfb: Failed to find supported mode near %dx%dx%d\n", + var->xres, var->yres, var->bits_per_pixel); + return -EINVAL; + } + } + + if( ((ivideo->vbflags & VB_LVDS) || /* Slave modes on LVDS and 301B-DH */ + ((ivideo->vbflags & VB_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) && + (var->bits_per_pixel == 8) ) { + refresh_rate = 60; + recalc_clock = TRUE; + } else if( (ivideo->current_htotal == htotal) && /* x=x & y=y & c=c -> assume depth change */ + (ivideo->current_vtotal == vtotal) && + (ivideo->current_pixclock == pixclock) ) { + drate = 1000000000 / pixclock; + hrate = (drate * 1000) / htotal; + refresh_rate = (unsigned int) (hrate * 2 / vtotal); + } else if( ( (ivideo->current_htotal != htotal) || /* x!=x | y!=y & c=c -> invalid pixclock */ + (ivideo->current_vtotal != vtotal) ) && + (ivideo->current_pixclock == var->pixclock) ) { + if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) { + refresh_rate = ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]; + } else if(ivideo->sisfb_parm_rate != -1) { + /* Sic, sisfb_parm_rate - want to know originally desired rate here */ + refresh_rate = ivideo->sisfb_parm_rate; + } else { + refresh_rate = 60; + } + recalc_clock = TRUE; + } else if((pixclock) && (htotal) && (vtotal)) { + drate = 1000000000 / pixclock; + hrate = (drate * 1000) / htotal; + refresh_rate = (unsigned int) (hrate * 2 / vtotal); + } else if(ivideo->current_refresh_rate) { + refresh_rate = ivideo->current_refresh_rate; + recalc_clock = TRUE; + } else { + refresh_rate = 60; + recalc_clock = TRUE; + } + + myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx); + + /* Eventually recalculate timing and clock */ + if(recalc_clock) { + if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx; + var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, + &ivideo->sishw_ext, + sisbios_mode[search_idx].mode_no[ivideo->mni], + myrateindex)); + sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext, + sisbios_mode[search_idx].mode_no[ivideo->mni], myrateindex, var); + if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { + var->pixclock <<= 1; + } + } + + if(ivideo->sisfb_thismonitor.datavalid) { + if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx, + myrateindex, refresh_rate)) { + printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); + } + } + + /* Adapt RGB settings */ + sisfb_bpp_to_var(ivideo, var); + + /* Sanity check for offsets */ + if(var->xoffset < 0) var->xoffset = 0; + if(var->yoffset < 0) var->yoffset = 0; + + if(var->xres > var->xres_virtual) { + var->xres_virtual = var->xres; + } + + if(ivideo->sisfb_ypan) { + maxyres = sisfb_calc_maxyres(ivideo, var); + if(ivideo->sisfb_max) { + var->yres_virtual = maxyres; + } else { + if(var->yres_virtual > maxyres) { + var->yres_virtual = maxyres; + } + } + if(var->yres_virtual <= var->yres) { + var->yres_virtual = var->yres; + } + } else { + if(var->yres != var->yres_virtual) { + var->yres_virtual = var->yres; + } + var->xoffset = 0; + var->yoffset = 0; + } + + /* Truncate offsets to maximum if too high */ + if(var->xoffset > var->xres_virtual - var->xres) { + var->xoffset = var->xres_virtual - var->xres - 1; + } + + if(var->yoffset > var->yres_virtual - var->yres) { + var->yoffset = var->yres_virtual - var->yres - 1; + } + + /* Set everything else to 0 */ + var->red.msb_right = + var->green.msb_right = + var->blue.msb_right = + var->transp.offset = + var->transp.length = + var->transp.msb_right = 0; + + return 0; +} + +static int +sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + int err; + + if(var->xoffset > (var->xres_virtual - var->xres)) { + return -EINVAL; + } + if(var->yoffset > (var->yres_virtual - var->yres)) { + return -EINVAL; + } + + if(var->vmode & FB_VMODE_YWRAP) return -EINVAL; + + if(var->xoffset + info->var.xres > info->var.xres_virtual || + var->yoffset + info->var.yres > info->var.yres_virtual) { + return -EINVAL; + } + + if((err = sisfb_pan_var(ivideo, var)) < 0) return err; + + info->var.xoffset = var->xoffset; + info->var.yoffset = var->yoffset; + + return 0; +} + +static int +sisfb_blank(int blank, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + + return(sisfb_myblank(ivideo, blank)); +} + +#endif + +/* ----------- FBDev related routines for all series ---------- */ + +static int +sisfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + int con, +#endif + struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + struct sis_memreq sismemreq; + struct fb_vblank sisvbblank; + sisfb_info x; + u32 gpu32 = 0; +#ifndef __user +#define __user +#endif + u32 __user *argp = (u32 __user *)arg; + + switch (cmd) { + case FBIO_ALLOC: + if(!capable(CAP_SYS_RAWIO)) { + return -EPERM; + } + if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq))) { + return -EFAULT; + } + sis_malloc(&sismemreq); + if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) { + sis_free((u32)sismemreq.offset); + return -EFAULT; + } + break; + + case FBIO_FREE: + if(!capable(CAP_SYS_RAWIO)) { + return -EPERM; + } + if(get_user(gpu32, argp)) { + return -EFAULT; + } + sis_free(gpu32); + break; + + case FBIOGET_VBLANK: + sisvbblank.count = 0; + sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount); + if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank))) { + return -EFAULT; + } + break; + + case SISFB_GET_INFO_SIZE: + return put_user(sizeof(sisfb_info), argp); + + case SISFB_GET_INFO_OLD: + if(ivideo->warncount++ < 50) { + printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); + } + case SISFB_GET_INFO: /* For communication with X driver */ + x.sisfb_id = SISFB_ID; + x.sisfb_version = VER_MAJOR; + x.sisfb_revision = VER_MINOR; + x.sisfb_patchlevel = VER_LEVEL; + x.chip_id = ivideo->chip_id; + x.memory = ivideo->video_size / 1024; + x.heapstart = ivideo->heapstart / 1024; + if(ivideo->modechanged) { + x.fbvidmode = ivideo->mode_no; + } else { + x.fbvidmode = ivideo->modeprechange; + } + x.sisfb_caps = ivideo->caps; + x.sisfb_tqlen = 512; /* yet fixed */ + x.sisfb_pcibus = ivideo->pcibus; + x.sisfb_pcislot = ivideo->pcislot; + x.sisfb_pcifunc = ivideo->pcifunc; + x.sisfb_lcdpdc = ivideo->detectedpdc; + x.sisfb_lcdpdca = ivideo->detectedpdca; + x.sisfb_lcda = ivideo->detectedlcda; + x.sisfb_vbflags = ivideo->vbflags; + x.sisfb_currentvbflags = ivideo->currentvbflags; + x.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler; + x.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT; + x.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0; + x.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0; + x.sisfb_emi30 = ivideo->SiS_Pr.EMI_30; + x.sisfb_emi31 = ivideo->SiS_Pr.EMI_31; + x.sisfb_emi32 = ivideo->SiS_Pr.EMI_32; + x.sisfb_emi33 = ivideo->SiS_Pr.EMI_33; + x.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32); + x.sisfb_tvypos = (u16)(ivideo->tvypos + 32); + + if(copy_to_user((void __user *)arg, &x, sizeof(x))) { + return -EFAULT; + } + break; + + case SISFB_GET_VBRSTATUS_OLD: + if(ivideo->warncount++ < 50) { + printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); + } + case SISFB_GET_VBRSTATUS: + if(sisfb_CheckVBRetrace(ivideo)) { + return put_user((u32)1, argp); + } else { + return put_user((u32)0, argp); + } + + case SISFB_GET_AUTOMAXIMIZE_OLD: + if(ivideo->warncount++ < 50) { + printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); + } + case SISFB_GET_AUTOMAXIMIZE: + if(ivideo->sisfb_max) return put_user((u32)1, argp); + else return put_user((u32)0, argp); + + case SISFB_SET_AUTOMAXIMIZE_OLD: + if(ivideo->warncount++ < 50) { + printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); + } + case SISFB_SET_AUTOMAXIMIZE: + if(copy_from_user(&gpu32, argp, sizeof(gpu32))) { + return -EFAULT; + } + ivideo->sisfb_max = (gpu32) ? 1 : 0; + break; + + case SISFB_SET_TVPOSOFFSET: + if(copy_from_user(&gpu32, argp, sizeof(gpu32))) { + return -EFAULT; + } + sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32); + sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32); + break; + + case SISFB_GET_TVPOSOFFSET: + return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)), + argp); + + case SISFB_SET_LOCK: + if(copy_from_user(&gpu32, argp, sizeof(gpu32))) { + return -EFAULT; + } + ivideo->sisfblocked = (gpu32) ? 1 : 0; + break; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +#ifdef CONFIG_COMPAT +static long sisfb_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg, struct fb_info *info) +{ + int ret; + lock_kernel(); + ret = sisfb_ioctl(NULL, f, cmd, arg, info); + unlock_kernel(); + return ret; +} +#endif + +static int +sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) +{ + struct sis_video_info *ivideo = (struct sis_video_info *)info->par; + + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + + strcpy(fix->id, ivideo->myid); + + fix->smem_start = ivideo->video_base; + fix->smem_len = ivideo->sisfb_mem; + fix->type = FB_TYPE_PACKED_PIXELS; + fix->type_aux = 0; + fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; + fix->xpanstep = 1; + fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0; + fix->ywrapstep = 0; + fix->line_length = ivideo->video_linelength; + fix->mmio_start = ivideo->mmio_base; + fix->mmio_len = ivideo->mmio_size; + if(ivideo->sisvga_engine == SIS_300_VGA) { + fix->accel = FB_ACCEL_SIS_GLAMOUR; + } else if((ivideo->chip == SIS_330) || (ivideo->chip == SIS_760)) { + fix->accel = FB_ACCEL_SIS_XABRE; + } else { + fix->accel = FB_ACCEL_SIS_GLAMOUR_2; + } + + return 0; +} + +/* ---------------- fb_ops structures ----------------- */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +static struct fb_ops sisfb_ops = { + .owner = THIS_MODULE, + .fb_get_fix = sisfb_get_fix, + .fb_get_var = sisfb_get_var, + .fb_set_var = sisfb_set_var, + .fb_get_cmap = sisfb_get_cmap, + .fb_set_cmap = sisfb_set_cmap, + .fb_pan_display = sisfb_pan_display, + .fb_ioctl = sisfb_ioctl +}; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +static struct fb_ops sisfb_ops = { + .owner = THIS_MODULE, + .fb_open = sisfb_open, + .fb_release = sisfb_release, + .fb_check_var = sisfb_check_var, + .fb_set_par = sisfb_set_par, + .fb_setcolreg = sisfb_setcolreg, + .fb_pan_display = sisfb_pan_display, + .fb_blank = sisfb_blank, + .fb_fillrect = fbcon_sis_fillrect, + .fb_copyarea = fbcon_sis_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_cursor = soft_cursor, + .fb_sync = fbcon_sis_sync, + .fb_ioctl = sisfb_ioctl, +#ifdef CONFIG_COMPAT + .fb_compat_ioctl = sisfb_compat_ioctl, +#endif +}; +#endif + +/* ---------------- Chip generation dependent routines ---------------- */ + +static struct pci_dev * sisfb_get_northbridge(int basechipid) +{ + struct pci_dev *pdev = NULL; + int nbridgenum, nbridgeidx, i; + const unsigned short nbridgeids[] = { + PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */ + PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */ + PCI_DEVICE_ID_SI_730, + PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */ + PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */ + PCI_DEVICE_ID_SI_651, + PCI_DEVICE_ID_SI_740, + PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760 VGA */ + PCI_DEVICE_ID_SI_741, + PCI_DEVICE_ID_SI_660, + PCI_DEVICE_ID_SI_760 + }; + + switch(basechipid) { +#ifdef CONFIG_FB_SIS_300 + case SIS_540: nbridgeidx = 0; nbridgenum = 1; break; + case SIS_630: nbridgeidx = 1; nbridgenum = 2; break; +#endif +#ifdef CONFIG_FB_SIS_315 + case SIS_550: nbridgeidx = 3; nbridgenum = 1; break; + case SIS_650: nbridgeidx = 4; nbridgenum = 3; break; + case SIS_660: nbridgeidx = 7; nbridgenum = 4; break; +#endif + default: return NULL; + } + for(i = 0; i < nbridgenum; i++) { + if((pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridgeids[nbridgeidx+i], NULL))) break; + } + return pdev; +} + +static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo) +{ +#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) + u8 reg; +#endif + + ivideo->video_size = 0; + + switch(ivideo->chip) { +#ifdef CONFIG_FB_SIS_300 + case SIS_300: + inSISIDXREG(SISSR, 0x14, reg); + ivideo->video_size = ((reg & 0x3F) + 1) << 20; + break; + case SIS_540: + case SIS_630: + case SIS_730: + if(!ivideo->nbridge) return -1; + pci_read_config_byte(ivideo->nbridge, 0x63, ®); + ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21); + break; +#endif +#ifdef CONFIG_FB_SIS_315 + case SIS_315H: + case SIS_315PRO: + case SIS_315: + inSISIDXREG(SISSR, 0x14, reg); + ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; + switch((reg >> 2) & 0x03) { + case 0x01: + case 0x03: + ivideo->video_size <<= 1; + break; + case 0x02: + ivideo->video_size += (ivideo->video_size/2); + } + break; + case SIS_330: + inSISIDXREG(SISSR, 0x14, reg); + ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; + if(reg & 0x0c) ivideo->video_size <<= 1; + break; + case SIS_550: + case SIS_650: + case SIS_740: + inSISIDXREG(SISSR, 0x14, reg); + ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20; + break; + case SIS_661: + case SIS_741: + inSISIDXREG(SISCR, 0x79, reg); + ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; + break; + case SIS_660: + case SIS_760: + inSISIDXREG(SISCR, 0x79, reg); + reg = (reg & 0xf0) >> 4; + if(reg) ivideo->video_size = (1 << reg) << 20; + inSISIDXREG(SISCR, 0x78, reg); + reg &= 0x30; + if(reg) { + if(reg == 0x10) ivideo->video_size += (32 << 20); + else ivideo->video_size += (64 << 20); + } + break; +#endif + default: + return -1; + } + return 0; +} + +/* -------------- video bridge device detection --------------- */ + +static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo) +{ + u8 cr32, temp; + +#ifdef CONFIG_FB_SIS_300 + if(ivideo->sisvga_engine == SIS_300_VGA) { + inSISIDXREG(SISSR, 0x17, temp); + if((temp & 0x0F) && (ivideo->chip != SIS_300)) { + /* PAL/NTSC is stored on SR16 on such machines */ + if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) { + inSISIDXREG(SISSR, 0x16, temp); + if(temp & 0x20) + ivideo->vbflags |= TV_PAL; + else + ivideo->vbflags |= TV_NTSC; + } + } + } +#endif + + inSISIDXREG(SISCR, 0x32, cr32); + + if(cr32 & SIS_CRT1) { + ivideo->sisfb_crt1off = 0; + } else { + ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0; + } + + ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA); + + if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV; + if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD; + if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA; + + /* Check given parms for hardware compatibility. + * (Cannot do this in the search_xx routines since we don't + * know what hardware we are running on then) + */ + + if(ivideo->chip != SIS_550) { + ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0; + } + + if(ivideo->sisfb_tvplug != -1) { + if( (ivideo->sisvga_engine != SIS_315_VGA) || + (!(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) ) { + if(ivideo->sisfb_tvplug & TV_YPBPR) { + ivideo->sisfb_tvplug = -1; + printk(KERN_ERR "sisfb: YPbPr not supported\n"); + } + } + } + if(ivideo->sisfb_tvplug != -1) { + if( (ivideo->sisvga_engine != SIS_315_VGA) || + (!(ivideo->vbflags & (VB_301|VB_301B|VB_302B))) ) { + if(ivideo->sisfb_tvplug & TV_HIVISION) { + ivideo->sisfb_tvplug = -1; + printk(KERN_ERR "sisfb: HiVision not supported\n"); + } + } + } + if(ivideo->sisfb_tvstd != -1) { + if( (!(ivideo->vbflags & VB_SISBRIDGE)) && + (!((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags & VB_CHRONTEL))) ) { + if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) { + ivideo->sisfb_tvstd = -1; + printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n"); + } + } + } + + /* Detect/set TV plug & type */ + if(ivideo->sisfb_tvplug != -1) { + ivideo->vbflags |= ivideo->sisfb_tvplug; + } else { + if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */ + else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION; + else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART; + else { + if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO; + if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO; + } + } + + if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) { + if(ivideo->sisfb_tvstd != -1) { + ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ); + ivideo->vbflags |= ivideo->sisfb_tvstd; + } + if(ivideo->vbflags & TV_SCART) { + ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ); + ivideo->vbflags |= TV_PAL; + } + if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) { + if(ivideo->sisvga_engine == SIS_300_VGA) { + inSISIDXREG(SISSR, 0x38, temp); + if(temp & 0x01) ivideo->vbflags |= TV_PAL; + else ivideo->vbflags |= TV_NTSC; + } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) { + inSISIDXREG(SISSR, 0x38, temp); + if(temp & 0x01) ivideo->vbflags |= TV_PAL; + else ivideo->vbflags |= TV_NTSC; + } else { + inSISIDXREG(SISCR, 0x79, temp); + if(temp & 0x20) ivideo->vbflags |= TV_PAL; + else ivideo->vbflags |= TV_NTSC; + } + } + } + + /* Copy forceCRT1 option to CRT1off if option is given */ + if(ivideo->sisfb_forcecrt1 != -1) { + ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1; + } +} + +static void __devinit sisfb_get_VB_type(struct sis_video_info *ivideo) +{ + char stdstr[] = "sisfb: Detected"; + char bridgestr[] = "video bridge"; + u8 vb_chipid; + u8 reg; + + inSISIDXREG(SISPART4, 0x00, vb_chipid); + switch(vb_chipid) { + case 0x01: + inSISIDXREG(SISPART4, 0x01, reg); + if(reg < 0xb0) { + ivideo->vbflags |= VB_301; + printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr); + } else if(reg < 0xc0) { + ivideo->vbflags |= VB_301B; + inSISIDXREG(SISPART4,0x23,reg); + if(!(reg & 0x02)) { + ivideo->vbflags |= VB_30xBDH; + printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr); + } else { + printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr); + } + } else if(reg < 0xd0) { + ivideo->vbflags |= VB_301C; + printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr); + } else if(reg < 0xe0) { + ivideo->vbflags |= VB_301LV; + printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr); + } else if(reg <= 0xe1) { + inSISIDXREG(SISPART4,0x39,reg); + if(reg == 0xff) { + ivideo->vbflags |= VB_302LV; + printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr); + } else { + ivideo->vbflags |= VB_301C; + printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr); +#if 0 + ivideo->vbflags |= VB_302ELV; + printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr); +#endif + } + } + break; + case 0x02: + ivideo->vbflags |= VB_302B; + printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr); + break; + } + + if((!(ivideo->vbflags & VB_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) { + inSISIDXREG(SISCR, 0x37, reg); + reg &= SIS_EXTERNAL_CHIP_MASK; + reg >>= 1; + if(ivideo->sisvga_engine == SIS_300_VGA) { +#ifdef CONFIG_FB_SIS_300 + switch(reg) { + case SIS_EXTERNAL_CHIP_LVDS: + ivideo->vbflags |= VB_LVDS; + break; + case SIS_EXTERNAL_CHIP_TRUMPION: + ivideo->vbflags |= VB_TRUMPION; + break; + case SIS_EXTERNAL_CHIP_CHRONTEL: + ivideo->vbflags |= VB_CHRONTEL; + break; + case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL: + ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); + break; + } + if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 1; +#endif + } else if(ivideo->chip < SIS_661) { +#ifdef CONFIG_FB_SIS_315 + switch (reg) { + case SIS310_EXTERNAL_CHIP_LVDS: + ivideo->vbflags |= VB_LVDS; + break; + case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL: + ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); + break; + } + if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2; +#endif + } else if(ivideo->chip >= SIS_661) { +#ifdef CONFIG_FB_SIS_315 + inSISIDXREG(SISCR, 0x38, reg); + reg >>= 5; + switch(reg) { + case 0x02: + ivideo->vbflags |= VB_LVDS; + break; + case 0x03: + ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); + break; + case 0x04: + ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); + break; + } + if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2; +#endif + } + if(ivideo->vbflags & VB_LVDS) { + printk(KERN_INFO "%s LVDS transmitter\n", stdstr); + } + if(ivideo->vbflags & VB_TRUMPION) { + printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr); + } + if(ivideo->vbflags & VB_CHRONTEL) { + printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr); + } + if(ivideo->vbflags & VB_CONEXANT) { + printk(KERN_INFO "%s Conexant external device\n", stdstr); + } + } + + if(ivideo->vbflags & VB_SISBRIDGE) { + SiS_Sense30x(ivideo); + } else if(ivideo->vbflags & VB_CHRONTEL) { + SiS_SenseCh(ivideo); + } +} + +/* ------------------ Sensing routines ------------------ */ + +static BOOLEAN __devinit sisfb_test_DDC1(struct sis_video_info *ivideo) +{ + unsigned short old; + int count = 48; + + old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr); + do { + if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break; + } while(count--); + return (count == -1) ? FALSE : TRUE; +} + +static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo) +{ + BOOLEAN mustwait = FALSE; + u8 sr1F, cr17; +#ifdef CONFIG_FB_SIS_315 + u8 cr63=0; +#endif + u16 temp = 0xffff; + int i; + + inSISIDXREG(SISSR,0x1F,sr1F); + orSISIDXREG(SISSR,0x1F,0x04); + andSISIDXREG(SISSR,0x1F,0x3F); + if(sr1F & 0xc0) mustwait = TRUE; + +#ifdef CONFIG_FB_SIS_315 + if(ivideo->sisvga_engine == SIS_315_VGA) { + inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,cr63); + cr63 &= 0x40; + andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF); + } +#endif + + inSISIDXREG(SISCR,0x17,cr17); + cr17 &= 0x80; + if(!cr17) { + orSISIDXREG(SISCR,0x17,0x80); + mustwait = TRUE; + outSISIDXREG(SISSR, 0x00, 0x01); + outSISIDXREG(SISSR, 0x00, 0x03); + } + + if(mustwait) { + for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo); + } + +#ifdef CONFIG_FB_SIS_315 + if(ivideo->chip >= SIS_330) { + andSISIDXREG(SISCR,0x32,~0x20); + if(ivideo->chip >= SIS_340) { + outSISIDXREG(SISCR, 0x57, 0x4a); + } else { + outSISIDXREG(SISCR, 0x57, 0x5f); + } + orSISIDXREG(SISCR, 0x53, 0x02); + while((inSISREG(SISINPSTAT)) & 0x01) break; + while(!((inSISREG(SISINPSTAT)) & 0x01)) break; + if((inSISREG(SISMISCW)) & 0x10) temp = 1; + andSISIDXREG(SISCR, 0x53, 0xfd); + andSISIDXREG(SISCR, 0x57, 0x00); + } +#endif + + if(temp == 0xffff) { + i = 3; + do { + temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 0, 0, NULL); + } while(((temp == 0) || (temp == 0xffff)) && i--); + + if((temp == 0) || (temp == 0xffff)) { + if(sisfb_test_DDC1(ivideo)) temp = 1; + } + } + + if((temp) && (temp != 0xffff)) { + orSISIDXREG(SISCR,0x32,0x20); + } + +#ifdef CONFIG_FB_SIS_315 + if(ivideo->sisvga_engine == SIS_315_VGA) { + setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,cr63); + } +#endif + + setSISIDXREG(SISCR,0x17,0x7F,cr17); + + outSISIDXREG(SISSR,0x1F,sr1F); +} + +/* Determine and detect attached devices on SiS30x */ +static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test) +{ + int temp, mytest, result, i, j; + + for(j = 0; j < 10; j++) { + result = 0; + for(i = 0; i < 3; i++) { + mytest = test; + outSISIDXREG(SISPART4,0x11,(type & 0x00ff)); + temp = (type >> 8) | (mytest & 0x00ff); + setSISIDXREG(SISPART4,0x10,0xe0,temp); + SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500); + mytest >>= 8; + mytest &= 0x7f; + inSISIDXREG(SISPART4,0x03,temp); + temp ^= 0x0e; + temp &= mytest; + if(temp == mytest) result++; +#if 1 + outSISIDXREG(SISPART4,0x11,0x00); + andSISIDXREG(SISPART4,0x10,0xe0); + SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000); +#endif + } + if((result == 0) || (result >= 2)) break; + } + return(result); +} + +static void __devinit SiS_Sense30x(struct sis_video_info *ivideo) +{ + u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0; + u16 svhs=0, svhs_c=0; + u16 cvbs=0, cvbs_c=0; + u16 vga2=0, vga2_c=0; + int myflag, result; + char stdstr[] = "sisfb: Detected"; + char tvstr[] = "TV connected to"; + + if(ivideo->vbflags & VB_301) { + svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1; + inSISIDXREG(SISPART4,0x01,myflag); + if(myflag & 0x04) { + svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd; + } + } else if(ivideo->vbflags & (VB_301B | VB_302B)) { + svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190; + } else if(ivideo->vbflags & (VB_301LV | VB_302LV)) { + svhs = 0x0200; cvbs = 0x0100; + } else if(ivideo->vbflags & (VB_301C | VB_302ELV)) { + svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190; + } else return; + + vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804; + if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) { + svhs_c = 0x0408; cvbs_c = 0x0808; + } + biosflag = 2; + + if(ivideo->chip == SIS_300) { + inSISIDXREG(SISSR,0x3b,myflag); + if(!(myflag & 0x01)) vga2 = vga2_c = 0; + } + + inSISIDXREG(SISSR,0x1e,backupSR_1e); + orSISIDXREG(SISSR,0x1e,0x20); + + inSISIDXREG(SISPART4,0x0d,backupP4_0d); + if(ivideo->vbflags & VB_301C) { + setSISIDXREG(SISPART4,0x0d,~0x07,0x01); + } else { + orSISIDXREG(SISPART4,0x0d,0x04); + } + SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000); + + inSISIDXREG(SISPART2,0x00,backupP2_00); + outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc)); + + inSISIDXREG(SISPART2,0x4d,backupP2_4d); + if(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV)) { + outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10)); + } + + if(!(ivideo->vbflags & VB_301C)) { + SISDoSense(ivideo, 0, 0); + } + + andSISIDXREG(SISCR, 0x32, ~0x14); + + if(vga2_c || vga2) { + if(SISDoSense(ivideo, vga2, vga2_c)) { + if(biosflag & 0x01) { + printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr); + orSISIDXREG(SISCR, 0x32, 0x04); + } else { + printk(KERN_INFO "%s secondary VGA connection\n", stdstr); + orSISIDXREG(SISCR, 0x32, 0x10); + } + } + } + + andSISIDXREG(SISCR, 0x32, 0x3f); + + if(ivideo->vbflags & VB_301C) { + orSISIDXREG(SISPART4,0x0d,0x04); + } + + if((ivideo->sisvga_engine == SIS_315_VGA) && + (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV))) { + outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10)); + SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000); + if((result = SISDoSense(ivideo, svhs, 0x0604))) { + if((result = SISDoSense(ivideo, cvbs, 0x0804))) { + printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr); + orSISIDXREG(SISCR,0x32,0x80); + } + } + outSISIDXREG(SISPART2,0x4d,backupP2_4d); + } + + andSISIDXREG(SISCR, 0x32, ~0x03); + + if(!(ivideo->vbflags & TV_YPBPR)) { + if((result = SISDoSense(ivideo, svhs, svhs_c))) { + printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr); + orSISIDXREG(SISCR, 0x32, 0x02); + } + if((biosflag & 0x02) || (!result)) { + if(SISDoSense(ivideo, cvbs, cvbs_c)) { + printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr); + orSISIDXREG(SISCR, 0x32, 0x01); + } + } + } + + SISDoSense(ivideo, 0, 0); + + outSISIDXREG(SISPART2,0x00,backupP2_00); + outSISIDXREG(SISPART4,0x0d,backupP4_0d); + outSISIDXREG(SISSR,0x1e,backupSR_1e); + + if(ivideo->vbflags & VB_301C) { + inSISIDXREG(SISPART2,0x00,biosflag); + if(biosflag & 0x20) { + for(myflag = 2; myflag > 0; myflag--) { + biosflag ^= 0x20; + outSISIDXREG(SISPART2,0x00,biosflag); + } + } + } + + outSISIDXREG(SISPART2,0x00,backupP2_00); +} + +/* Determine and detect attached TV's on Chrontel */ +static void __devinit SiS_SenseCh(struct sis_video_info *ivideo) +{ +#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) + u8 temp1, temp2; + char stdstr[] = "sisfb: Chrontel: Detected TV connected to"; +#endif +#ifdef CONFIG_FB_SIS_300 + unsigned char test[3]; + int i; +#endif + + if(ivideo->chip < SIS_315H) { + +#ifdef CONFIG_FB_SIS_300 + ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */ + SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */ + SiS_DDC2Delay(&ivideo->SiS_Pr, 1000); + temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25); + /* See Chrontel TB31 for explanation */ + temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e); + if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) { + SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b0e); + SiS_DDC2Delay(&ivideo->SiS_Pr, 300); + } + temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25); + if(temp2 != temp1) temp1 = temp2; + + if((temp1 >= 0x22) && (temp1 <= 0x50)) { + /* Read power status */ + temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e); + if((temp1 & 0x03) != 0x03) { + /* Power all outputs */ + SiS_SetCH700x(&ivideo->SiS_Pr, 0x0B0E); + SiS_DDC2Delay(&ivideo->SiS_Pr, 300); + } + /* Sense connected TV devices */ + for(i = 0; i < 3; i++) { + SiS_SetCH700x(&ivideo->SiS_Pr, 0x0110); + SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); + SiS_SetCH700x(&ivideo->SiS_Pr, 0x0010); + SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); + temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10); + if(!(temp1 & 0x08)) test[i] = 0x02; + else if(!(temp1 & 0x02)) test[i] = 0x01; + else test[i] = 0; + SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); + } + + if(test[0] == test[1]) temp1 = test[0]; + else if(test[0] == test[2]) temp1 = test[0]; + else if(test[1] == test[2]) temp1 = test[1]; + else { + printk(KERN_INFO + "sisfb: TV detection unreliable - test results varied\n"); + temp1 = test[2]; + } + if(temp1 == 0x02) { + printk(KERN_INFO "%s SVIDEO output\n", stdstr); + ivideo->vbflags |= TV_SVIDEO; + orSISIDXREG(SISCR, 0x32, 0x02); + andSISIDXREG(SISCR, 0x32, ~0x05); + } else if (temp1 == 0x01) { + printk(KERN_INFO "%s CVBS output\n", stdstr); + ivideo->vbflags |= TV_AVIDEO; + orSISIDXREG(SISCR, 0x32, 0x01); + andSISIDXREG(SISCR, 0x32, ~0x06); + } else { + SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8); + andSISIDXREG(SISCR, 0x32, ~0x07); + } + } else if(temp1 == 0) { + SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8); + andSISIDXREG(SISCR, 0x32, ~0x07); + } + /* Set general purpose IO for Chrontel communication */ + SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00); +#endif + + } else { + +#ifdef CONFIG_FB_SIS_315 + ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */ + temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49); + SiS_SetCH701x(&ivideo->SiS_Pr, 0x2049); + SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); + temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20); + temp2 |= 0x01; + SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20); + SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); + temp2 ^= 0x01; + SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20); + SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); + temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20); + SiS_SetCH701x(&ivideo->SiS_Pr, (temp1 << 8) | 0x49); + temp1 = 0; + if(temp2 & 0x02) temp1 |= 0x01; + if(temp2 & 0x10) temp1 |= 0x01; + if(temp2 & 0x04) temp1 |= 0x02; + if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04; + switch(temp1) { + case 0x01: + printk(KERN_INFO "%s CVBS output\n", stdstr); + ivideo->vbflags |= TV_AVIDEO; + orSISIDXREG(SISCR, 0x32, 0x01); + andSISIDXREG(SISCR, 0x32, ~0x06); + break; + case 0x02: + printk(KERN_INFO "%s SVIDEO output\n", stdstr); + ivideo->vbflags |= TV_SVIDEO; + orSISIDXREG(SISCR, 0x32, 0x02); + andSISIDXREG(SISCR, 0x32, ~0x05); + break; + case 0x04: + printk(KERN_INFO "%s SCART output\n", stdstr); + orSISIDXREG(SISCR, 0x32, 0x04); + andSISIDXREG(SISCR, 0x32, ~0x03); + break; + default: + andSISIDXREG(SISCR, 0x32, ~0x07); + } +#endif + } +} + +/* ------------------------ Heap routines -------------------------- */ + +static u32 __devinit +sisfb_getheapstart(struct sis_video_info *ivideo) +{ + u32 ret = ivideo->sisfb_parm_mem * 1024; + u32 max = ivideo->video_size - ivideo->hwcursor_size; + u32 def; + + /* Calculate heap start = end of memory for console + * + * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ + * C = console, D = heap, H = HWCursor, Q = cmd-queue + * + * Basically given by "mem" parameter + * + * maximum = videosize - cmd_queue - hwcursor + * (results in a heap of size 0) + * default = SiS 300: depends on videosize + * SiS 315/330: 32k below max + */ + + if(ivideo->sisvga_engine == SIS_300_VGA) { + max -= TURBO_QUEUE_AREA_SIZE; + if(ivideo->video_size > 0x1000000) { + def = 0xc00000; + } else if(ivideo->video_size > 0x800000) { + def = 0x800000; + } else { + def = 0x400000; + } + } else { + max -= COMMAND_QUEUE_AREA_SIZE; + def = max - 0x8000; + } + + if((!ret) || (ret > max) || (ivideo->cardnumber != 0)) { + ret = def; + } + + return ret; +} + +static int __devinit +sisfb_heap_init(struct sis_video_info *ivideo) +{ + SIS_OH *poh; + + ivideo->heapstart = ivideo->sisfb_mem = sisfb_getheapstart(ivideo); + + ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart; + ivideo->sisfb_heap_end = ivideo->video_vbase + ivideo->video_size; + + /* Initialize command queue (We use MMIO only) */ + +#ifdef CONFIG_FB_SIS_315 + if(ivideo->sisvga_engine == SIS_315_VGA) { + u32 tempq = 0; + u8 temp = 0; + + ivideo->sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE; + + outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); + outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET); + + tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT); + MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq); + + temp = SIS_CMD_QUEUE_SIZE_512k; + temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR); + outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp); + + tempq = (u32)(ivideo->video_size - COMMAND_QUEUE_AREA_SIZE); + MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq); + + ivideo->caps |= MMIO_CMD_QUEUE_CAP; + } +#endif + +#ifdef CONFIG_FB_SIS_300 + if(ivideo->sisvga_engine == SIS_300_VGA) { + unsigned long tqueue_pos; + u8 tq_state; + + ivideo->sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE; + + tqueue_pos = (ivideo->video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024); + + inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state); + tq_state |= 0xf0; + tq_state &= 0xfc; + tq_state |= (u8)(tqueue_pos >> 8); + outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state); + + outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff)); + + ivideo->caps |= TURBO_QUEUE_CAP; + } +#endif + + /* Reserve memory for the HWCursor */ + ivideo->sisfb_heap_end -= ivideo->hwcursor_size; + ivideo->hwcursor_vbase = ivideo->sisfb_heap_end; + ivideo->caps |= HW_CURSOR_CAP; + + ivideo->sisfb_heap_size = ivideo->sisfb_heap_end - ivideo->sisfb_heap_start; + + if(ivideo->cardnumber == 0) { + + printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n", + (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024)); + + sisfb_heap.vinfo = ivideo; + + sisfb_heap.poha_chain = NULL; + sisfb_heap.poh_freelist = NULL; + + poh = sisfb_poh_new_node(); + if(poh == NULL) return 1; + + poh->poh_next = &sisfb_heap.oh_free; + poh->poh_prev = &sisfb_heap.oh_free; + poh->size = ivideo->sisfb_heap_size; + poh->offset = ivideo->heapstart; + + sisfb_heap.oh_free.poh_next = poh; + sisfb_heap.oh_free.poh_prev = poh; + sisfb_heap.oh_free.size = 0; + sisfb_heap.max_freesize = poh->size; + + sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used; + sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used; + sisfb_heap.oh_used.size = SENTINEL; + + } else { + + printk(KERN_INFO "Skipped heap initialization for secondary cards\n"); + + } + + return 0; +} + +static SIS_OH * +sisfb_poh_new_node(void) +{ + int i; + unsigned long cOhs; + SIS_OHALLOC *poha; + SIS_OH *poh; + + if(sisfb_heap.poh_freelist == NULL) { + poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL); + if(!poha) return NULL; + + poha->poha_next = sisfb_heap.poha_chain; + sisfb_heap.poha_chain = poha; + + cOhs = (SIS_OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1; + + poh = &poha->aoh[0]; + for(i = cOhs - 1; i != 0; i--) { + poh->poh_next = poh + 1; + poh = poh + 1; + } + + poh->poh_next = NULL; + sisfb_heap.poh_freelist = &poha->aoh[0]; + } + + poh = sisfb_heap.poh_freelist; + sisfb_heap.poh_freelist = poh->poh_next; + + return (poh); +} + +static SIS_OH * +sisfb_poh_allocate(u32 size) +{ + SIS_OH *pohThis; + SIS_OH *pohRoot; + int bAllocated = 0; + + if(size > sisfb_heap.max_freesize) { + DPRINTK("sisfb: Can't allocate %dk video memory\n", + (unsigned int) size / 1024); + return (NULL); + } + + pohThis = sisfb_heap.oh_free.poh_next; + + while(pohThis != &sisfb_heap.oh_free) { + if (size <= pohThis->size) { + bAllocated = 1; + break; + } + pohThis = pohThis->poh_next; + } + + if(!bAllocated) { + DPRINTK("sisfb: Can't allocate %dk video memory\n", + (unsigned int) size / 1024); + return (NULL); + } + + if(size == pohThis->size) { + pohRoot = pohThis; + sisfb_delete_node(pohThis); + } else { + pohRoot = sisfb_poh_new_node(); + + if(pohRoot == NULL) { + return (NULL); + } + + pohRoot->offset = pohThis->offset; + pohRoot->size = size; + + pohThis->offset += size; + pohThis->size -= size; + } + + sisfb_heap.max_freesize -= size; + + pohThis = &sisfb_heap.oh_used; + sisfb_insert_node(pohThis, pohRoot); + + return (pohRoot); +} + +static void +sisfb_delete_node(SIS_OH *poh) +{ + SIS_OH *poh_prev; + SIS_OH *poh_next; + + poh_prev = poh->poh_prev; + poh_next = poh->poh_next; + + poh_prev->poh_next = poh_next; + poh_next->poh_prev = poh_prev; +} + +static void +sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh) +{ + SIS_OH *pohTemp; + + pohTemp = pohList->poh_next; + + pohList->poh_next = poh; + pohTemp->poh_prev = poh; + + poh->poh_prev = pohList; + poh->poh_next = pohTemp; +} + +static SIS_OH * +sisfb_poh_free(u32 base) +{ + SIS_OH *pohThis; + SIS_OH *poh_freed; + SIS_OH *poh_prev; + SIS_OH *poh_next; + u32 ulUpper; + u32 ulLower; + int foundNode = 0; + + poh_freed = sisfb_heap.oh_used.poh_next; + + while(poh_freed != &sisfb_heap.oh_used) { + if(poh_freed->offset == base) { + foundNode = 1; + break; + } + + poh_freed = poh_freed->poh_next; + } + + if(!foundNode) return(NULL); + + sisfb_heap.max_freesize += poh_freed->size; + + poh_prev = poh_next = NULL; + ulUpper = poh_freed->offset + poh_freed->size; + ulLower = poh_freed->offset; + + pohThis = sisfb_heap.oh_free.poh_next; + + while(pohThis != &sisfb_heap.oh_free) { + if(pohThis->offset == ulUpper) { + poh_next = pohThis; + } else if((pohThis->offset + pohThis->size) == ulLower) { + poh_prev = pohThis; + } + pohThis = pohThis->poh_next; + } + + sisfb_delete_node(poh_freed); + + if(poh_prev && poh_next) { + poh_prev->size += (poh_freed->size + poh_next->size); + sisfb_delete_node(poh_next); + sisfb_free_node(poh_freed); + sisfb_free_node(poh_next); + return(poh_prev); + } + + if(poh_prev) { + poh_prev->size += poh_freed->size; + sisfb_free_node(poh_freed); + return(poh_prev); + } + + if(poh_next) { + poh_next->size += poh_freed->size; + poh_next->offset = poh_freed->offset; + sisfb_free_node(poh_freed); + return(poh_next); + } + + sisfb_insert_node(&sisfb_heap.oh_free, poh_freed); + + return(poh_freed); +} + +static void +sisfb_free_node(SIS_OH *poh) +{ + if(poh == NULL) return; + + poh->poh_next = sisfb_heap.poh_freelist; + sisfb_heap.poh_freelist = poh; +} + +void +sis_malloc(struct sis_memreq *req) +{ + struct sis_video_info *ivideo = sisfb_heap.vinfo; + SIS_OH *poh = NULL; + + if((ivideo) && (!ivideo->havenoheap)) { + poh = sisfb_poh_allocate((u32)req->size); + } + + if(poh == NULL) { + req->offset = req->size = 0; + DPRINTK("sisfb: Video RAM allocation failed\n"); + } else { + req->offset = poh->offset; + req->size = poh->size; + DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n", + (poh->offset + ivideo->video_vbase)); + } +} + +/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */ + +void +sis_free(u32 base) +{ + struct sis_video_info *ivideo = sisfb_heap.vinfo; + SIS_OH *poh; + + if((!ivideo) || (ivideo->havenoheap)) return; + + poh = sisfb_poh_free((u32)base); + + if(poh == NULL) { + DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n", + (unsigned int) base); + } +} + +/* --------------------- SetMode routines ------------------------- */ + +static void +sisfb_pre_setmode(struct sis_video_info *ivideo) +{ + u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0; + int tvregnum = 0; + + ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2); + + inSISIDXREG(SISCR, 0x31, cr31); + cr31 &= ~0x60; + cr31 |= 0x04; + + cr33 = ivideo->rate_idx & 0x0F; + +#ifdef CONFIG_FB_SIS_315 + if(ivideo->sisvga_engine == SIS_315_VGA) { + if(ivideo->chip >= SIS_661) { + inSISIDXREG(SISCR, 0x38, cr38); + cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */ + } else { + tvregnum = 0x38; + inSISIDXREG(SISCR, tvregnum, cr38); + cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */ + } + } +#endif +#ifdef CONFIG_FB_SIS_300 + if(ivideo->sisvga_engine == SIS_300_VGA) { + tvregnum = 0x35; + inSISIDXREG(SISCR, tvregnum, cr38); + } +#endif + + SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE); + SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE); + + switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { + + case CRT2_TV: + cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */ + if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) { +#ifdef CONFIG_FB_SIS_315 + if(ivideo->chip >= SIS_661) { + cr38 |= 0x04; + if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20; + else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40; + else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60; + cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; + cr35 &= ~0x01; + ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL)); + } else if(ivideo->sisvga_engine == SIS_315_VGA) { + cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE); + cr38 |= 0x08; + if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10; + else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20; + else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30; + cr31 &= ~0x01; + ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL)); + } +#endif + } else if((ivideo->vbflags & TV_HIVISION) && (ivideo->vbflags & (VB_301|VB_301B|VB_302B))) { + if(ivideo->chip >= SIS_661) { + cr38 |= 0x04; + cr35 |= 0x60; + } else { + cr30 |= 0x80; + } + cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; + cr31 |= 0x01; + cr35 |= 0x01; + ivideo->currentvbflags |= TV_HIVISION; + } else if(ivideo->vbflags & TV_SCART) { + cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE); + cr31 |= 0x01; + cr35 |= 0x01; + ivideo->currentvbflags |= TV_SCART; + } else { + if(ivideo->vbflags & TV_SVIDEO) { + cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE); + ivideo->currentvbflags |= TV_SVIDEO; + } + if(ivideo->vbflags & TV_AVIDEO) { + cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE); + ivideo->currentvbflags |= TV_AVIDEO; + } + } + cr31 |= SIS_DRIVER_MODE; + + if(ivideo->vbflags & (TV_AVIDEO|TV_SVIDEO)) { + if(ivideo->vbflags & TV_PAL) { + cr31 |= 0x01; cr35 |= 0x01; + ivideo->currentvbflags |= TV_PAL; + if(ivideo->vbflags & TV_PALM) { + cr38 |= 0x40; cr35 |= 0x04; + ivideo->currentvbflags |= TV_PALM; + } else if(ivideo->vbflags & TV_PALN) { + cr38 |= 0x80; cr35 |= 0x08; + ivideo->currentvbflags |= TV_PALN; + } + } else { + cr31 &= ~0x01; cr35 &= ~0x01; + ivideo->currentvbflags |= TV_NTSC; + if(ivideo->vbflags & TV_NTSCJ) { + cr38 |= 0x40; cr35 |= 0x02; + ivideo->currentvbflags |= TV_NTSCJ; + } + } + } + break; + + case CRT2_LCD: + cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE); + cr31 |= SIS_DRIVER_MODE; + SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn); + SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn); + break; + + case CRT2_VGA: + cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE); + cr31 |= SIS_DRIVER_MODE; + if(ivideo->sisfb_nocrt2rate) { + cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4); + } else { + cr33 |= ((ivideo->rate_idx & 0x0F) << 4); + } + break; + + default: /* disable CRT2 */ + cr30 = 0x00; + cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE); + } + + outSISIDXREG(SISCR, 0x30, cr30); + outSISIDXREG(SISCR, 0x33, cr33); + + if(ivideo->chip >= SIS_661) { +#ifdef CONFIG_FB_SIS_315 + cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */ + setSISIDXREG(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */ + cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */ + setSISIDXREG(SISCR, 0x38, 0xf8, cr38); +#endif + } else if(ivideo->chip != SIS_300) { + outSISIDXREG(SISCR, tvregnum, cr38); + } + outSISIDXREG(SISCR, 0x31, cr31); + + if(ivideo->accel) sisfb_syncaccel(ivideo); + + ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem; +} + +/* Fix SR11 for 661 and later */ +#ifdef CONFIG_FB_SIS_315 +static void +sisfb_fixup_SR11(struct sis_video_info *ivideo) +{ + u8 tmpreg; + + if(ivideo->chip >= SIS_661) { + inSISIDXREG(SISSR,0x11,tmpreg); + if(tmpreg & 0x20) { + inSISIDXREG(SISSR,0x3e,tmpreg); + tmpreg = (tmpreg + 1) & 0xff; + outSISIDXREG(SISSR,0x3e,tmpreg); + inSISIDXREG(SISSR,0x11,tmpreg); + } + if(tmpreg & 0xf0) { + andSISIDXREG(SISSR,0x11,0x0f); + } + } +} +#endif + +static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val) +{ + if(val > 32) val = 32; + if(val < -32) val = -32; + ivideo->tvxpos = val; + + if(ivideo->sisfblocked) return; + if(!ivideo->modechanged) return; + + if(ivideo->currentvbflags & CRT2_TV) { + + if(ivideo->vbflags & VB_CHRONTEL) { + + int x = ivideo->tvx; + + switch(ivideo->chronteltype) { + case 1: + x += val; + if(x < 0) x = 0; + outSISIDXREG(SISSR,0x05,0x86); + SiS_SetCH700x(&ivideo->SiS_Pr, (((x & 0xff) << 8) | 0x0a)); + SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, (((x & 0x0100) << 1) | 0x08),0xFD); + break; + case 2: + /* Not supported by hardware */ + break; + } + + } else if(ivideo->vbflags & VB_SISBRIDGE) { + + u8 p2_1f,p2_20,p2_2b,p2_42,p2_43; + unsigned short temp; + + p2_1f = ivideo->p2_1f; + p2_20 = ivideo->p2_20; + p2_2b = ivideo->p2_2b; + p2_42 = ivideo->p2_42; + p2_43 = ivideo->p2_43; + + temp = p2_1f | ((p2_20 & 0xf0) << 4); + temp += (val * 2); + p2_1f = temp & 0xff; + p2_20 = (temp & 0xf00) >> 4; + p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f; + temp = p2_43 | ((p2_42 & 0xf0) << 4); + temp += (val * 2); + p2_43 = temp & 0xff; + p2_42 = (temp & 0xf00) >> 4; + outSISIDXREG(SISPART2,0x1f,p2_1f); + setSISIDXREG(SISPART2,0x20,0x0F,p2_20); + setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b); + setSISIDXREG(SISPART2,0x42,0x0F,p2_42); + outSISIDXREG(SISPART2,0x43,p2_43); + } + } +} + +static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val) +{ + if(val > 32) val = 32; + if(val < -32) val = -32; + ivideo->tvypos = val; + + if(ivideo->sisfblocked) return; + if(!ivideo->modechanged) return; + + if(ivideo->currentvbflags & CRT2_TV) { + + if(ivideo->vbflags & VB_CHRONTEL) { + + int y = ivideo->tvy; + + switch(ivideo->chronteltype) { + case 1: + y -= val; + if(y < 0) y = 0; + outSISIDXREG(SISSR,0x05,0x86); + SiS_SetCH700x(&ivideo->SiS_Pr, (((y & 0xff) << 8) | 0x0b)); + SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, ((y & 0x0100) | 0x08),0xFE); + break; + case 2: + /* Not supported by hardware */ + break; + } + + } else if(ivideo->vbflags & VB_SISBRIDGE) { + + char p2_01, p2_02; + val /= 2; + p2_01 = ivideo->p2_01; + p2_02 = ivideo->p2_02; + + p2_01 += val; + p2_02 += val; + while((p2_01 <= 0) || (p2_02 <= 0)) { + p2_01 += 2; + p2_02 += 2; + } + outSISIDXREG(SISPART2,0x01,p2_01); + outSISIDXREG(SISPART2,0x02,p2_02); + } + } +} + +static void +sisfb_post_setmode(struct sis_video_info *ivideo) +{ + BOOLEAN crt1isoff = FALSE; + BOOLEAN doit = TRUE; +#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) + u8 reg; +#endif +#ifdef CONFIG_FB_SIS_315 + u8 reg1; +#endif + + outSISIDXREG(SISSR,0x05,0x86); + +#ifdef CONFIG_FB_SIS_315 + sisfb_fixup_SR11(ivideo); +#endif + + /* Now we actually HAVE changed the display mode */ + ivideo->modechanged = 1; + + /* We can't switch off CRT1 if bridge is in slave mode */ + if(ivideo->vbflags & VB_VIDEOBRIDGE) { + if(sisfb_bridgeisslave(ivideo)) doit = FALSE; + } else ivideo->sisfb_crt1off = 0; + +#ifdef CONFIG_FB_SIS_300 + if(ivideo->sisvga_engine == SIS_300_VGA) { + if((ivideo->sisfb_crt1off) && (doit)) { + crt1isoff = TRUE; + reg = 0x00; + } else { + crt1isoff = FALSE; + reg = 0x80; + } + setSISIDXREG(SISCR, 0x17, 0x7f, reg); + } +#endif +#ifdef CONFIG_FB_SIS_315 + if(ivideo->sisvga_engine == SIS_315_VGA) { + if((ivideo->sisfb_crt1off) && (doit)) { + crt1isoff = TRUE; + reg = 0x40; + reg1 = 0xc0; + } else { + crt1isoff = FALSE; + reg = 0x00; + reg1 = 0x00; + + } + setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg); + setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1); + } +#endif + + if(crt1isoff) { + ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1; + ivideo->currentvbflags |= VB_SINGLE_MODE; + } else { + ivideo->currentvbflags |= VB_DISPTYPE_CRT1; + if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) { + ivideo->currentvbflags |= VB_MIRROR_MODE; + } else { + ivideo->currentvbflags |= VB_SINGLE_MODE; + } + } + + andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04); + + if(ivideo->currentvbflags & CRT2_TV) { + if(ivideo->vbflags & VB_SISBRIDGE) { + inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f); + inSISIDXREG(SISPART2,0x20,ivideo->p2_20); + inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b); + inSISIDXREG(SISPART2,0x42,ivideo->p2_42); + inSISIDXREG(SISPART2,0x43,ivideo->p2_43); + inSISIDXREG(SISPART2,0x01,ivideo->p2_01); + inSISIDXREG(SISPART2,0x02,ivideo->p2_02); + } else if(ivideo->vbflags & VB_CHRONTEL) { + if(ivideo->chronteltype == 1) { + ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a); + ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8); + ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b); + ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8); + } + } + } + + if(ivideo->tvxpos) { + sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos); + } + if(ivideo->tvypos) { + sisfb_set_TVyposoffset(ivideo, ivideo->tvypos); + } + + if((ivideo->currentvbflags & CRT2_TV) && (ivideo->vbflags & VB_301)) { /* Set filter for SiS301 */ + + unsigned char filter_tb = 0; + + switch (ivideo->video_width) { + case 320: + filter_tb = (ivideo->vbflags & TV_NTSC) ? 4 : 12; + break; + case 640: + filter_tb = (ivideo->vbflags & TV_NTSC) ? 5 : 13; + break; + case 720: + filter_tb = (ivideo->vbflags & TV_NTSC) ? 6 : 14; + break; + case 400: + case 800: + filter_tb = (ivideo->vbflags & TV_NTSC) ? 7 : 15; + break; + default: + ivideo->sisfb_filter = -1; + break; + } + + orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01); + + if(ivideo->vbflags & TV_NTSC) { + + andSISIDXREG(SISPART2, 0x3a, 0x1f); + + if (ivideo->vbflags & TV_SVIDEO) { + + andSISIDXREG(SISPART2, 0x30, 0xdf); + + } else if (ivideo->vbflags & TV_AVIDEO) { + + orSISIDXREG(SISPART2, 0x30, 0x20); + + switch (ivideo->video_width) { + case 640: + outSISIDXREG(SISPART2, 0x35, 0xEB); + outSISIDXREG(SISPART2, 0x36, 0x04); + outSISIDXREG(SISPART2, 0x37, 0x25); + outSISIDXREG(SISPART2, 0x38, 0x18); + break; + case 720: + outSISIDXREG(SISPART2, 0x35, 0xEE); + outSISIDXREG(SISPART2, 0x36, 0x0C); + outSISIDXREG(SISPART2, 0x37, 0x22); + outSISIDXREG(SISPART2, 0x38, 0x08); + break; + case 400: + case 800: + outSISIDXREG(SISPART2, 0x35, 0xEB); + outSISIDXREG(SISPART2, 0x36, 0x15); + outSISIDXREG(SISPART2, 0x37, 0x25); + outSISIDXREG(SISPART2, 0x38, 0xF6); + break; + } + } + + } else if(ivideo->vbflags & TV_PAL) { + + andSISIDXREG(SISPART2, 0x3A, 0x1F); + + if (ivideo->vbflags & TV_SVIDEO) { + + andSISIDXREG(SISPART2, 0x30, 0xDF); + + } else if (ivideo->vbflags & TV_AVIDEO) { + + orSISIDXREG(SISPART2, 0x30, 0x20); + + switch (ivideo->video_width) { + case 640: + outSISIDXREG(SISPART2, 0x35, 0xF1); + outSISIDXREG(SISPART2, 0x36, 0xF7); + outSISIDXREG(SISPART2, 0x37, 0x1F); + outSISIDXREG(SISPART2, 0x38, 0x32); + break; + case 720: + outSISIDXREG(SISPART2, 0x35, 0xF3); + outSISIDXREG(SISPART2, 0x36, 0x00); + outSISIDXREG(SISPART2, 0x37, 0x1D); + outSISIDXREG(SISPART2, 0x38, 0x20); + break; + case 400: + case 800: + outSISIDXREG(SISPART2, 0x35, 0xFC); + outSISIDXREG(SISPART2, 0x36, 0xFB); + outSISIDXREG(SISPART2, 0x37, 0x14); + outSISIDXREG(SISPART2, 0x38, 0x2A); + break; + } + } + } + + if((ivideo->sisfb_filter >= 0) && (ivideo->sisfb_filter <= 7)) { + outSISIDXREG(SISPART2,0x35,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][0])); + outSISIDXREG(SISPART2,0x36,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][1])); + outSISIDXREG(SISPART2,0x37,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][2])); + outSISIDXREG(SISPART2,0x38,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][3])); + } + + } +} + +#ifndef MODULE +SISINITSTATIC int __init sisfb_setup(char *options) +{ + char *this_opt; + + sisfb_setdefaultparms(); + + printk(KERN_DEBUG "sisfb: Options %s\n", options); + + if(!options || !(*options)) { + return 0; + } + + while((this_opt = strsep(&options, ",")) != NULL) { + + if(!(*this_opt)) continue; + + if(!strnicmp(this_opt, "off", 3)) { + sisfb_off = 1; + } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) { + /* Need to check crt2 type first for fstn/dstn */ + sisfb_search_crt2type(this_opt + 14); + } else if(!strnicmp(this_opt, "tvmode:",7)) { + sisfb_search_tvstd(this_opt + 7); + } else if(!strnicmp(this_opt, "tvstandard:",11)) { + sisfb_search_tvstd(this_opt + 7); + } else if(!strnicmp(this_opt, "mode:", 5)) { + sisfb_search_mode(this_opt + 5, FALSE); + } else if(!strnicmp(this_opt, "vesa:", 5)) { + sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), FALSE); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + } else if(!strnicmp(this_opt, "inverse", 7)) { + sisfb_inverse = 1; + /* fb_invert_cmaps(); */ + } else if(!strnicmp(this_opt, "font:", 5)) { + if(strlen(this_opt + 5) < 40) { + strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1); + sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0'; + } +#endif + } else if(!strnicmp(this_opt, "rate:", 5)) { + sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0); + } else if(!strnicmp(this_opt, "filter:", 7)) { + sisfb_filter = (int)simple_strtoul(this_opt + 7, NULL, 0); + } else if(!strnicmp(this_opt, "forcecrt1:", 10)) { + sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0); + } else if(!strnicmp(this_opt, "mem:",4)) { + sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0); + } else if(!strnicmp(this_opt, "pdc:", 4)) { + sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0); + } else if(!strnicmp(this_opt, "pdc1:", 5)) { + sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0); + } else if(!strnicmp(this_opt, "noaccel", 7)) { + sisfb_accel = 0; + } else if(!strnicmp(this_opt, "accel", 5)) { + sisfb_accel = -1; + } else if(!strnicmp(this_opt, "noypan", 6)) { + sisfb_ypan = 0; + } else if(!strnicmp(this_opt, "ypan", 4)) { + sisfb_ypan = -1; + } else if(!strnicmp(this_opt, "nomax", 5)) { + sisfb_max = 0; + } else if(!strnicmp(this_opt, "max", 3)) { + sisfb_max = -1; + } else if(!strnicmp(this_opt, "userom:", 7)) { + sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0); + } else if(!strnicmp(this_opt, "useoem:", 7)) { + sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); + } else if(!strnicmp(this_opt, "nocrt2rate", 10)) { + sisfb_nocrt2rate = 1; + } else if(!strnicmp(this_opt, "scalelcd:", 9)) { + unsigned long temp = 2; + temp = simple_strtoul(this_opt + 9, NULL, 0); + if((temp == 0) || (temp == 1)) { + sisfb_scalelcd = temp ^ 1; + } + } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) { + int temp = 0; + temp = (int)simple_strtol(this_opt + 13, NULL, 0); + if((temp >= -32) && (temp <= 32)) { + sisfb_tvxposoffset = temp; + } + } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) { + int temp = 0; + temp = (int)simple_strtol(this_opt + 13, NULL, 0); + if((temp >= -32) && (temp <= 32)) { + sisfb_tvyposoffset = temp; + } + } else if(!strnicmp(this_opt, "specialtiming:", 14)) { + sisfb_search_specialtiming(this_opt + 14); + } else if(!strnicmp(this_opt, "lvdshl:", 7)) { + int temp = 4; + temp = simple_strtoul(this_opt + 7, NULL, 0); + if((temp >= 0) && (temp <= 3)) { + sisfb_lvdshl = temp; + } + } else if(this_opt[0] >= '0' && this_opt[0] <= '9') { + sisfb_search_mode(this_opt, TRUE); +#if !defined(__i386__) && !defined(__x86_64__) + } else if(!strnicmp(this_opt, "resetcard", 9)) { + sisfb_resetcard = 1; + } else if(!strnicmp(this_opt, "videoram:", 9)) { + sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0); +#endif + } else { + printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt); + } + + } + + + + return 0; +} +#endif + +static UCHAR * __devinit sis_find_rom(struct pci_dev *pdev) +{ + struct sis_video_info *ivideo = pci_get_drvdata(pdev); + USHORT pciid; + int romptr; + UCHAR *myrombase; + u32 temp; + SIS_IOTYPE1 *rom_base, *rom; + + if(!(myrombase = vmalloc(65536))) return NULL; + +#if defined(__i386__) || defined(__x86_64__) + + for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) { + + rom_base = ioremap(temp, 0x10000); + if(!rom_base) continue; + + if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) { + iounmap(rom_base); + continue; + } + + romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8)); + if(romptr > (0x10000 - 8)) { + iounmap(rom_base); + continue; + } + + rom = rom_base + romptr; + + if((readb(rom) != 'P') || (readb(rom + 1) != 'C') || + (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) { + iounmap(rom_base); + continue; + } + + pciid = readb(rom + 4) | (readb(rom + 5) << 8); + if(pciid != 0x1039) { + iounmap(rom_base); + continue; + } + + pciid = readb(rom + 6) | (readb(rom + 7) << 8); + if(pciid == ivideo->chip_id) { + memcpy_fromio(myrombase, rom_base, 65536); + iounmap(rom_base); + return myrombase; + } + + iounmap(rom_base); + } + +#else + + pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &temp); + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, + (ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE); + + rom_base = ioremap(ivideo->video_base, 65536); + if(rom_base) { + if((readb(rom_base) == 0x55) && (readb(rom_base + 1) == 0xaa)) { + romptr = (u16)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8)); + if(romptr <= (0x10000 - 8)) { + rom = rom_base + romptr; + if((readb(rom) == 'P') && (readb(rom + 1) == 'C') && + (readb(rom + 2) == 'I') && (readb(rom + 3) == 'R')) { + pciid = readb(rom + 4) | (readb(rom + 5) << 8); + if(pciid == 0x1039) { + pciid = readb(rom + 6) | (readb(rom + 7) << 8); + if(pciid == ivideo->chip_id) { + memcpy_fromio(myrombase, rom_base, 65536); + iounmap(rom_base); + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp); + return myrombase; + } + } + } + } + } + iounmap(rom_base); + } + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp); + +#endif + + vfree(myrombase); + return NULL; +} + +#ifdef CONFIG_FB_SIS_300 +static int __devinit +sisfb_chkbuswidth300(struct pci_dev *pdev, SIS_IOTYPE1 *FBAddress) +{ + struct sis_video_info *ivideo = pci_get_drvdata(pdev); + int i, j; + USHORT temp; + UCHAR reg; + + andSISIDXREG(SISSR,0x15,0xFB); + orSISIDXREG(SISSR,0x15,0x04); + outSISIDXREG(SISSR,0x13,0x00); + outSISIDXREG(SISSR,0x14,0xBF); + + for(i=0; i<2; i++) { + temp = 0x1234; + for(j=0; j<4; j++) { + writew(temp, FBAddress); + if(readw(FBAddress) == temp) break; + orSISIDXREG(SISSR,0x3c,0x01); + inSISIDXREG(SISSR,0x05,reg); + inSISIDXREG(SISSR,0x05,reg); + andSISIDXREG(SISSR,0x3c,0xfe); + inSISIDXREG(SISSR,0x05,reg); + inSISIDXREG(SISSR,0x05,reg); + temp++; + } + } + + writel(0x01234567L, FBAddress); + writel(0x456789ABL, (FBAddress+4)); + writel(0x89ABCDEFL, (FBAddress+8)); + writel(0xCDEF0123L, (FBAddress+12)); + inSISIDXREG(SISSR,0x3b,reg); + if(reg & 0x01) { + if(readl((FBAddress+12)) == 0xCDEF0123L) return(4); /* Channel A 128bit */ + } + if(readl((FBAddress+4)) == 0x456789ABL) return(2); /* Channel B 64bit */ + return(1); /* 32bit */ +} + +static void __devinit +sisfb_setramsize300(struct pci_dev *pdev) +{ + struct sis_video_info *ivideo = pci_get_drvdata(pdev); + SIS_IOTYPE1 *FBAddr = ivideo->video_vbase; + SIS_IOTYPE1 *Addr; + USHORT sr13, sr14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0; + int PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount; + int RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank; + int PageCapacity, PhysicalAdrHigh, PhysicalAdrHalfPage, i, j, k; + const USHORT SiS_DRAMType[17][5] = { + {0x0C,0x0A,0x02,0x40,0x39}, + {0x0D,0x0A,0x01,0x40,0x48}, + {0x0C,0x09,0x02,0x20,0x35}, + {0x0D,0x09,0x01,0x20,0x44}, + {0x0C,0x08,0x02,0x10,0x31}, + {0x0D,0x08,0x01,0x10,0x40}, + {0x0C,0x0A,0x01,0x20,0x34}, + {0x0C,0x09,0x01,0x08,0x32}, + {0x0B,0x08,0x02,0x08,0x21}, + {0x0C,0x08,0x01,0x08,0x30}, + {0x0A,0x08,0x02,0x04,0x11}, + {0x0B,0x0A,0x01,0x10,0x28}, + {0x09,0x08,0x02,0x02,0x01}, + {0x0B,0x09,0x01,0x08,0x24}, + {0x0B,0x08,0x01,0x04,0x20}, + {0x0A,0x08,0x01,0x02,0x10}, + {0x09,0x08,0x01,0x01,0x00} + }; + + buswidth = sisfb_chkbuswidth300(pdev, FBAddr); + + MB2Bank = 16; + Done = 0; + for(i = 6; i >= 0; i--) { + if(Done) break; + PseudoRankCapacity = 1 << i; + for(j = 4; j >= 1; j--) { + if(Done) break; + PseudoTotalCapacity = PseudoRankCapacity * j; + PseudoAdrPinCount = 15 - j; + if(PseudoTotalCapacity <= 64) { + for(k = 0; k <= 16; k++) { + if(Done) break; + RankCapacity = buswidth * SiS_DRAMType[k][3]; + AdrPinCount = SiS_DRAMType[k][2] + SiS_DRAMType[k][0]; + if(RankCapacity == PseudoRankCapacity) + if(AdrPinCount <= PseudoAdrPinCount) { + if(j == 3) { /* Rank No */ + BankNumHigh = RankCapacity * MB2Bank * 3 - 1; + BankNumMid = RankCapacity * MB2Bank * 1 - 1; + } else { + BankNumHigh = RankCapacity * MB2Bank * j - 1; + BankNumMid = RankCapacity * MB2Bank * j / 2 - 1; + } + PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4; + PhysicalAdrHigh = BankNumHigh; + PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity; + PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh; + /* Write data */ + andSISIDXREG(SISSR,0x15,0xFB); /* Test */ + orSISIDXREG(SISSR,0x15,0x04); /* Test */ + TotalCapacity = SiS_DRAMType[k][3] * buswidth; + sr13 = SiS_DRAMType[k][4]; + if(buswidth == 4) sr14 = (TotalCapacity - 1) | 0x80; + if(buswidth == 2) sr14 = (TotalCapacity - 1) | 0x40; + if(buswidth == 1) sr14 = (TotalCapacity - 1) | 0x00; + outSISIDXREG(SISSR,0x13,sr13); + outSISIDXREG(SISSR,0x14,sr14); + Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh; + /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHigh; */ + writew(((USHORT)PhysicalAdrHigh), Addr); + Addr = FBAddr + BankNumMid * 64 * 1024 + PhysicalAdrHigh; + /* *((USHORT *)(Addr)) = (USHORT)BankNumMid; */ + writew(((USHORT)BankNumMid), Addr); + Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHalfPage; + /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHalfPage; */ + writew(((USHORT)PhysicalAdrHalfPage), Addr); + Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrOtherPage; + /* *((USHORT *)(Addr)) = PhysicalAdrOtherPage; */ + writew(((USHORT)PhysicalAdrOtherPage), Addr); + /* Read data */ + Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh; + data = readw(Addr); /* *((USHORT *)(Addr)); */ + if(data == PhysicalAdrHigh) Done = 1; + } /* if */ + } /* for k */ + } /* if */ + } /* for j */ + } /* for i */ +} + +static void __devinit sisfb_post_sis300(struct pci_dev *pdev) +{ + struct sis_video_info *ivideo = pci_get_drvdata(pdev); + u8 reg, v1, v2, v3, v4, v5, v6, v7, v8; + u16 index, rindex, memtype = 0; + + outSISIDXREG(SISSR,0x05,0x86); + + if(ivideo->sishw_ext.UseROM) { + if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80) { + memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52]; + } else { + inSISIDXREG(SISSR,0x3a,memtype); + } + memtype &= 0x07; + } + + if(ivideo->revision_id <= 0x13) { + v1 = 0x44; v2 = 0x42; v3 = 0x80; + v4 = 0x44; v5 = 0x42; v6 = 0x80; + } else { + v1 = 0x68; v2 = 0x43; v3 = 0x80; /* Assume 125Mhz MCLK */ + v4 = 0x68; v5 = 0x43; v6 = 0x80; /* Assume 125Mhz ECLK */ + if(ivideo->sishw_ext.UseROM) { + index = memtype * 5; + rindex = index + 0x54; + v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; + v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; + rindex = index + 0x7c; + v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; + v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; + v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; + } + } + outSISIDXREG(SISSR,0x28,v1); + outSISIDXREG(SISSR,0x29,v2); + outSISIDXREG(SISSR,0x2a,v3); + outSISIDXREG(SISSR,0x2e,v4); + outSISIDXREG(SISSR,0x2f,v5); + outSISIDXREG(SISSR,0x30,v6); + v1 = 0x10; + if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0xa4]; + outSISIDXREG(SISSR,0x07,v1); /* DAC speed */ + outSISIDXREG(SISSR,0x11,0x0f); /* DDC, power save */ + v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a; + v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00; + if(ivideo->sishw_ext.UseROM) { + memtype += 0xa5; + v1 = ivideo->sishw_ext.pjVirtualRomBase[memtype]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 8]; + v3 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 16]; + v4 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 24]; + v5 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 32]; + v6 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 40]; + v7 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 48]; + v8 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 56]; + } + if(ivideo->revision_id >= 0x80) v3 &= 0xfd; + outSISIDXREG(SISSR,0x15,v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */ + outSISIDXREG(SISSR,0x16,v2); + outSISIDXREG(SISSR,0x17,v3); + outSISIDXREG(SISSR,0x18,v4); + outSISIDXREG(SISSR,0x19,v5); + outSISIDXREG(SISSR,0x1a,v6); + outSISIDXREG(SISSR,0x1b,v7); + outSISIDXREG(SISSR,0x1c,v8); /* ---- */ + andSISIDXREG(SISSR,0x15,0xfb); + orSISIDXREG(SISSR,0x15,0x04); + if(ivideo->sishw_ext.UseROM) { + if(ivideo->sishw_ext.pjVirtualRomBase[0x53] & 0x02) { + orSISIDXREG(SISSR,0x19,0x20); + } + } + v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */ + if(ivideo->revision_id >= 0x80) v1 |= 0x01; + outSISIDXREG(SISSR,0x1f,v1); + outSISIDXREG(SISSR,0x20,0xa0); /* linear & relocated io */ + v1 = 0xf6; v2 = 0x0d; v3 = 0x00; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe8]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe9]; + v3 = ivideo->sishw_ext.pjVirtualRomBase[0xea]; + } + outSISIDXREG(SISSR,0x23,v1); + outSISIDXREG(SISSR,0x24,v2); + outSISIDXREG(SISSR,0x25,v3); + outSISIDXREG(SISSR,0x21,0x84); + outSISIDXREG(SISSR,0x22,0x00); + outSISIDXREG(SISCR,0x37,0x00); + orSISIDXREG(SISPART1,0x24,0x01); /* unlock crt2 */ + outSISIDXREG(SISPART1,0x00,0x00); + v1 = 0x40; v2 = 0x11; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0xec]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[0xeb]; + } + outSISIDXREG(SISPART1,0x02,v1); + if(ivideo->revision_id >= 0x80) v2 &= ~0x01; + inSISIDXREG(SISPART4,0x00,reg); + if((reg == 1) || (reg == 2)) { + outSISIDXREG(SISCR,0x37,0x02); + outSISIDXREG(SISPART2,0x00,0x1c); + v4 = 0x00; v5 = 0x00; v6 = 0x10; + if(ivideo->sishw_ext.UseROM) { + v4 = ivideo->sishw_ext.pjVirtualRomBase[0xf5]; + v5 = ivideo->sishw_ext.pjVirtualRomBase[0xf6]; + v6 = ivideo->sishw_ext.pjVirtualRomBase[0xf7]; + } + outSISIDXREG(SISPART4,0x0d,v4); + outSISIDXREG(SISPART4,0x0e,v5); + outSISIDXREG(SISPART4,0x10,v6); + outSISIDXREG(SISPART4,0x0f,0x3f); + inSISIDXREG(SISPART4,0x01,reg); + if(reg >= 0xb0) { + inSISIDXREG(SISPART4,0x23,reg); + reg &= 0x20; + reg <<= 1; + outSISIDXREG(SISPART4,0x23,reg); + } + } else { + v2 &= ~0x10; + } + outSISIDXREG(SISSR,0x32,v2); + andSISIDXREG(SISPART1,0x24,0xfe); /* Lock CRT2 */ + inSISIDXREG(SISSR,0x16,reg); + reg &= 0xc3; + outSISIDXREG(SISCR,0x35,reg); + outSISIDXREG(SISCR,0x83,0x00); +#if !defined(__i386__) && !defined(__x86_64__) + if(sisfb_videoram) { + outSISIDXREG(SISSR,0x13,0x28); /* ? */ + reg = ((sisfb_videoram >> 10) - 1) | 0x40; + outSISIDXREG(SISSR,0x14,reg); + } else { +#endif + /* Need to map max FB size for finding out about RAM size */ + ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000); + if(ivideo->video_vbase) { + sisfb_setramsize300(pdev); + iounmap(ivideo->video_vbase); + } else { + printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n"); + outSISIDXREG(SISSR,0x13,0x28); /* ? */ + outSISIDXREG(SISSR,0x14,0x47); /* 8MB, 64bit default */ + } +#if !defined(__i386__) && !defined(__x86_64__) + } +#endif + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe6]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe7]; + } else { + inSISIDXREG(SISSR,0x3a,reg); + if((reg & 0x30) == 0x30) { + v1 = 0x04; /* PCI */ + v2 = 0x92; + } else { + v1 = 0x14; /* AGP */ + v2 = 0xb2; + } + } + outSISIDXREG(SISSR,0x21,v1); + outSISIDXREG(SISSR,0x22,v2); +} +#endif + +#ifdef CONFIG_FB_SIS_315 +static void __devinit sisfb_post_sis315330(struct pci_dev *pdev) +{ +#ifdef YET_TO_BE_DONE + struct sis_video_info *ivideo = pci_get_drvdata(pdev); + u8 reg, v1, v2, v3, v4, v5, v6, v7, v8; + u16 index, rindex, memtype = 0; + u32 reg1_32, reg2_32, reg3_32; + int i; + + /* Unlock */ + /* outSISIDXREG(0x3c4,0x05,0x86); */ + outSISIDXREG(SISSR,0x05,0x86); + + /* Enable relocated i/o ports */ + /* setSISIDXREG(0x3c4,0x20,~0x10,0x20); */ + setSISIDXREG(SISSR,0x20,~0x10,0x20); + + /* Clear regs */ + for(i = 0; i < 0x22; i++) { + outSISIDXREG(SISSR,(0x06 + i),0x00); + } + v1 = 0x0d; + if( is 330) v1 = 0x0b; + for(i = 0; i < v1; i++) { + outSISIDXREG(SISSR,(0x31 + i),0x00); + } + for(i = 0; i < 0x10; i++) { + outSISIDXREG(SISCR,(0x30 + i),0x00); + } + + /* Reset clocks */ + reg = inSISREG(SISMISCR); + outSISIDXREG(SISSR,0x28,0x81); + outSISIDXREG(SISSR,0x2A,0x00); + outSISIDXREG(SISSR,0x29,0xE1); + outSISREG(SISMISCW,(reg | 0x0c)); + outSISIDXREG(SISSR,0x2B,0x81); + outSISIDXREG(SISSR,0x2D,0x00); + outSISIDXREG(SISSR,0x2C,0xE1); + outSISIDXREG(SISSR,0x2E,0x81); + outSISIDXREG(SISSR,0x30,0x00); + outSISIDXREG(SISSR,0x2F,0xE1); + SiS_DDC2Delay(....); + outSISREG(SISMISCW,reg); + + /* Get memory type */ + if(ivideo->sishw_ext.UseROM) { + if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80)) { + memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52]; + } else { + inSISIDXREG(SISSR,0x3a,memtype); + } + memtype &= 0x03; + if( is 330 ) { + if(memtype <= 1) memtype = 0; + else { + inSISIDXREG(SISCR,0x5F,reg); + reg &= 0x30; + switch(reg) { + case 0x00: memtype = 1; break; + case 0x10: memtype = 3; break; + case 0x20: memtype = 3; break; + default: memtype = 2; + } + } + } + } + + /* Set clocks */ + v1 = 0x3b; v2 = 0x22; v3 = 0x01; /* Assume 143Mhz MCLK */ + v4 = 0x5c; v5 = 0x23; v6 = 0x01; /* Assume 166Mhz ECLK */ + if(ivideo->sishw_ext.UseROM) { + index = memtype * 5; + rindex = index + 0x54; + v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; + v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; + rindex = index + 0x68; + v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; + v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; + v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; + } + outSISIDXREG(SISSR,0x28,v1); + outSISIDXREG(SISSR,0x29,v2); + outSISIDXREG(SISSR,0x2a,v3); + if( is 330 ) { + inSISIDXREG(SISSR,0x3a,reg); + reg &= 0x03; + if(reg >= 2) { + ... + } + } + outSISIDXREG(SISSR,0x2e,v4); + outSISIDXREG(SISSR,0x2f,v5); + outSISIDXREG(SISSR,0x30,v6); + + /* End of comp with 330 */ + + v1 = 0x18; + if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0x7c]; + outSISIDXREG(SISSR,0x07,v1); + outSISIDXREG(SISSR,0x11,0x0f); + + v1 = 0x00; v2 = 0x0f; v3 = 0xba; v4 = 0xa9; + v5 = 0xa0; v6 = 0x00; v7 = 0x30; + if(ivideo->sishw_ext.UseROM) { + index = memtype + 0x7d; + v1 = ivideo->sishw_ext.pjVirtualRomBase[index]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4]; + v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8]; + v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12]; + v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16]; + v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20]; + v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24]; + } + outSISIDXREG(SISSR,0x15,v1); /* Ram type (assuming 0, BIOS 0x7d step 4) */ + outSISIDXREG(SISSR,0x16,v2); + outSISIDXREG(SISSR,0x17,v3); + outSISIDXREG(SISSR,0x18,v4); + outSISIDXREG(SISSR,0x19,v5); + outSISIDXREG(SISSR,0x1a,v6); + outSISIDXREG(SISSR,0x1b,v7); + outSISIDXREG(SISSR,0x1c,v8); /* ---- */ + + v1 = 0x77; v2 = 0x77; v3 = 0x00; v4 = 0x5b; v5 = 0x00; + if(ivideo->sishw_ext.UseROM) { + index = memtype + 0xa2; + v1 = ivideo->sishw_ext.pjVirtualRomBase[index]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4]; + v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8]; + v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12]; + v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16]; + } + outSISIDXREG(SISCR,0x40,v1); + outSISIDXREG(SISCR,0x41,v2); + outSISIDXREG(SISCR,0x42,v3); + outSISIDXREG(SISCR,0x43,v4); + outSISIDXREG(SISCR,0x44,v5); + + if( is 330 ) { + + v1 = 0x; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA]; + } + outSISIDXREG(SISCR,0x59,v1); + + v1 = 0x; v2 = 0x; v3 = 0x; v4 = 0x; + v5 = 0x; v6 = 0x; v7 = 0x; v8 = 0x; + if(ivideo->sishw_ext.UseROM) { + index = memtype + 0xbe; + v1 = ivideo->sishw_ext.pjVirtualRomBase[index]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4]; + v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8]; + v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12]; + v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16]; + v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20]; + v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24]; + v8 = ivideo->sishw_ext.pjVirtualRomBase[index + 28]; + } + outSISIDXREG(SISCR,0x68,v1); + outSISIDXREG(SISCR,0x69,v2); + outSISIDXREG(SISCR,0x6a,v3); + outSISIDXREG(SISCR,0x6b,v4); + outSISIDXREG(SISCR,0x6c,v5); + outSISIDXREG(SISCR,0x6d,v6); + outSISIDXREG(SISCR,0x6e,v7); + outSISIDXREG(SISCR,0x6f,v8); + + v1 = 0x20; + inSISIDXREG(SISSR,0x3b,reg); + + if(!(reg & 0x04)) { + inSISIDXREG(SISCR,0x5F,reg); + reg &= 0x30; + if(reg) v1 = 0x23; + } + outSISIDXREG(SISCR,0x48,v1); + outSISIDXREG(SISCR,0x4c,0x20); + + xx= xxx(); + if(xx >= 1) { + v1 = 0x; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA]; + } + outSISIDXREG(SISCR,0x59,v1); + } + + + + } else { + + outSISIDXREG(SISCR,0x48,0x23); + + andSISIDXREG(SISSR,0x16,0x0f); + if(memtype <= 1) { + orSISIDXREG(SISSR,0x16,0x80); + } else { + v1 = 0x0f; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0x81 + memtype]; + } + if(!(v1 & 0x10)) v2 = 0xc0; + else v2 = 0xd0; + orSISIDXREG(SISSR,0x16,v2); + andSISIDXREG(SISSR,0x16,0x0f); + if(!(v1 & 0x10)) v2 = 0x80; + else v2 = 0xA0; + orSISIDXREG(SISSR,0x16,v2); + } + + if(memtype >= 2) { + const u8 sr3cseq1[] = { 0xc0,0xe0,0xf0,0xe0,0xf0,0xa0,0xb0,0xa0,0xb0,0x90,0xd0 }; + const u8 sr3cseq2[] = { 0xc0,0xa0,0xb0,0xa0,0xb0,0xe0,0xf0,0xa0,0xb0,0x90,0xd0 }; + for(i = 0; i < 11; i++) { + outSISIDXREG(SISSR,0x3c,sr3cseq1[i]); + } + outSISIDXREG(SISSR,0x3d,0x00); + outSISIDXREG(SISSR,0x3d,0x04); + SiS_DDC2Delay(0x200); + v1 = inSISIDXREG(SISCR,0xEC); + v2 = inSISIDXREG(SISCR,0xED); + reg1_32 = (v2 << 8) | v1; + outSISIDXREG(SISSR,0x3D,0x00); + for(i = 0; i < 11; i++) { + outSISIDXREG(SISSR,0x3c,sr3cseq2[i]); + } + outSISIDXREG(SISSR,0x3d,0x00); + outSISIDXREG(SISSR,0x3d,0x04); + SiS_DDC2Delay(0x200); + v1 = inSISIDXREG(SISCR,0xEC); + v2 = inSISIDXREG(SISCR,0xED); + reg2_32 = (v2 << 8) | v1; + outSISIDXREG(SISSR,0x3D,0x00); + reg3_32 = reg2_32 << 1; + reg2_32 >>= 1; + reg3_32 += reg2_32; + v1 = 0x40; + if(reg3_32 > reg1_32) v1 = 0x10; + outSISIDXREG(SISCR,0x59,v1); + } + + } + + v1 = 0x00; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0x99]; + } + outSISIDXREG(SISSR,0x1f,v1); + + outSISIDXREG(SISSR,0x20,0x20); + + v1 = 0xf6; v2 = 0x0d; v3 = 0x33; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9c]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9d]; + v3 = ivideo->sishw_ext.pjVirtualRomBase[0x9e]; + } + outSISIDXREG(SISSR,0x23,v1); + outSISIDXREG(SISSR,0x24,v2); + outSISIDXREG(SISSR,0x25,v3); + + outSISIDXREG(SISSR,0x21,0x84); + outSISIDXREG(SISSR,0x22,0x00); + outSISIDXREG(SISSR,0x27,0x1f); + + v1 = 0x00; v2 = 0x00; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9F]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[0xA1]; + } + outSISIDXREG(SISSR,0x31,v1); + outSISIDXREG(SISSR,0x33,v2); + + v1 = 0x11; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0xA0]; + } + v2 = inSISIDXREG(SISPART4,0x00); + if((v2 != 1) && (v2 != 2)) v1 &= 0xef; + outSISIDXREG(SISSR,0x32,v1); + + /* AGP */ + pci_read_config_long(pdev, 0x50, ®1_32); + reg1_32 >>= 20; + reg1_32 &= 0x0f; + if(reg1_32 == 1) { + v1 = 0xAA; v2 = 0x33; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF7]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9E]; + } + } else { + v1 = 0x88; v2 = 0x03; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF8]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[0xF6]; + } + } + outSISIDXREG(SISCR,0x49,v1); + outSISIDXREG(SISSR,0x25,v2); + + v1 = inSISIDXREG(SISPART4,0x00); + if((v1 == 1) || (v1 == 2)) { + orSISIDXREG(SISPART1,0x2F,0x01); /* Unlock CRT2 */ + outSISIDXREG(SISPART1,0x00,0x00); + v1 = 0x00; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb6]; + } + outSISIDXREG(SISPART1,0x02,v1); + outSISIDXREG(SISPART1,0x2E,0x08); + outSISIDXREG(SISPART2,0x00,0x1c); + v1 = 0x40; v2 = 0x00; v3 = 0x80; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb7]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[0xb8]; + v3 = ivideo->sishw_ext.pjVirtualRomBase[0xbb]; + } + outSISIDXREG(SISPART4,0x0d,v1); + outSISIDXREG(SISPART4,0x0e,v2); + outSISIDXREG(SISPART4,0x10,v3); + outSISIDXREG(SISPART4,0x0F,0x3F); + + inSISIDXREG(SISPART4,0x01,reg); + if(reg >= 0xb0) { + inSISIDXREG(SISPART4,0x23,reg); + reg &= 0x20; + reg <<= 1; + outSISIDXREG(SISPART4,0x23,reg); + } + } + outSISIDXREG(SISCR,0x37,0x02); /* Why? */ + + outSISIDXREG(SISCR,0x83,0x00); + outSISIDXREG(SISCR,0x90,0x00); + andSISIDXREG(SISSR,0x5B,0xDF); + outSISIDXREG(SISVID,0x00,0x86); + outSISIDXREG(SISVID,0x32,0x00); + outSISIDXREG(SISVID,0x30,0x00); + outSISIDXREG(SISVID,0x32,0x01); + outSISIDXREG(SISVID,0x30,0x00); + orSISIDXREG(SISCR,0x63,0x80); + /* End of Init1 */ + + /* Set Mode 0x2e */ + + /* Ramsize */ + orSISIDXREG(SISSR,0x16,0x0f); + orSISIDXREG(SISSR,0x18,0xA9); + orSISIDXREG(SISSR,0x19,0xA0); + orSISIDXREG(SISSR,0x1B,0x30); + andSISIDXREG(SISSR,0x17,0xF8); + orSISIDXREG(SISSR,0x19,0x03); + andSIDIDXREG(SISSR,0x13,0x00); + + /* Need to map max FB size for finding out about RAM size */ + ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000); + if(ivideo->video_vbase) { + /* Find out about bus width */ + if(memtype <= 1) { + outSISIDXREG(SISSR,0x14,0x02); + andSISIDXREG(SISSR,0x16,0x0F); + orSISIDXREG(SISSR,0x16,0x80); + + ... + + } else { + + ... + + } + + /* Find out about size */ + + + iounmap(ivideo->video_vbase); + } else { + printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n"); + outSISIDXREG(SISSR,0x14,0x??); /* 8MB, 64bit default */ + } + + /* AGP (Missing: Checks for VIA and AMD hosts) */ + v1 = 0xA5; v2 = 0xFB; + if(ivideo->sishw_ext.UseROM) { + v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9A]; + v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9B]; + } + outSISIDXREG(SISSR,0x21,v1); + outSISIDXREG(SISSR,0x22,v2); + +#endif + return; +} +#endif + + +int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data]; + struct sis_video_info *ivideo = NULL; + struct fb_info *sis_fb_info = NULL; + u16 reg16; + u8 reg; + int sisvga_enabled = 0, i; + + if(sisfb_off) return -ENXIO; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3)) + sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev); + if(!sis_fb_info) return -ENOMEM; +#else + sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL); + if(!sis_fb_info) return -ENOMEM; + memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo)); + sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info)); +#endif + + ivideo = (struct sis_video_info *)sis_fb_info->par; + ivideo->memyselfandi = sis_fb_info; + + if(card_list == NULL) { + ivideo->cardnumber = 0; + } else { + struct sis_video_info *countvideo = card_list; + ivideo->cardnumber = 1; + while((countvideo = countvideo->next) != NULL) ivideo->cardnumber++; + } + + strncpy(ivideo->myid, chipinfo->chip_name, 30); + + ivideo->warncount = 0; + ivideo->chip_id = pdev->device; + pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id); + ivideo->sishw_ext.jChipRevision = ivideo->revision_id; + pci_read_config_word(pdev, PCI_COMMAND, ®16); + sisvga_enabled = reg16 & 0x01; + ivideo->pcibus = pdev->bus->number; + ivideo->pcislot = PCI_SLOT(pdev->devfn); + ivideo->pcifunc = PCI_FUNC(pdev->devfn); + ivideo->subsysvendor = pdev->subsystem_vendor; + ivideo->subsysdevice = pdev->subsystem_device; + +#ifndef MODULE + if(sisfb_mode_idx == -1) { + sisfb_get_vga_mode_from_kernel(); + } +#endif + + ivideo->chip = chipinfo->chip; + ivideo->sisvga_engine = chipinfo->vgaengine; + ivideo->hwcursor_size = chipinfo->hwcursor_size; + ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable; + ivideo->mni = chipinfo->mni; + + ivideo->detectedpdc = 0xff; + ivideo->detectedpdca = 0xff; + ivideo->detectedlcda = 0xff; + + ivideo->sisfb_thismonitor.datavalid = FALSE; + + ivideo->sisfb_parm_mem = sisfb_parm_mem; + ivideo->sisfb_accel = sisfb_accel; + ivideo->sisfb_ypan = sisfb_ypan; + ivideo->sisfb_max = sisfb_max; + ivideo->sisfb_userom = sisfb_userom; + ivideo->sisfb_useoem = sisfb_useoem; + ivideo->sisfb_mode_idx = sisfb_mode_idx; + ivideo->sisfb_parm_rate = sisfb_parm_rate; + ivideo->sisfb_crt1off = sisfb_crt1off; + ivideo->sisfb_forcecrt1 = sisfb_forcecrt1; + ivideo->sisfb_crt2type = sisfb_crt2type; + ivideo->sisfb_crt2flags = sisfb_crt2flags; + /* pdc(a), scalelcd, special timing, lvdshl handled below */ + ivideo->sisfb_dstn = sisfb_dstn; + ivideo->sisfb_fstn = sisfb_fstn; + ivideo->sisfb_tvplug = sisfb_tvplug; + ivideo->sisfb_tvstd = sisfb_tvstd; + ivideo->tvxpos = sisfb_tvxposoffset; + ivideo->tvypos = sisfb_tvyposoffset; + ivideo->sisfb_filter = sisfb_filter; + ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) + ivideo->sisfb_inverse = sisfb_inverse; +#endif + + ivideo->refresh_rate = 0; + if(ivideo->sisfb_parm_rate != -1) { + ivideo->refresh_rate = ivideo->sisfb_parm_rate; + } + + ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd; + ivideo->SiS_Pr.CenterScreen = -1; + ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming; + ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl; + + ivideo->SiS_Pr.SiS_Backup70xx = 0xff; + ivideo->SiS_Pr.SiS_CHOverScan = -1; + ivideo->SiS_Pr.SiS_ChSW = FALSE; + ivideo->SiS_Pr.SiS_UseLCDA = FALSE; + ivideo->SiS_Pr.HaveEMI = FALSE; + ivideo->SiS_Pr.HaveEMILCD = FALSE; + ivideo->SiS_Pr.OverruleEMI = FALSE; + ivideo->SiS_Pr.SiS_SensibleSR11 = FALSE; + ivideo->SiS_Pr.SiS_MyCR63 = 0x63; + ivideo->SiS_Pr.PDC = -1; + ivideo->SiS_Pr.PDCA = -1; +#ifdef CONFIG_FB_SIS_315 + if(ivideo->chip >= SIS_330) { + ivideo->SiS_Pr.SiS_MyCR63 = 0x53; + if(ivideo->chip >= SIS_661) { + ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE; + } + } +#endif + + memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var)); + + pci_set_drvdata(pdev, ivideo); + + /* Patch special cases */ + if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) { + switch(ivideo->nbridge->device) { +#ifdef CONFIG_FB_SIS_300 + case PCI_DEVICE_ID_SI_730: + ivideo->chip = SIS_730; + strcpy(ivideo->myid, "SiS 730"); + break; +#endif +#ifdef CONFIG_FB_SIS_315 + case PCI_DEVICE_ID_SI_651: + /* ivideo->chip is ok */ + strcpy(ivideo->myid, "SiS 651"); + break; + case PCI_DEVICE_ID_SI_740: + ivideo->chip = SIS_740; + strcpy(ivideo->myid, "SiS 740"); + break; + case PCI_DEVICE_ID_SI_661: + ivideo->chip = SIS_661; + strcpy(ivideo->myid, "SiS 661"); + break; + case PCI_DEVICE_ID_SI_741: + ivideo->chip = SIS_741; + strcpy(ivideo->myid, "SiS 741"); + break; + case PCI_DEVICE_ID_SI_760: + ivideo->chip = SIS_760; + strcpy(ivideo->myid, "SiS 760"); + break; +#endif + } + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + strcpy(sis_fb_info->modename, ivideo->myid); +#endif + + ivideo->sishw_ext.jChipType = ivideo->chip; + +#ifdef CONFIG_FB_SIS_315 + if((ivideo->sishw_ext.jChipType == SIS_315PRO) || + (ivideo->sishw_ext.jChipType == SIS_315)) { + ivideo->sishw_ext.jChipType = SIS_315H; + } +#endif + + ivideo->video_base = pci_resource_start(pdev, 0); + ivideo->mmio_base = pci_resource_start(pdev, 1); + ivideo->mmio_size = pci_resource_len(pdev, 1); + ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30; + ivideo->sishw_ext.ulIOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO; + + if(!sisvga_enabled) { + if(pci_enable_device(pdev)) { + pci_set_drvdata(pdev, NULL); + kfree(sis_fb_info); + return -EIO; + } + } + + SiSRegInit(&ivideo->SiS_Pr, ivideo->sishw_ext.ulIOAddress); + +#ifdef CONFIG_FB_SIS_300 + /* Find PCI systems for Chrontel/GPIO communication setup */ + if(ivideo->chip == SIS_630) { + i=0; + do { + if(mychswtable[i].subsysVendor == ivideo->subsysvendor && + mychswtable[i].subsysCard == ivideo->subsysdevice) { + ivideo->SiS_Pr.SiS_ChSW = TRUE; + printk(KERN_DEBUG "sisfb: Identified [%s %s] requiring Chrontel/GPIO setup\n", + mychswtable[i].vendorName, mychswtable[i].cardName); + break; + } + i++; + } while(mychswtable[i].subsysVendor != 0); + } +#endif + + outSISIDXREG(SISSR, 0x05, 0x86); + + if( (!sisvga_enabled) +#if !defined(__i386__) && !defined(__x86_64__) + || (sisfb_resetcard) +#endif + ) { + for(i = 0x30; i <= 0x3f; i++) { + outSISIDXREG(SISCR,i,0x00); + } + } + + /* Find out about current video mode */ + ivideo->modeprechange = 0x03; + inSISIDXREG(SISCR,0x34,reg); + if(reg & 0x7f) { + ivideo->modeprechange = reg & 0x7f; + } else if(sisvga_enabled) { +#if defined(__i386__) || defined(__x86_64__) + unsigned char SIS_IOTYPE2 *tt = ioremap(0, 0x1000); + if(tt) { + ivideo->modeprechange = readb(tt + 0x449); + iounmap(tt); + } +#endif + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#ifdef MODULE + if((reg & 0x80) && (reg != 0xff)) { + if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF) { + printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n"); + pci_set_drvdata(pdev, NULL); + kfree(sis_fb_info); + return -EBUSY; + } + } +#endif +#endif + + ivideo->sishw_ext.bIntegratedMMEnabled = TRUE; +#ifdef CONFIG_FB_SIS_300 + if(ivideo->sisvga_engine == SIS_300_VGA) { + if(ivideo->chip != SIS_300) { + inSISIDXREG(SISSR, 0x1a, reg); + if(!(reg & 0x10)) { + ivideo->sishw_ext.bIntegratedMMEnabled = FALSE; + } + } + } +#endif + + ivideo->bios_abase = NULL; + if(ivideo->sisfb_userom) { + ivideo->sishw_ext.pjVirtualRomBase = sis_find_rom(pdev); + ivideo->bios_abase = ivideo->sishw_ext.pjVirtualRomBase; + if(ivideo->sishw_ext.pjVirtualRomBase) { + printk(KERN_INFO "sisfb: Video ROM found and copied\n"); + ivideo->sishw_ext.UseROM = TRUE; + } else { + ivideo->sishw_ext.UseROM = FALSE; + printk(KERN_INFO "sisfb: Video ROM not found\n"); + } + } else { + ivideo->sishw_ext.pjVirtualRomBase = NULL; + ivideo->sishw_ext.UseROM = FALSE; + printk(KERN_INFO "sisfb: Video ROM usage disabled\n"); + } + + /* Find systems for special custom timing */ + if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) { + int j; + unsigned char *biosver = NULL; + unsigned char *biosdate = NULL; + BOOLEAN footprint; + u32 chksum = 0; + + if(ivideo->sishw_ext.UseROM) { + biosver = ivideo->sishw_ext.pjVirtualRomBase + 0x06; + biosdate = ivideo->sishw_ext.pjVirtualRomBase + 0x2c; + for(i=0; i<32768; i++) chksum += ivideo->sishw_ext.pjVirtualRomBase[i]; + } + + i=0; + do { + if( (mycustomttable[i].chipID == ivideo->chip) && + ((!strlen(mycustomttable[i].biosversion)) || + (ivideo->sishw_ext.UseROM && + (!strncmp(mycustomttable[i].biosversion, biosver, strlen(mycustomttable[i].biosversion))))) && + ((!strlen(mycustomttable[i].biosdate)) || + (ivideo->sishw_ext.UseROM && + (!strncmp(mycustomttable[i].biosdate, biosdate, strlen(mycustomttable[i].biosdate))))) && + ((!mycustomttable[i].bioschksum) || + (ivideo->sishw_ext.UseROM && + (mycustomttable[i].bioschksum == chksum))) && + (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) && + (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) { + footprint = TRUE; + for(j = 0; j < 5; j++) { + if(mycustomttable[i].biosFootprintAddr[j]) { + if(ivideo->sishw_ext.UseROM) { + if(ivideo->sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] != + mycustomttable[i].biosFootprintData[j]) { + footprint = FALSE; + } + } else footprint = FALSE; + } + } + if(footprint) { + ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID; + printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n", + mycustomttable[i].vendorName, + mycustomttable[i].cardName); + printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n", + mycustomttable[i].optionName); + break; + } + } + i++; + } while(mycustomttable[i].chipID); + } + +#ifdef CONFIG_FB_SIS_300 + if(ivideo->sisvga_engine == SIS_300_VGA) { + if( (!sisvga_enabled) +#if !defined(__i386__) && !defined(__x86_64__) + || (sisfb_resetcard) +#endif + ) { + if(ivideo->chip == SIS_300) { + sisfb_post_sis300(pdev); + } + } + } +#endif + +#ifdef CONFIG_FB_SIS_315 + if(ivideo->sisvga_engine == SIS_315_VGA) { + if( (!sisvga_enabled) +#if !defined(__i386__) && !defined(__x86_64__) + || (sisfb_resetcard) +#endif + ) { + if((ivideo->chip == SIS_315H) || + (ivideo->chip == SIS_315) || + (ivideo->chip == SIS_315PRO) || + (ivideo->chip == SIS_330)) { + sisfb_post_sis315330(pdev); + } + } + } +#endif + + if(sisfb_get_dram_size(ivideo)) { + printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n"); + if(ivideo->bios_abase) vfree(ivideo->bios_abase); + pci_set_drvdata(pdev, NULL); + kfree(sis_fb_info); + return -ENODEV; + } + + if((ivideo->sisfb_mode_idx < 0) || + ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { + /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ + orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE)); + /* Enable 2D accelerator engine */ + orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D); + } + + if(sisfb_pdc != 0xff) { + if(ivideo->sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c; + else sisfb_pdc &= 0x1f; + ivideo->SiS_Pr.PDC = sisfb_pdc; + } +#ifdef CONFIG_FB_SIS_315 + if(ivideo->sisvga_engine == SIS_315_VGA) { + if(sisfb_pdca != 0xff) ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f; + } +#endif + + if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) { + printk(KERN_ERR "sisfb: Fatal error: Unable to reserve frame buffer memory\n"); + printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n"); + if(ivideo->bios_abase) vfree(ivideo->bios_abase); + pci_set_drvdata(pdev, NULL); + kfree(sis_fb_info); + return -ENODEV; + } + + if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) { + printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n"); + release_mem_region(ivideo->video_base, ivideo->video_size); + if(ivideo->bios_abase) vfree(ivideo->bios_abase); + pci_set_drvdata(pdev, NULL); + kfree(sis_fb_info); + return -ENODEV; + } + + ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size); + ivideo->sishw_ext.pjVideoMemoryAddress = ivideo->video_vbase; + if(!ivideo->video_vbase) { + printk(KERN_ERR "sisfb: Fatal error: Unable to map frame buffer memory\n"); + release_mem_region(ivideo->video_base, ivideo->video_size); + release_mem_region(ivideo->mmio_base, ivideo->mmio_size); + if(ivideo->bios_abase) vfree(ivideo->bios_abase); + pci_set_drvdata(pdev, NULL); + kfree(sis_fb_info); + return -ENODEV; + } + + ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size); + if(!ivideo->mmio_vbase) { + printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n"); + iounmap(ivideo->video_vbase); + release_mem_region(ivideo->video_base, ivideo->video_size); + release_mem_region(ivideo->mmio_base, ivideo->mmio_size); + if(ivideo->bios_abase) vfree(ivideo->bios_abase); + pci_set_drvdata(pdev, NULL); + kfree(sis_fb_info); + return -ENODEV; + } + + printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%lx, size %ldk\n", + ivideo->video_base, (ULONG)ivideo->video_vbase, ivideo->video_size / 1024); + + printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n", + ivideo->mmio_base, (ULONG)ivideo->mmio_vbase, ivideo->mmio_size / 1024); + + if((ivideo->havenoheap = sisfb_heap_init(ivideo))) { + printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n"); + } + + /* Used for clearing the screen only, therefore respect our mem limit */ + ivideo->sishw_ext.ulVideoMemorySize = ivideo->sisfb_mem; + + ivideo->mtrr = 0; + + ivideo->vbflags = 0; + ivideo->lcddefmodeidx = DEFAULT_LCDMODE; + ivideo->tvdefmodeidx = DEFAULT_TVMODE; + ivideo->defmodeidx = DEFAULT_MODE; + + ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr, &ivideo->sishw_ext); + + if((ivideo->sisfb_mode_idx < 0) || + ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { + + sisfb_sense_crt1(ivideo); + + sisfb_get_VB_type(ivideo); + + if(ivideo->vbflags & VB_VIDEOBRIDGE) { + sisfb_detect_VB_connect(ivideo); + } + + ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD); + + if(ivideo->vbflags & VB_VIDEOBRIDGE) { + if(ivideo->sisfb_crt2type != -1) { + if((ivideo->sisfb_crt2type == CRT2_LCD) && (ivideo->vbflags & CRT2_LCD)) { + ivideo->currentvbflags |= CRT2_LCD; + } else if(ivideo->sisfb_crt2type != CRT2_LCD) { + ivideo->currentvbflags |= ivideo->sisfb_crt2type; + } + } else { + /* Chrontel 700x TV detection often unreliable, therefore use a + * different default order on such machines + */ + if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags & VB_CHRONTEL)) { + if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD; + else if(ivideo->vbflags & CRT2_TV) ivideo->currentvbflags |= CRT2_TV; + else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA; + } else { + if(ivideo->vbflags & CRT2_TV) ivideo->currentvbflags |= CRT2_TV; + else if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD; + else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA; + } + } + } + + if(ivideo->vbflags & CRT2_LCD) { + inSISIDXREG(SISCR, 0x36, reg); + reg &= 0x0f; + if(ivideo->sisvga_engine == SIS_300_VGA) { + ivideo->CRT2LCDType = sis300paneltype[reg]; + } else if(ivideo->chip >= SIS_661) { + ivideo->CRT2LCDType = sis661paneltype[reg]; + } else { + ivideo->CRT2LCDType = sis310paneltype[reg]; + if((ivideo->chip == SIS_550) && (sisfb_fstn)) { + if((ivideo->CRT2LCDType != LCD_640x480_2) && + (ivideo->CRT2LCDType != LCD_640x480_3)) { + ivideo->CRT2LCDType = LCD_320x480; + } + } + } + if(ivideo->CRT2LCDType == LCD_UNKNOWN) { + /* For broken BIOSes: Assume 1024x768, RGB18 */ + ivideo->CRT2LCDType = LCD_1024x768; + setSISIDXREG(SISCR,0x36,0xf0,0x02); + setSISIDXREG(SISCR,0x37,0xee,0x01); + printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg); + } + for(i = 0; i < SIS_LCD_NUMBER; i++) { + if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) { + ivideo->lcdxres = sis_lcd_data[i].xres; + ivideo->lcdyres = sis_lcd_data[i].yres; + ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx; + break; + } + } + if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) { + ivideo->lcdxres = 1360; ivideo->lcdyres = 1024; ivideo->lcddefmodeidx = 99; + } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) { + ivideo->lcdxres = 848; ivideo->lcdyres = 480; ivideo->lcddefmodeidx = 47; + } + printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n", + ivideo->lcdxres, ivideo->lcdyres); + } + +#ifdef CONFIG_FB_SIS_300 + /* Save the current PanelDelayCompensation if the LCD is currently used */ + if(ivideo->sisvga_engine == SIS_300_VGA) { + if(ivideo->vbflags & (VB_LVDS | VB_30xBDH)) { + int tmp; + inSISIDXREG(SISCR,0x30,tmp); + if(tmp & 0x20) { + /* Currently on LCD? If yes, read current pdc */ + inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc); + ivideo->detectedpdc &= 0x3c; + if(ivideo->SiS_Pr.PDC == -1) { + /* Let option override detection */ + ivideo->SiS_Pr.PDC = ivideo->detectedpdc; + } + printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n", + ivideo->detectedpdc); + } + if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) { + printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n", + ivideo->SiS_Pr.PDC); + } + } + } +#endif + +#ifdef CONFIG_FB_SIS_315 + if(ivideo->sisvga_engine == SIS_315_VGA) { + + /* Try to find about LCDA */ + if(ivideo->vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) { + int tmp; + inSISIDXREG(SISPART1,0x13,tmp); + if(tmp & 0x04) { + ivideo->SiS_Pr.SiS_UseLCDA = TRUE; + ivideo->detectedlcda = 0x03; + } + } + + /* Save PDC */ + if(ivideo->vbflags & (VB_301LV | VB_302LV | VB_302ELV)) { + int tmp; + inSISIDXREG(SISCR,0x30,tmp); + if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) { + /* Currently on LCD? If yes, read current pdc */ + u8 pdc; + inSISIDXREG(SISPART1,0x2D,pdc); + ivideo->detectedpdc = (pdc & 0x0f) << 1; + ivideo->detectedpdca = (pdc & 0xf0) >> 3; + inSISIDXREG(SISPART1,0x35,pdc); + ivideo->detectedpdc |= ((pdc >> 7) & 0x01); + inSISIDXREG(SISPART1,0x20,pdc); + ivideo->detectedpdca |= ((pdc >> 6) & 0x01); + if(ivideo->newrom) { + /* New ROM invalidates other PDC resp. */ + if(ivideo->detectedlcda != 0xff) { + ivideo->detectedpdc = 0xff; + } else { + ivideo->detectedpdca = 0xff; + } + } + if(ivideo->SiS_Pr.PDC == -1) { + if(ivideo->detectedpdc != 0xff) { + ivideo->SiS_Pr.PDC = ivideo->detectedpdc; + } + } + if(ivideo->SiS_Pr.PDCA == -1) { + if(ivideo->detectedpdca != 0xff) { + ivideo->SiS_Pr.PDCA = ivideo->detectedpdca; + } + } + if(ivideo->detectedpdc != 0xff) { + printk(KERN_INFO + "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n", + ivideo->detectedpdc); + } + if(ivideo->detectedpdca != 0xff) { + printk(KERN_INFO + "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n", + ivideo->detectedpdca); + } + } + + /* Save EMI */ + if(ivideo->vbflags & (VB_302LV | VB_302ELV)) { + inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30); + inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31); + inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32); + inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33); + ivideo->SiS_Pr.HaveEMI = TRUE; + if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) { + ivideo->SiS_Pr.HaveEMILCD = TRUE; + } + } + } + + /* Let user override detected PDCs (all bridges) */ + if(ivideo->vbflags & (VB_301B | VB_301C | VB_301LV | VB_302LV | VB_302ELV)) { + if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) { + printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n", + ivideo->SiS_Pr.PDC); + } + if((ivideo->SiS_Pr.PDCA != -1) && (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) { + printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n", + ivideo->SiS_Pr.PDCA); + } + } + + } +#endif + + if(!ivideo->sisfb_crt1off) { + sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0); + } else { + if((ivideo->vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) && + (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) { + sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1); + } + } + + if(ivideo->sisfb_mode_idx >= 0) { + int bu = ivideo->sisfb_mode_idx; + ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo, + ivideo->sisfb_mode_idx, ivideo->currentvbflags); + if(bu != ivideo->sisfb_mode_idx) { + printk(KERN_ERR "Mode %dx%dx%d failed validation\n", + sisbios_mode[bu].xres, + sisbios_mode[bu].yres, + sisbios_mode[bu].bpp); + } + } + + if(ivideo->sisfb_mode_idx < 0) { + switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { + case CRT2_LCD: + ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx; + break; + case CRT2_TV: + ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx; + break; + default: + ivideo->sisfb_mode_idx = ivideo->defmodeidx; + break; + } + } + + ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; + + if(ivideo->refresh_rate != 0) { + sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx); + } + + if(ivideo->rate_idx == 0) { + ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx; + ivideo->refresh_rate = 60; + } + + if(ivideo->sisfb_thismonitor.datavalid) { + if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx, + ivideo->rate_idx, ivideo->refresh_rate)) { + printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); + } + } + + ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp; + ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres; + ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres; + + sisfb_set_vparms(ivideo); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + + /* ---------------- For 2.4: Now switch the mode ------------------ */ + + printk(KERN_INFO "sisfb: Mode is %dx%dx%d (%dHz)\n", + ivideo->video_width, ivideo->video_height, ivideo->video_bpp, + ivideo->refresh_rate); + + sisfb_pre_setmode(ivideo); + + if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) { + printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n", + ivideo->mode_no); + iounmap(ivideo->video_vbase); + iounmap(ivideo->mmio_vbase); + release_mem_region(ivideo->video_base, ivideo->video_size); + release_mem_region(ivideo->mmio_base, ivideo->mmio_size); + if(ivideo->bios_abase) vfree(ivideo->bios_abase); + pci_set_drvdata(pdev, NULL); + kfree(sis_fb_info); + return -EINVAL; + } + + outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); + + sisfb_post_setmode(ivideo); + + /* Maximize regardless of sisfb_max at startup */ + ivideo->default_var.yres_virtual = 32767; + + /* Force reset of x virtual in crtc_to_var */ + ivideo->default_var.xres_virtual = 0; + + sisfb_crtc_to_var(ivideo, &ivideo->default_var); + + sisfb_calc_pitch(ivideo, &ivideo->default_var); + sisfb_set_pitch(ivideo); + + ivideo->accel = 0; + if(ivideo->sisfb_accel) { + ivideo->accel = -1; + ivideo->default_var.accel_flags |= FB_ACCELF_TEXT; + } + sisfb_initaccel(ivideo); + + sis_fb_info->node = -1; + sis_fb_info->flags = FBINFO_FLAG_DEFAULT; + sis_fb_info->fbops = &sisfb_ops; + sis_fb_info->disp = &ivideo->sis_disp; + sis_fb_info->blank = &sisfb_blank; + sis_fb_info->switch_con = &sisfb_switch; + sis_fb_info->updatevar = &sisfb_update_var; + sis_fb_info->changevar = NULL; + strcpy(sis_fb_info->fontname, sisfb_fontname); + + sisfb_set_disp(-1, &ivideo->default_var, sis_fb_info); + +#else /* --------- For 2.6: Setup a somewhat sane default var ------------ */ + + printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n", + ivideo->video_width, ivideo->video_height, ivideo->video_bpp, + ivideo->refresh_rate); + + ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width; + ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height; + ivideo->default_var.bits_per_pixel = ivideo->video_bpp; + + sisfb_bpp_to_var(ivideo, &ivideo->default_var); + + ivideo->default_var.pixclock = (u32) (1000000000 / + sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, &ivideo->sishw_ext, + ivideo->mode_no, ivideo->rate_idx)); + + if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext, + ivideo->mode_no, ivideo->rate_idx, &ivideo->default_var)) { + if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { + ivideo->default_var.pixclock <<= 1; + } + } + + if(ivideo->sisfb_ypan) { + /* Maximize regardless of sisfb_max at startup */ + ivideo->default_var.yres_virtual = sisfb_calc_maxyres(ivideo, &ivideo->default_var); + if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) { + ivideo->default_var.yres_virtual = ivideo->default_var.yres; + } + } + + sisfb_calc_pitch(ivideo, &ivideo->default_var); + + ivideo->accel = 0; + if(ivideo->sisfb_accel) { + ivideo->accel = -1; +#ifdef STUPID_ACCELF_TEXT_SHIT + ivideo->default_var.accel_flags |= FB_ACCELF_TEXT; +#endif + } + sisfb_initaccel(ivideo); + +#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN) + sis_fb_info->flags = FBINFO_DEFAULT | + FBINFO_HWACCEL_YPAN | + FBINFO_HWACCEL_XPAN | + FBINFO_HWACCEL_COPYAREA | + FBINFO_HWACCEL_FILLRECT | + ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED); +#else + sis_fb_info->flags = FBINFO_FLAG_DEFAULT; +#endif + sis_fb_info->var = ivideo->default_var; + sis_fb_info->fix = ivideo->sisfb_fix; + sis_fb_info->screen_base = ivideo->video_vbase; + sis_fb_info->fbops = &sisfb_ops; + + sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info); + sis_fb_info->pseudo_palette = ivideo->pseudo_palette; + + fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0); +#endif /* 2.6 */ + + printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", (unsigned long)ivideo->vbflags); + +#ifdef CONFIG_MTRR + ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size, + MTRR_TYPE_WRCOMB, 1); + if(!ivideo->mtrr) { + printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n"); + } +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + vc_resize_con(1, 1, 0); +#endif + + if(register_framebuffer(sis_fb_info) < 0) { + printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n"); + iounmap(ivideo->video_vbase); + iounmap(ivideo->mmio_vbase); + release_mem_region(ivideo->video_base, ivideo->video_size); + release_mem_region(ivideo->mmio_base, ivideo->mmio_size); + if(ivideo->bios_abase) vfree(ivideo->bios_abase); + pci_set_drvdata(pdev, NULL); + kfree(sis_fb_info); + return -EINVAL; + } + + ivideo->registered = 1; + + /* Enlist us */ + ivideo->next = card_list; + card_list = ivideo; + + printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n", + ivideo->sisfb_accel ? "enabled" : "disabled", + ivideo->sisfb_ypan ? + (ivideo->sisfb_max ? "enabled (auto-max)" : "enabled (no auto-max)") : "disabled"); + + + printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%d\n", +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + GET_FB_IDX(sis_fb_info->node), +#else + sis_fb_info->node, +#endif + ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL); + + printk(KERN_INFO "sisfb: (C) 2001-2004 Thomas Winischhofer.\n"); + + } /* if mode = "none" */ + + return 0; +} + +/*****************************************************/ +/* PCI DEVICE HANDLING */ +/*****************************************************/ + +static void __devexit sisfb_remove(struct pci_dev *pdev) +{ + struct sis_video_info *ivideo = pci_get_drvdata(pdev); + struct fb_info *sis_fb_info = ivideo->memyselfandi; + int registered = ivideo->registered; + + /* Unmap */ + iounmap(ivideo->video_vbase); + iounmap(ivideo->mmio_vbase); + vfree(ivideo->bios_abase); + + /* Release mem regions */ + release_mem_region(ivideo->video_base, ivideo->video_size); + release_mem_region(ivideo->mmio_base, ivideo->mmio_size); + +#ifdef CONFIG_MTRR + /* Release MTRR region */ + if(ivideo->mtrr) { + mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size); + } +#endif + + /* Unregister the framebuffer */ + if(ivideo->registered) { + unregister_framebuffer(sis_fb_info); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3)) + framebuffer_release(sis_fb_info); +#else + kfree(sis_fb_info); +#endif + } + + pci_set_drvdata(pdev, NULL); + + /* TODO: Restore the initial mode + * This sounds easy but is as good as impossible + * on many machines with SiS chip and video bridge + * since text modes are always set up differently + * from machine to machine. Depends on the type + * of integration between chipset and bridge. + */ + if(registered) { + printk(KERN_INFO "sisfb: Restoring of text mode not supported yet\n"); + } +}; + +static struct pci_driver sisfb_driver = { + .name = "sisfb", + .id_table = sisfb_pci_table, + .probe = sisfb_probe, + .remove = __devexit_p(sisfb_remove) +}; + +SISINITSTATIC int __init sisfb_init(void) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) +#ifndef MODULE + char *options = NULL; + + if(fb_get_options("sisfb", &options)) + return -ENODEV; + sisfb_setup(options); +#endif +#endif + return(pci_register_driver(&sisfb_driver)); +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) +#ifndef MODULE +module_init(sisfb_init); +#endif +#endif + +/*****************************************************/ +/* MODULE */ +/*****************************************************/ + +#ifdef MODULE + +static char *mode = NULL; +static int vesa = -1; +static unsigned int rate = 0; +static unsigned int crt1off = 1; +static unsigned int mem = 0; +static char *forcecrt2type = NULL; +static int forcecrt1 = -1; +static int pdc = -1; +static int pdc1 = -1; +static int noaccel = -1; +static int noypan = -1; +static int nomax = -1; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +static int inverse = 0; +#endif +static int userom = -1; +static int useoem = -1; +static char *tvstandard = NULL; +static int nocrt2rate = 0; +static int scalelcd = -1; +static char *specialtiming = NULL; +static int lvdshl = -1; +static int tvxposoffset = 0, tvyposoffset = 0; +static int filter = -1; +#if !defined(__i386__) && !defined(__x86_64__) +static int resetcard = 0; +static int videoram = 0; +#endif + +MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer device driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others"); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +MODULE_PARM(mem, "i"); +MODULE_PARM(noaccel, "i"); +MODULE_PARM(noypan, "i"); +MODULE_PARM(nomax, "i"); +MODULE_PARM(userom, "i"); +MODULE_PARM(useoem, "i"); +MODULE_PARM(mode, "s"); +MODULE_PARM(vesa, "i"); +MODULE_PARM(rate, "i"); +MODULE_PARM(forcecrt1, "i"); +MODULE_PARM(forcecrt2type, "s"); +MODULE_PARM(scalelcd, "i"); +MODULE_PARM(pdc, "i"); +MODULE_PARM(pdc1, "i"); +MODULE_PARM(specialtiming, "s"); +MODULE_PARM(lvdshl, "i"); +MODULE_PARM(tvstandard, "s"); +MODULE_PARM(tvxposoffset, "i"); +MODULE_PARM(tvyposoffset, "i"); +MODULE_PARM(filter, "i"); +MODULE_PARM(nocrt2rate, "i"); +MODULE_PARM(inverse, "i"); +#if !defined(__i386__) && !defined(__x86_64__) +MODULE_PARM(resetcard, "i"); +MODULE_PARM(videoram, "i"); +#endif +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +module_param(mem, int, 0); +module_param(noaccel, int, 0); +module_param(noypan, int, 0); +module_param(nomax, int, 0); +module_param(userom, int, 0); +module_param(useoem, int, 0); +module_param(mode, charp, 0); +module_param(vesa, int, 0); +module_param(rate, int, 0); +module_param(forcecrt1, int, 0); +module_param(forcecrt2type, charp, 0); +module_param(scalelcd, int, 0); +module_param(pdc, int, 0); +module_param(pdc1, int, 0); +module_param(specialtiming, charp, 0); +module_param(lvdshl, int, 0); +module_param(tvstandard, charp, 0); +module_param(tvxposoffset, int, 0); +module_param(tvyposoffset, int, 0); +module_param(filter, int, 0); +module_param(nocrt2rate, int, 0); +#if !defined(__i386__) && !defined(__x86_64__) +module_param(resetcard, int, 0); +module_param(videoram, int, 0); +#endif +#endif + +MODULE_PARM_DESC(mem, + "\nDetermines the beginning of the video memory heap in KB. This heap is used\n" + "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n" + "on the amount of video RAM available. If 8MB of video RAM or less is available,\n" + "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n" + "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n" + "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n" + "for XFree86 4.x/X.org 6.7 and later.\n"); + +MODULE_PARM_DESC(noaccel, + "\nIf set to anything other than 0, 2D acceleration will be disabled.\n" + "(default: 0)\n"); + +MODULE_PARM_DESC(noypan, + "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n" + "will be performed by redrawing the screen. (default: 0)\n"); + +MODULE_PARM_DESC(nomax, + "\nIf y-panning is enabled, sisfb will by default use the entire available video\n" + "memory for the virtual screen in order to optimize scrolling performance. If\n" + "this is set to anything other than 0, sisfb will not do this and thereby \n" + "enable the user to positively specify a virtual Y size of the screen using\n" + "fbset. (default: 0)\n"); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +MODULE_PARM_DESC(mode, + "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n" + "1024x768x16. Other formats supported include XxY-Depth and\n" + "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n" + "number, it will be interpreted as a VESA mode number. (default: none if\n" + "sisfb is a module; this leaves the console untouched and the driver will\n" + "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n" + "is in the kernel)\n"); +MODULE_PARM_DESC(vesa, + "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n" + "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n" + "and the driver will only do the video memory management for eg. DRM/DRI;\n" + "0x0103 if sisfb is in the kernel)\n"); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +MODULE_PARM_DESC(mode, + "\nSelects the desired default display mode in the format XxYxDepth,\n" + "eg. 1024x768x16. Other formats supported include XxY-Depth and\n" + "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n" + "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n"); + +MODULE_PARM_DESC(vesa, + "\nSelects the desired default display mode by VESA defined mode number, eg.\n" + "0x117 (default: 0x0103)\n"); +#endif + +MODULE_PARM_DESC(rate, + "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n" + "If the mode is specified in the format XxY-Depth@Rate, this parameter\n" + "will be ignored (default: 60)\n"); + +MODULE_PARM_DESC(forcecrt1, + "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n" + "connected. With this option, the detection can be overridden (1=CRT1 ON,\n" + "0=CRT1 OFF) (default: [autodetected])\n"); + +MODULE_PARM_DESC(forcecrt2type, + "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n" + "LCD, TV or secondary VGA. With this option, this autodetection can be\n" + "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n" + "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n" + "be used instead of TV to override the TV detection. Furthermore, on systems\n" + "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n" + "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n" + "depends on the very hardware in use. (default: [autodetected])\n"); + +MODULE_PARM_DESC(scalelcd, + "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n" + "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n" + "show black bars around the image, TMDS panels will probably do the scaling\n" + "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n"); + +MODULE_PARM_DESC(pdc, + "\nThis is for manually selecting the LCD panel delay compensation. The driver\n" + "should detect this correctly in most cases; however, sometimes this is not\n" + "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n" + "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n" + "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n" + "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n"); + +#ifdef CONFIG_FB_SIS_315 +MODULE_PARM_DESC(pdc1, + "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n" + "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n" + "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n" + "implemented yet.\n"); +#endif + +MODULE_PARM_DESC(specialtiming, + "\nPlease refer to documentation for more information on this option.\n"); + +MODULE_PARM_DESC(lvdshl, + "\nPlease refer to documentation for more information on this option.\n"); + +MODULE_PARM_DESC(tvstandard, + "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n" + "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n"); + +MODULE_PARM_DESC(tvxposoffset, + "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n" + "Default: 0\n"); + +MODULE_PARM_DESC(tvyposoffset, + "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n" + "Default: 0\n"); + +MODULE_PARM_DESC(filter, + "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n" + "(Possible values 0-7, default: [no filter])\n"); + +MODULE_PARM_DESC(nocrt2rate, + "\nSetting this to 1 will force the driver to use the default refresh rate for\n" + "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n"); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +MODULE_PARM_DESC(inverse, + "\nSetting this to anything but 0 should invert the display colors, but this\n" + "does not seem to work. (default: 0)\n"); +#endif + +#if !defined(__i386__) && !defined(__x86_64__) +#ifdef CONFIG_FB_SIS_300 +MODULE_PARM_DESC(resetcard, + "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n" + "the BIOS did not POST the card (only supported for SiS 300/305 currently).\n" + "Default: 0\n"); + +MODULE_PARM_DESC(videoram, + "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n" + "some non-x86 architectures where the memory auto detection fails. Only\n" + "relevant if resetcard is set, too. Default: [auto-detect]\n"); +#endif +#endif + +int __devinit sisfb_init_module(void) +{ + sisfb_setdefaultparms(); + + if(rate) sisfb_parm_rate = rate; + + if((scalelcd == 0) || (scalelcd == 1)) { + sisfb_scalelcd = scalelcd ^ 1; + } + + /* Need to check crt2 type first for fstn/dstn */ + + if(forcecrt2type) + sisfb_search_crt2type(forcecrt2type); + + if(tvstandard) + sisfb_search_tvstd(tvstandard); + + if(mode) + sisfb_search_mode(mode, FALSE); + else if(vesa != -1) + sisfb_search_vesamode(vesa, FALSE); + + sisfb_crt1off = (crt1off == 0) ? 1 : 0; + + sisfb_forcecrt1 = forcecrt1; + if(forcecrt1 == 1) sisfb_crt1off = 0; + else if(forcecrt1 == 0) sisfb_crt1off = 1; + + if(noaccel == 1) sisfb_accel = 0; + else if(noaccel == 0) sisfb_accel = 1; + + if(noypan == 1) sisfb_ypan = 0; + else if(noypan == 0) sisfb_ypan = 1; + + if(nomax == 1) sisfb_max = 0; + else if(nomax == 0) sisfb_max = 1; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + if(inverse) sisfb_inverse = 1; +#endif + + if(mem) sisfb_parm_mem = mem; + + if(userom != -1) sisfb_userom = userom; + if(useoem != -1) sisfb_useoem = useoem; + + if(pdc != -1) sisfb_pdc = (pdc & 0x7f); + if(pdc1 != -1) sisfb_pdca = (pdc1 & 0x1f); + + sisfb_nocrt2rate = nocrt2rate; + + if(specialtiming) + sisfb_search_specialtiming(specialtiming); + + if((lvdshl >= 0) && (lvdshl <= 3)) sisfb_lvdshl = lvdshl; + + if(filter != -1) sisfb_filter = filter; + + sisfb_tvxposoffset = tvxposoffset; + sisfb_tvyposoffset = tvyposoffset; + +#if !defined(__i386__) && !defined(__x86_64__) + sisfb_resetcard = (resetcard) ? 1 : 0; + if(videoram) sisfb_videoram = videoram; +#endif + + return(sisfb_init()); +} + +static void __exit sisfb_remove_module(void) +{ + pci_unregister_driver(&sisfb_driver); + printk(KERN_DEBUG "sisfb: Module unloaded\n"); +} + +module_init(sisfb_init_module); +module_exit(sisfb_remove_module); + +#endif /* /MODULE */ + +EXPORT_SYMBOL(sis_malloc); +EXPORT_SYMBOL(sis_free); + + diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h new file mode 100644 index 000000000000..a6678a7aff35 --- /dev/null +++ b/drivers/video/sis/sis_main.h @@ -0,0 +1,955 @@ +/* + * SiS 300/305/540/630(S)/730(S) + * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760 + * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3 + * + * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the named License, + * or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef _SISFB_MAIN +#define _SISFB_MAIN + +#include <linux/spinlock.h> + +#include "vstruct.h" +#include "sis.h" + +#define MODE_INDEX_NONE 0 /* index for mode=none */ + +/* Fbcon stuff */ +static struct fb_var_screeninfo my_default_var = { + .xres = 0, + .yres = 0, + .xres_virtual = 0, + .yres_virtual = 0, + .xoffset = 0, + .yoffset = 0, + .bits_per_pixel = 0, + .grayscale = 0, + .red = {0, 8, 0}, + .green = {0, 8, 0}, + .blue = {0, 8, 0}, + .transp = {0, 0, 0}, + .nonstd = 0, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .accel_flags = 0, + .pixclock = 0, + .left_margin = 0, + .right_margin = 0, + .upper_margin = 0, + .lower_margin = 0, + .hsync_len = 0, + .vsync_len = 0, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, +}; + +/* Boot-time parameters */ +static int sisfb_off = 0; +static int sisfb_parm_mem = 0; +static int sisfb_accel = -1; +static int sisfb_ypan = -1; +static int sisfb_max = -1; +static int sisfb_userom = 1; +static int sisfb_useoem = -1; +#ifdef MODULE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +static int sisfb_mode_idx = -1; +#else +static int sisfb_mode_idx = MODE_INDEX_NONE; /* Don't use a mode by default if we are a module */ +#endif +#else +static int sisfb_mode_idx = -1; /* Use a default mode if we are inside the kernel */ +#endif +static int sisfb_parm_rate = -1; +static int sisfb_crt1off = 0; +static int sisfb_forcecrt1 = -1; +static int sisfb_crt2type = -1; /* CRT2 type (for overriding autodetection) */ +static int sisfb_crt2flags = 0; +static int sisfb_pdc = 0xff; +static int sisfb_pdca = 0xff; +static int sisfb_scalelcd = -1; +static int sisfb_specialtiming = CUT_NONE; +static int sisfb_lvdshl = -1; +static int sisfb_dstn = 0; +static int sisfb_fstn = 0; +static int sisfb_tvplug = -1; /* Tv plug type (for overriding autodetection) */ +static int sisfb_tvstd = -1; +static int sisfb_tvxposoffset = 0; +static int sisfb_tvyposoffset = 0; +static int sisfb_filter = -1; +static int sisfb_nocrt2rate = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +static int sisfb_inverse = 0; +static char sisfb_fontname[40]; +#endif +#if !defined(__i386__) && !defined(__x86_64__) +static int sisfb_resetcard = 0; +static int sisfb_videoram = 0; +#endif + +/* List of supported chips */ +static struct sisfb_chip_info { + int chip; + int vgaengine; + int mni; + int hwcursor_size; + int CRT2_write_enable; + const char *chip_name; +} sisfb_chip_info[] __devinitdata = { + { SIS_300, SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 300/305" }, + { SIS_540, SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 540" }, + { SIS_630, SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 630" }, + { SIS_315H, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315H" }, + { SIS_315, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315" }, + { SIS_315PRO, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315PRO" }, + { SIS_550, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 55x" }, + { SIS_650, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 650" }, + { SIS_330, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 330" }, + { SIS_660, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 660" }, +}; + +static struct pci_device_id __devinitdata sisfb_pci_table[] = { +#ifdef CONFIG_FB_SIS_300 + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, +#endif +#ifdef CONFIG_FB_SIS_315 + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315H, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315PRO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7}, + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8}, + { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_660_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, +#endif + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, sisfb_pci_table); + +static struct sis_video_info *card_list = NULL; + +/* TODO: This is not handled card-wise because the DRM + does not refer to a unique fb when calling sis_alloc + or sis_free. Therefore, this is handled globally for + now (hoping that nobody is crazy enough to run two + SiS cards at the same time). + */ +static SIS_HEAP sisfb_heap; + +#define MD_SIS300 1 +#define MD_SIS315 2 + +/* Mode table */ +static const struct _sisbios_mode { + char name[15]; + u8 mode_no[2]; + u16 vesa_mode_no_1; /* "SiS defined" VESA mode number */ + u16 vesa_mode_no_2; /* Real VESA mode numbers */ + u16 xres; + u16 yres; + u16 bpp; + u16 rate_idx; + u16 cols; + u16 rows; + u8 chipset; +} sisbios_mode[] = { +/*0*/ {"none", {0xff,0xff}, 0x0000, 0x0000, 0, 0, 0, 0, 0, 0, MD_SIS300|MD_SIS315}, + {"320x200x8", {0x59,0x59}, 0x0138, 0x0000, 320, 200, 8, 1, 40, 12, MD_SIS300|MD_SIS315}, + {"320x200x16", {0x41,0x41}, 0x010e, 0x0000, 320, 200, 16, 1, 40, 12, MD_SIS300|MD_SIS315}, + {"320x200x24", {0x4f,0x4f}, 0x0000, 0x0000, 320, 200, 32, 1, 40, 12, MD_SIS300|MD_SIS315}, /* That's for people who mix up color- and fb depth */ + {"320x200x32", {0x4f,0x4f}, 0x0000, 0x0000, 320, 200, 32, 1, 40, 12, MD_SIS300|MD_SIS315}, + {"320x240x8", {0x50,0x50}, 0x0132, 0x0000, 320, 240, 8, 1, 40, 15, MD_SIS300|MD_SIS315}, + {"320x240x16", {0x56,0x56}, 0x0135, 0x0000, 320, 240, 16, 1, 40, 15, MD_SIS300|MD_SIS315}, + {"320x240x24", {0x53,0x53}, 0x0000, 0x0000, 320, 240, 32, 1, 40, 15, MD_SIS300|MD_SIS315}, + {"320x240x32", {0x53,0x53}, 0x0000, 0x0000, 320, 240, 32, 1, 40, 15, MD_SIS300|MD_SIS315}, + {"320x240x8", {0x5a,0x5a}, 0x0132, 0x0000, 320, 480, 8, 1, 40, 30, MD_SIS315}, /* FSTN */ +/*10*/ {"320x240x16", {0x5b,0x5b}, 0x0135, 0x0000, 320, 480, 16, 1, 40, 30, MD_SIS315}, /* FSTN */ + {"400x300x8", {0x51,0x51}, 0x0133, 0x0000, 400, 300, 8, 1, 50, 18, MD_SIS300|MD_SIS315}, + {"400x300x16", {0x57,0x57}, 0x0136, 0x0000, 400, 300, 16, 1, 50, 18, MD_SIS300|MD_SIS315}, + {"400x300x24", {0x54,0x54}, 0x0000, 0x0000, 400, 300, 32, 1, 50, 18, MD_SIS300|MD_SIS315}, + {"400x300x32", {0x54,0x54}, 0x0000, 0x0000, 400, 300, 32, 1, 50, 18, MD_SIS300|MD_SIS315}, + {"512x384x8", {0x52,0x52}, 0x0000, 0x0000, 512, 384, 8, 1, 64, 24, MD_SIS300|MD_SIS315}, + {"512x384x16", {0x58,0x58}, 0x0000, 0x0000, 512, 384, 16, 1, 64, 24, MD_SIS300|MD_SIS315}, + {"512x384x24", {0x5c,0x5c}, 0x0000, 0x0000, 512, 384, 32, 1, 64, 24, MD_SIS300|MD_SIS315}, + {"512x384x32", {0x5c,0x5c}, 0x0000, 0x0000, 512, 384, 32, 1, 64, 24, MD_SIS300|MD_SIS315}, + {"640x400x8", {0x2f,0x2f}, 0x0000, 0x0000, 640, 400, 8, 1, 80, 25, MD_SIS300|MD_SIS315}, +/*20*/ {"640x400x16", {0x5d,0x5d}, 0x0000, 0x0000, 640, 400, 16, 1, 80, 25, MD_SIS300|MD_SIS315}, + {"640x400x24", {0x5e,0x5e}, 0x0000, 0x0000, 640, 400, 32, 1, 80, 25, MD_SIS300|MD_SIS315}, + {"640x400x32", {0x5e,0x5e}, 0x0000, 0x0000, 640, 400, 32, 1, 80, 25, MD_SIS300|MD_SIS315}, + {"640x480x8", {0x2e,0x2e}, 0x0101, 0x0101, 640, 480, 8, 1, 80, 30, MD_SIS300|MD_SIS315}, + {"640x480x16", {0x44,0x44}, 0x0111, 0x0111, 640, 480, 16, 1, 80, 30, MD_SIS300|MD_SIS315}, + {"640x480x24", {0x62,0x62}, 0x013a, 0x0112, 640, 480, 32, 1, 80, 30, MD_SIS300|MD_SIS315}, + {"640x480x32", {0x62,0x62}, 0x013a, 0x0112, 640, 480, 32, 1, 80, 30, MD_SIS300|MD_SIS315}, + {"720x480x8", {0x31,0x31}, 0x0000, 0x0000, 720, 480, 8, 1, 90, 30, MD_SIS300|MD_SIS315}, + {"720x480x16", {0x33,0x33}, 0x0000, 0x0000, 720, 480, 16, 1, 90, 30, MD_SIS300|MD_SIS315}, + {"720x480x24", {0x35,0x35}, 0x0000, 0x0000, 720, 480, 32, 1, 90, 30, MD_SIS300|MD_SIS315}, +/*30*/ {"720x480x32", {0x35,0x35}, 0x0000, 0x0000, 720, 480, 32, 1, 90, 30, MD_SIS300|MD_SIS315}, + {"720x576x8", {0x32,0x32}, 0x0000, 0x0000, 720, 576, 8, 1, 90, 36, MD_SIS300|MD_SIS315}, + {"720x576x16", {0x34,0x34}, 0x0000, 0x0000, 720, 576, 16, 1, 90, 36, MD_SIS300|MD_SIS315}, + {"720x576x24", {0x36,0x36}, 0x0000, 0x0000, 720, 576, 32, 1, 90, 36, MD_SIS300|MD_SIS315}, + {"720x576x32", {0x36,0x36}, 0x0000, 0x0000, 720, 576, 32, 1, 90, 36, MD_SIS300|MD_SIS315}, + {"768x576x8", {0x5f,0x5f}, 0x0000, 0x0000, 768, 576, 8, 1, 96, 36, MD_SIS300|MD_SIS315}, + {"768x576x16", {0x60,0x60}, 0x0000, 0x0000, 768, 576, 16, 1, 96, 36, MD_SIS300|MD_SIS315}, + {"768x576x24", {0x61,0x61}, 0x0000, 0x0000, 768, 576, 32, 1, 96, 36, MD_SIS300|MD_SIS315}, + {"768x576x32", {0x61,0x61}, 0x0000, 0x0000, 768, 576, 32, 1, 96, 36, MD_SIS300|MD_SIS315}, + {"800x480x8", {0x70,0x70}, 0x0000, 0x0000, 800, 480, 8, 1, 100, 30, MD_SIS300|MD_SIS315}, +/*40*/ {"800x480x16", {0x7a,0x7a}, 0x0000, 0x0000, 800, 480, 16, 1, 100, 30, MD_SIS300|MD_SIS315}, + {"800x480x24", {0x76,0x76}, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_SIS300|MD_SIS315}, + {"800x480x32", {0x76,0x76}, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_SIS300|MD_SIS315}, +#define DEFAULT_MODE 43 /* index for 800x600x8 */ +#define DEFAULT_LCDMODE 43 /* index for 800x600x8 */ +#define DEFAULT_TVMODE 43 /* index for 800x600x8 */ + {"800x600x8", {0x30,0x30}, 0x0103, 0x0103, 800, 600, 8, 2, 100, 37, MD_SIS300|MD_SIS315}, + {"800x600x16", {0x47,0x47}, 0x0114, 0x0114, 800, 600, 16, 2, 100, 37, MD_SIS300|MD_SIS315}, + {"800x600x24", {0x63,0x63}, 0x013b, 0x0115, 800, 600, 32, 2, 100, 37, MD_SIS300|MD_SIS315}, + {"800x600x32", {0x63,0x63}, 0x013b, 0x0115, 800, 600, 32, 2, 100, 37, MD_SIS300|MD_SIS315}, + {"848x480x8", {0x39,0x39}, 0x0000, 0x0000, 848, 480, 8, 2, 106, 30, MD_SIS300|MD_SIS315}, + {"848x480x16", {0x3b,0x3b}, 0x0000, 0x0000, 848, 480, 16, 2, 106, 30, MD_SIS300|MD_SIS315}, + {"848x480x24", {0x3e,0x3e}, 0x0000, 0x0000, 848, 480, 32, 2, 106, 30, MD_SIS300|MD_SIS315}, +/*50*/ {"848x480x32", {0x3e,0x3e}, 0x0000, 0x0000, 848, 480, 32, 2, 106, 30, MD_SIS300|MD_SIS315}, + {"856x480x8", {0x3f,0x3f}, 0x0000, 0x0000, 856, 480, 8, 2, 107, 30, MD_SIS300|MD_SIS315}, + {"856x480x16", {0x42,0x42}, 0x0000, 0x0000, 856, 480, 16, 2, 107, 30, MD_SIS300|MD_SIS315}, + {"856x480x24", {0x45,0x45}, 0x0000, 0x0000, 856, 480, 32, 2, 107, 30, MD_SIS300|MD_SIS315}, + {"856x480x32", {0x45,0x45}, 0x0000, 0x0000, 856, 480, 32, 2, 107, 30, MD_SIS300|MD_SIS315}, + {"960x540x8", {0x1d,0x1d}, 0x0000, 0x0000, 960, 540, 8, 1, 120, 33, MD_SIS315}, + {"960x540x16", {0x1e,0x1e}, 0x0000, 0x0000, 960, 540, 16, 1, 120, 33, MD_SIS315}, + {"960x540x24", {0x1f,0x1f}, 0x0000, 0x0000, 960, 540, 32, 1, 120, 33, MD_SIS315}, + {"960x540x32", {0x1f,0x1f}, 0x0000, 0x0000, 960, 540, 32, 1, 120, 33, MD_SIS315}, + {"960x600x8", {0x20,0x20}, 0x0000, 0x0000, 960, 600, 8, 1, 120, 37, MD_SIS315}, +/*60*/ {"960x600x16", {0x21,0x21}, 0x0000, 0x0000, 960, 600, 16, 1, 120, 37, MD_SIS315}, + {"960x600x24", {0x22,0x22}, 0x0000, 0x0000, 960, 600, 32, 1, 120, 37, MD_SIS315}, + {"960x600x32", {0x22,0x22}, 0x0000, 0x0000, 960, 600, 32, 1, 120, 37, MD_SIS315}, + {"1024x576x8", {0x71,0x71}, 0x0000, 0x0000, 1024, 576, 8, 1, 128, 36, MD_SIS300|MD_SIS315}, + {"1024x576x16", {0x74,0x74}, 0x0000, 0x0000, 1024, 576, 16, 1, 128, 36, MD_SIS300|MD_SIS315}, + {"1024x576x24", {0x77,0x77}, 0x0000, 0x0000, 1024, 576, 32, 1, 128, 36, MD_SIS300|MD_SIS315}, + {"1024x576x32", {0x77,0x77}, 0x0000, 0x0000, 1024, 576, 32, 1, 128, 36, MD_SIS300|MD_SIS315}, + {"1024x600x8", {0x20,0x20}, 0x0000, 0x0000, 1024, 600, 8, 1, 128, 37, MD_SIS300 }, + {"1024x600x16", {0x21,0x21}, 0x0000, 0x0000, 1024, 600, 16, 1, 128, 37, MD_SIS300 }, + {"1024x600x24", {0x22,0x22}, 0x0000, 0x0000, 1024, 600, 32, 1, 128, 37, MD_SIS300 }, +/*70*/ {"1024x600x32", {0x22,0x22}, 0x0000, 0x0000, 1024, 600, 32, 1, 128, 37, MD_SIS300 }, + {"1024x768x8", {0x38,0x38}, 0x0105, 0x0105, 1024, 768, 8, 2, 128, 48, MD_SIS300|MD_SIS315}, + {"1024x768x16", {0x4a,0x4a}, 0x0117, 0x0117, 1024, 768, 16, 2, 128, 48, MD_SIS300|MD_SIS315}, + {"1024x768x24", {0x64,0x64}, 0x013c, 0x0118, 1024, 768, 32, 2, 128, 48, MD_SIS300|MD_SIS315}, + {"1024x768x32", {0x64,0x64}, 0x013c, 0x0118, 1024, 768, 32, 2, 128, 48, MD_SIS300|MD_SIS315}, + {"1152x768x8", {0x23,0x23}, 0x0000, 0x0000, 1152, 768, 8, 1, 144, 48, MD_SIS300 }, + {"1152x768x16", {0x24,0x24}, 0x0000, 0x0000, 1152, 768, 16, 1, 144, 48, MD_SIS300 }, + {"1152x768x24", {0x25,0x25}, 0x0000, 0x0000, 1152, 768, 32, 1, 144, 48, MD_SIS300 }, + {"1152x768x32", {0x25,0x25}, 0x0000, 0x0000, 1152, 768, 32, 1, 144, 48, MD_SIS300 }, + {"1152x864x8", {0x29,0x29}, 0x0000, 0x0000, 1152, 864, 8, 1, 144, 54, MD_SIS300|MD_SIS315}, +/*80*/ {"1152x864x16", {0x2a,0x2a}, 0x0000, 0x0000, 1152, 864, 16, 1, 144, 54, MD_SIS300|MD_SIS315}, + {"1152x864x24", {0x2b,0x2b}, 0x0000, 0x0000, 1152, 864, 32, 1, 144, 54, MD_SIS300|MD_SIS315}, + {"1152x864x32", {0x2b,0x2b}, 0x0000, 0x0000, 1152, 864, 32, 1, 144, 54, MD_SIS300|MD_SIS315}, + {"1280x720x8", {0x79,0x79}, 0x0000, 0x0000, 1280, 720, 8, 1, 160, 45, MD_SIS300|MD_SIS315}, + {"1280x720x16", {0x75,0x75}, 0x0000, 0x0000, 1280, 720, 16, 1, 160, 45, MD_SIS300|MD_SIS315}, + {"1280x720x24", {0x78,0x78}, 0x0000, 0x0000, 1280, 720, 32, 1, 160, 45, MD_SIS300|MD_SIS315}, + {"1280x720x32", {0x78,0x78}, 0x0000, 0x0000, 1280, 720, 32, 1, 160, 45, MD_SIS300|MD_SIS315}, + {"1280x768x8", {0x55,0x23}, 0x0000, 0x0000, 1280, 768, 8, 1, 160, 48, MD_SIS300|MD_SIS315}, + {"1280x768x16", {0x5a,0x24}, 0x0000, 0x0000, 1280, 768, 16, 1, 160, 48, MD_SIS300|MD_SIS315}, + {"1280x768x24", {0x5b,0x25}, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48, MD_SIS300|MD_SIS315}, +/*90*/ {"1280x768x32", {0x5b,0x25}, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48, MD_SIS300|MD_SIS315}, + {"1280x800x8", {0x14,0x14}, 0x0000, 0x0000, 1280, 800, 8, 1, 160, 50, MD_SIS315}, + {"1280x800x16", {0x15,0x15}, 0x0000, 0x0000, 1280, 800, 16, 1, 160, 50, MD_SIS315}, + {"1280x800x24", {0x16,0x16}, 0x0000, 0x0000, 1280, 800, 32, 1, 160, 50, MD_SIS315}, + {"1280x800x32", {0x16,0x16}, 0x0000, 0x0000, 1280, 800, 32, 1, 160, 50, MD_SIS315}, + {"1280x960x8", {0x7c,0x7c}, 0x0000, 0x0000, 1280, 960, 8, 1, 160, 60, MD_SIS300|MD_SIS315}, + {"1280x960x16", {0x7d,0x7d}, 0x0000, 0x0000, 1280, 960, 16, 1, 160, 60, MD_SIS300|MD_SIS315}, + {"1280x960x24", {0x7e,0x7e}, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_SIS300|MD_SIS315}, + {"1280x960x32", {0x7e,0x7e}, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_SIS300|MD_SIS315}, + {"1280x1024x8", {0x3a,0x3a}, 0x0107, 0x0107, 1280, 1024, 8, 2, 160, 64, MD_SIS300|MD_SIS315}, +/*100*/ {"1280x1024x16", {0x4d,0x4d}, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315}, + {"1280x1024x24", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315}, + {"1280x1024x32", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315}, + {"1360x768x8", {0x48,0x48}, 0x0000, 0x0000, 1360, 768, 8, 1, 170, 48, MD_SIS300|MD_SIS315}, + {"1360x768x16", {0x4b,0x4b}, 0x0000, 0x0000, 1360, 768, 16, 1, 170, 48, MD_SIS300|MD_SIS315}, + {"1360x768x24", {0x4e,0x4e}, 0x0000, 0x0000, 1360, 768, 32, 1, 170, 48, MD_SIS300|MD_SIS315}, + {"1360x768x32", {0x4e,0x4e}, 0x0000, 0x0000, 1360, 768, 32, 1, 170, 48, MD_SIS300|MD_SIS315}, + {"1360x1024x8", {0x67,0x67}, 0x0000, 0x0000, 1360, 1024, 8, 1, 170, 64, MD_SIS300 }, + {"1360x1024x16", {0x6f,0x6f}, 0x0000, 0x0000, 1360, 1024, 16, 1, 170, 64, MD_SIS300 }, + {"1360x1024x24", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300 }, +/*110*/ {"1360x1024x32", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300 }, + {"1400x1050x8", {0x26,0x26}, 0x0000, 0x0000, 1400, 1050, 8, 1, 175, 65, MD_SIS315}, + {"1400x1050x16", {0x27,0x27}, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65, MD_SIS315}, + {"1400x1050x24", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_SIS315}, + {"1400x1050x32", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_SIS315}, + {"1600x1200x8", {0x3c,0x3c}, 0x0130, 0x011c, 1600, 1200, 8, 1, 200, 75, MD_SIS300|MD_SIS315}, + {"1600x1200x16", {0x3d,0x3d}, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315}, + {"1600x1200x24", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315}, + {"1600x1200x32", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315}, + {"1680x1050x8", {0x17,0x17}, 0x0000, 0x0000, 1680, 1050, 8, 1, 210, 65, MD_SIS315}, +/*120*/ {"1680x1050x16", {0x18,0x18}, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65, MD_SIS315}, + {"1680x1050x24", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65, MD_SIS315}, + {"1680x1050x32", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65, MD_SIS315}, + {"1920x1080x8", {0x2c,0x2c}, 0x0000, 0x0000, 1920, 1080, 8, 1, 240, 67, MD_SIS315}, + {"1920x1080x16", {0x2d,0x2d}, 0x0000, 0x0000, 1920, 1080, 16, 1, 240, 67, MD_SIS315}, + {"1920x1080x24", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67, MD_SIS315}, + {"1920x1080x32", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67, MD_SIS315}, + {"1920x1440x8", {0x68,0x68}, 0x013f, 0x0000, 1920, 1440, 8, 1, 240, 75, MD_SIS300|MD_SIS315}, + {"1920x1440x16", {0x69,0x69}, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_SIS300|MD_SIS315}, + {"1920x1440x24", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315}, +/*130*/ {"1920x1440x32", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315}, + {"2048x1536x8", {0x6c,0x6c}, 0x0000, 0x0000, 2048, 1536, 8, 1, 256, 96, MD_SIS315}, + {"2048x1536x16", {0x6d,0x6d}, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96, MD_SIS315}, + {"2048x1536x24", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96, MD_SIS315}, + {"2048x1536x32", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96, MD_SIS315}, + {"\0", {0x00,0x00}, 0, 0, 0, 0, 0, 0, 0} +}; + +#define SIS_LCD_NUMBER 17 +static const struct _sis_lcd_data { + u32 lcdtype; + u16 xres; + u16 yres; + u8 default_mode_idx; +} sis_lcd_data[] = { + { LCD_640x480, 640, 480, 23 }, + { LCD_800x600, 800, 600, 43 }, + { LCD_1024x600, 1024, 600, 67 }, + { LCD_1024x768, 1024, 768, 71 }, + { LCD_1152x768, 1152, 768, 75 }, + { LCD_1152x864, 1152, 864, 79 }, + { LCD_1280x720, 1280, 720, 83 }, + { LCD_1280x768, 1280, 768, 87 }, + { LCD_1280x800, 1280, 800, 91 }, + { LCD_1280x960, 1280, 960, 95 }, + { LCD_1280x1024, 1280, 1024, 99 }, + { LCD_1400x1050, 1400, 1050, 111 }, + { LCD_1680x1050, 1680, 1050, 119 }, + { LCD_1600x1200, 1600, 1200, 115 }, + { LCD_640x480_2, 640, 480, 23 }, + { LCD_640x480_3, 640, 480, 23 }, + { LCD_320x480, 320, 480, 9 }, +}; + +/* CR36 evaluation */ +static const USHORT sis300paneltype[] = + { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024, + LCD_1280x960, LCD_640x480, LCD_1024x600, LCD_1152x768, + LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN, + LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN, LCD_UNKNOWN }; + +static const USHORT sis310paneltype[] = + { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024, + LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960, + LCD_1152x768, LCD_1400x1050, LCD_1280x768, LCD_1600x1200, + LCD_640x480_2, LCD_640x480_3, LCD_UNKNOWN, LCD_UNKNOWN }; + +static const USHORT sis661paneltype[] = + { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024, + LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960, + LCD_1152x768, LCD_1400x1050, LCD_1280x768, LCD_1600x1200, + LCD_1280x800, LCD_1680x1050, LCD_1280x720, LCD_UNKNOWN }; + +#define FL_550_DSTN 0x01 +#define FL_550_FSTN 0x02 +#define FL_300 0x04 +#define FL_315 0x08 + +static struct _sis_crt2type { + char name[32]; + u32 type_no; + u32 tvplug_no; + u16 flags; +} sis_crt2type[] __initdata = { + {"NONE", 0, -1, FL_300|FL_315}, + {"LCD", CRT2_LCD, -1, FL_300|FL_315}, + {"TV", CRT2_TV, -1, FL_300|FL_315}, + {"VGA", CRT2_VGA, -1, FL_300|FL_315}, + {"SVIDEO", CRT2_TV, TV_SVIDEO, FL_300|FL_315}, + {"COMPOSITE", CRT2_TV, TV_AVIDEO, FL_300|FL_315}, + {"CVBS", CRT2_TV, TV_AVIDEO, FL_300|FL_315}, + {"SVIDEO+COMPOSITE", CRT2_TV, TV_AVIDEO|TV_SVIDEO, FL_300|FL_315}, + {"COMPOSITE+SVIDEO", CRT2_TV, TV_AVIDEO|TV_SVIDEO, FL_300|FL_315}, + {"SVIDEO+CVBS", CRT2_TV, TV_AVIDEO|TV_SVIDEO, FL_300|FL_315}, + {"CVBS+SVIDEO", CRT2_TV, TV_AVIDEO|TV_SVIDEO, FL_300|FL_315}, + {"SCART", CRT2_TV, TV_SCART, FL_300|FL_315}, + {"HIVISION", CRT2_TV, TV_HIVISION, FL_315}, + {"YPBPR480I", CRT2_TV, TV_YPBPR|TV_YPBPR525I, FL_315}, + {"YPBPR480P", CRT2_TV, TV_YPBPR|TV_YPBPR525P, FL_315}, + {"YPBPR720P", CRT2_TV, TV_YPBPR|TV_YPBPR750P, FL_315}, + {"YPBPR1080I", CRT2_TV, TV_YPBPR|TV_YPBPR1080I, FL_315}, + {"DSTN", CRT2_LCD, -1, FL_315|FL_550_DSTN}, + {"FSTN", CRT2_LCD, -1, FL_315|FL_550_FSTN}, + {"\0", -1, -1, 0} +}; + +/* TV standard */ +static struct _sis_tvtype { + char name[6]; + u32 type_no; +} sis_tvtype[] __initdata = { + {"PAL", TV_PAL}, + {"NTSC", TV_NTSC}, + {"PALM", TV_PAL|TV_PALM}, + {"PALN", TV_PAL|TV_PALN}, + {"NTSCJ", TV_NTSC|TV_NTSCJ}, + {"\0", -1} +}; + +static const struct _sis_vrate { + u16 idx; + u16 xres; + u16 yres; + u16 refresh; + BOOLEAN SiS730valid32bpp; +} sisfb_vrate[] = { + {1, 320, 200, 70, TRUE}, + {1, 320, 240, 60, TRUE}, + {1, 320, 480, 60, TRUE}, + {1, 400, 300, 60, TRUE}, + {1, 512, 384, 60, TRUE}, + {1, 640, 400, 72, TRUE}, + {1, 640, 480, 60, TRUE}, {2, 640, 480, 72, TRUE}, {3, 640, 480, 75, TRUE}, + {4, 640, 480, 85, TRUE}, {5, 640, 480, 100, TRUE}, {6, 640, 480, 120, TRUE}, + {7, 640, 480, 160, TRUE}, {8, 640, 480, 200, TRUE}, + {1, 720, 480, 60, TRUE}, + {1, 720, 576, 58, TRUE}, + {1, 768, 576, 58, TRUE}, + {1, 800, 480, 60, TRUE}, {2, 800, 480, 75, TRUE}, {3, 800, 480, 85, TRUE}, + {1, 800, 600, 56, TRUE}, {2, 800, 600, 60, TRUE}, {3, 800, 600, 72, TRUE}, + {4, 800, 600, 75, TRUE}, {5, 800, 600, 85, TRUE}, {6, 800, 600, 105, TRUE}, + {7, 800, 600, 120, TRUE}, {8, 800, 600, 160, TRUE}, + {1, 848, 480, 39, TRUE}, {2, 848, 480, 60, TRUE}, + {1, 856, 480, 39, TRUE}, {2, 856, 480, 60, TRUE}, + {1, 960, 540, 60, TRUE}, + {1, 960, 600, 60, TRUE}, + {1, 1024, 576, 60, TRUE}, {2, 1024, 576, 75, TRUE}, {3, 1024, 576, 85, TRUE}, + {1, 1024, 600, 60, TRUE}, + {1, 1024, 768, 43, TRUE}, {2, 1024, 768, 60, TRUE}, {3, 1024, 768, 70, FALSE}, + {4, 1024, 768, 75, FALSE}, {5, 1024, 768, 85, TRUE}, {6, 1024, 768, 100, TRUE}, + {7, 1024, 768, 120, TRUE}, + {1, 1152, 768, 60, TRUE}, + {1, 1152, 864, 60, TRUE}, {1, 1152, 864, 75, TRUE}, {2, 1152, 864, 84, TRUE}, + {1, 1280, 720, 60, TRUE}, {2, 1280, 720, 75, TRUE}, {3, 1280, 720, 85, TRUE}, + {1, 1280, 768, 60, TRUE}, + {1, 1280, 800, 60, TRUE}, + {1, 1280, 960, 60, TRUE}, {2, 1280, 960, 85, TRUE}, + {1, 1280, 1024, 43, TRUE}, {2, 1280, 1024, 60, TRUE}, {3, 1280, 1024, 75, TRUE}, + {4, 1280, 1024, 85, TRUE}, + {1, 1360, 768, 60, TRUE}, + {1, 1360, 1024, 59, TRUE}, + {1, 1400, 1050, 60, TRUE}, {2, 1400, 1050, 75, TRUE}, + {1, 1600, 1200, 60, TRUE}, {2, 1600, 1200, 65, TRUE}, {3, 1600, 1200, 70, TRUE}, + {4, 1600, 1200, 75, TRUE}, {5, 1600, 1200, 85, TRUE}, {6, 1600, 1200, 100, TRUE}, + {7, 1600, 1200, 120, TRUE}, + {1, 1680, 1050, 60, TRUE}, + {1, 1920, 1080, 30, TRUE}, + {1, 1920, 1440, 60, TRUE}, {2, 1920, 1440, 65, TRUE}, {3, 1920, 1440, 70, TRUE}, + {4, 1920, 1440, 75, TRUE}, {5, 1920, 1440, 85, TRUE}, {6, 1920, 1440, 100, TRUE}, + {1, 2048, 1536, 60, TRUE}, {2, 2048, 1536, 65, TRUE}, {3, 2048, 1536, 70, TRUE}, + {4, 2048, 1536, 75, TRUE}, {5, 2048, 1536, 85, TRUE}, + {0, 0, 0, 0, FALSE} +}; + +static const struct _sisfbddcsmodes { + u32 mask; + u16 h; + u16 v; + u32 d; +} sisfb_ddcsmodes[] = { + { 0x10000, 67, 75, 108000}, + { 0x08000, 48, 72, 50000}, + { 0x04000, 46, 75, 49500}, + { 0x01000, 35, 43, 44900}, + { 0x00800, 48, 60, 65000}, + { 0x00400, 56, 70, 75000}, + { 0x00200, 60, 75, 78800}, + { 0x00100, 80, 75, 135000}, + { 0x00020, 31, 60, 25200}, + { 0x00008, 38, 72, 31500}, + { 0x00004, 37, 75, 31500}, + { 0x00002, 35, 56, 36000}, + { 0x00001, 38, 60, 40000} +}; + +static const struct _sisfbddcfmodes { + u16 x; + u16 y; + u16 v; + u16 h; + u32 d; +} sisfb_ddcfmodes[] = { + { 1280, 1024, 85, 92, 157500}, + { 1600, 1200, 60, 75, 162000}, + { 1600, 1200, 65, 82, 175500}, + { 1600, 1200, 70, 88, 189000}, + { 1600, 1200, 75, 94, 202500}, + { 1600, 1200, 85, 107,229500}, + { 1920, 1440, 60, 90, 234000}, + { 1920, 1440, 75, 113,297000} +}; + +#ifdef CONFIG_FB_SIS_300 +static struct _chswtable { + u16 subsysVendor; + u16 subsysCard; + char *vendorName; + char *cardName; +} mychswtable[] __devinitdata = { + { 0x1631, 0x1002, "Mitachi", "0x1002" }, + { 0x1071, 0x7521, "Mitac" , "7521P" }, + { 0, 0, "" , "" } +}; +#endif + +static struct _customttable { + u16 chipID; + char *biosversion; + char *biosdate; + u32 bioschksum; + u16 biosFootprintAddr[5]; + u8 biosFootprintData[5]; + u16 pcisubsysvendor; + u16 pcisubsyscard; + char *vendorName; + char *cardName; + u32 SpecialID; + char *optionName; +} mycustomttable[] __devinitdata = { + { SIS_630, "2.00.07", "09/27/2002-13:38:25", + 0x3240A8, + { 0x220, 0x227, 0x228, 0x229, 0x0ee }, + { 0x01, 0xe3, 0x9a, 0x6a, 0xef }, + 0x1039, 0x6300, + "Barco", "iQ R200L/300/400", CUT_BARCO1366, "BARCO_1366" + }, + { SIS_630, "2.00.07", "09/27/2002-13:38:25", + 0x323FBD, + { 0x220, 0x227, 0x228, 0x229, 0x0ee }, + { 0x00, 0x5a, 0x64, 0x41, 0xef }, + 0x1039, 0x6300, + "Barco", "iQ G200L/300/400/500", CUT_BARCO1024, "BARCO_1024" + }, + { SIS_650, "", "", + 0, + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0x0e11, 0x083c, + "Inventec (Compaq)", "3017cl/3045US", CUT_COMPAQ12802, "COMPAQ_1280" + }, + { SIS_650, "", "", + 0, + { 0x00c, 0, 0, 0, 0 }, + { 'e' , 0, 0, 0, 0 }, + 0x1558, 0x0287, + "Clevo", "L285/L287 (Version 1)", CUT_CLEVO1024, "CLEVO_L28X_1" + }, + { SIS_650, "", "", + 0, + { 0x00c, 0, 0, 0, 0 }, + { 'y' , 0, 0, 0, 0 }, + 0x1558, 0x0287, + "Clevo", "L285/L287 (Version 2)", CUT_CLEVO10242, "CLEVO_L28X_2" + }, + { SIS_650, "", "", + 0, + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0x1558, 0x0400, /* possibly 401 and 402 as well; not panelsize specific (?) */ + "Clevo", "D400S/D410S/D400H/D410H", CUT_CLEVO1400, "CLEVO_D4X0" + }, + { SIS_650, "", "", + 0, /* Shift LCD in LCD-via-CRT1 mode */ + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0x1558, 0x2263, + "Clevo", "D22ES/D27ES", CUT_UNIWILL1024, "CLEVO_D2X0ES" + }, + { SIS_650, "", "", + 0, /* Shift LCD in LCD-via-CRT1 mode */ + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0x1734, 0x101f, + "Uniwill", "N243S9", CUT_UNIWILL1024, "UNIWILL_N243S9" + }, + { SIS_650, "", "", + 0, /* Shift LCD in LCD-via-CRT1 mode */ + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0x1584, 0x5103, + "Uniwill", "N35BS1", CUT_UNIWILL10242, "UNIWILL_N35BS1" + }, + { SIS_650, "1.09.2c", "", /* Other versions, too? */ + 0, /* Shift LCD in LCD-via-CRT1 mode */ + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0x1019, 0x0f05, + "ECS", "A928", CUT_UNIWILL1024, "ECS_A928" + }, + { SIS_740, "1.11.27a", "", + 0, + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0x1043, 0x1612, + "Asus", "L3000D/L3500D", CUT_ASUSL3000D, "ASUS_L3X00" + }, + { SIS_650, "1.10.9k", "", + 0, + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0x1025, 0x0028, + "Acer", "Aspire 1700", CUT_ACER1280, "ACER_ASPIRE1700" + }, + { SIS_650, "1.10.7w", "", + 0, + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0x14c0, 0x0012, + "Compal", "??? (V1)", CUT_COMPAL1400_1, "COMPAL_1400_1" + }, + { SIS_650, "1.10.7x", "", + 0, + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0x14c0, 0x0012, + "Compal", "??? (V2)", CUT_COMPAL1400_2, "COMPAL_1400_2" + }, + { SIS_650, "1.10.8o", "", + 0, /* For EMI (unknown) */ + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0x1043, 0x1612, + "Asus", "A2H (V1)", CUT_ASUSA2H_1, "ASUS_A2H_1" + }, + { SIS_650, "1.10.8q", "", + 0, /* For EMI */ + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0x1043, 0x1612, + "Asus", "A2H (V2)", CUT_ASUSA2H_2, "ASUS_A2H_2" + }, + { 4321, "", "", /* never autodetected */ + 0, + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0, 0, + "Generic", "LVDS/Parallel 848x480", CUT_PANEL848, "PANEL848x480" + }, + { 0, "", "", + 0, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + 0, 0, + "", "", CUT_NONE, "" + } +}; + +static const struct _sis_TV_filter { + u8 filter[9][4]; +} sis_TV_filter[] = { + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_0 */ + {0x00,0xE0,0x10,0x60}, + {0x00,0xEE,0x10,0x44}, + {0x00,0xF4,0x10,0x38}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0x00,0x00,0x10,0x20}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_1 */ + {0x00,0xE0,0x10,0x60}, + {0x00,0xEE,0x10,0x44}, + {0x00,0xF4,0x10,0x38}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0x00,0x00,0x10,0x20}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_2 */ + {0xF5,0xEE,0x1B,0x44}, + {0xF8,0xF4,0x18,0x38}, + {0xEB,0x04,0x25,0x18}, + {0xF1,0x05,0x1F,0x16}, + {0xF6,0x06,0x1A,0x14}, + {0xFA,0x06,0x16,0x14}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_3 */ + {0xF1,0x04,0x1F,0x18}, + {0xEE,0x0D,0x22,0x06}, + {0xF7,0x06,0x19,0x14}, + {0xF4,0x0B,0x1C,0x0A}, + {0xFA,0x07,0x16,0x12}, + {0xF9,0x0A,0x17,0x0C}, + {0x00,0x07,0x10,0x12}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_4 - 320 */ + {0x00,0xE0,0x10,0x60}, + {0x00,0xEE,0x10,0x44}, + {0x00,0xF4,0x10,0x38}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0x00,0x00,0x10,0x20}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_5 - 640 */ + {0xF5,0xEE,0x1B,0x44}, + {0xF8,0xF4,0x18,0x38}, + {0xEB,0x04,0x25,0x18}, + {0xF1,0x05,0x1F,0x16}, + {0xF6,0x06,0x1A,0x14}, + {0xFA,0x06,0x16,0x14}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_6 - 720 */ + {0xEB,0x04,0x25,0x18}, + {0xE7,0x0E,0x29,0x04}, + {0xEE,0x0C,0x22,0x08}, + {0xF6,0x0B,0x1A,0x0A}, + {0xF9,0x0A,0x17,0x0C}, + {0xFC,0x0A,0x14,0x0C}, + {0x00,0x08,0x10,0x10}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_7 - 800 */ + {0xEC,0x02,0x24,0x1C}, + {0xF2,0x04,0x1E,0x18}, + {0xEB,0x15,0x25,0xF6}, + {0xF4,0x10,0x1C,0x00}, + {0xF8,0x0F,0x18,0x02}, + {0x00,0x04,0x10,0x18}, + {0x01,0x06,0x0F,0x14}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_0 */ + {0x00,0xE0,0x10,0x60}, + {0x00,0xEE,0x10,0x44}, + {0x00,0xF4,0x10,0x38}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0x00,0x00,0x10,0x20}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_1 */ + {0x00,0xE0,0x10,0x60}, + {0x00,0xEE,0x10,0x44}, + {0x00,0xF4,0x10,0x38}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0x00,0x00,0x10,0x20}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_2 */ + {0xF5,0xEE,0x1B,0x44}, + {0xF8,0xF4,0x18,0x38}, + {0xF1,0xF7,0x01,0x32}, + {0xF5,0xFB,0x1B,0x2A}, + {0xF9,0xFF,0x17,0x22}, + {0xFB,0x01,0x15,0x1E}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_3 */ + {0xF5,0xFB,0x1B,0x2A}, + {0xEE,0xFE,0x22,0x24}, + {0xF3,0x00,0x1D,0x20}, + {0xF9,0x03,0x17,0x1A}, + {0xFB,0x02,0x14,0x1E}, + {0xFB,0x04,0x15,0x18}, + {0x00,0x06,0x10,0x14}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_4 - 320 */ + {0x00,0xE0,0x10,0x60}, + {0x00,0xEE,0x10,0x44}, + {0x00,0xF4,0x10,0x38}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0x00,0x00,0x10,0x20}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_5 - 640 */ + {0xF5,0xEE,0x1B,0x44}, + {0xF8,0xF4,0x18,0x38}, + {0xF1,0xF7,0x1F,0x32}, + {0xF5,0xFB,0x1B,0x2A}, + {0xF9,0xFF,0x17,0x22}, + {0xFB,0x01,0x15,0x1E}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_6 - 720 */ + {0xF5,0xEE,0x1B,0x2A}, + {0xEE,0xFE,0x22,0x24}, + {0xF3,0x00,0x1D,0x20}, + {0xF9,0x03,0x17,0x1A}, + {0xFB,0x02,0x14,0x1E}, + {0xFB,0x04,0x15,0x18}, + {0x00,0x06,0x10,0x14}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_7 - 800 */ + {0xF5,0xEE,0x1B,0x44}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0xEB,0x05,0x25,0x16}, + {0xF1,0x05,0x1F,0x16}, + {0xFA,0x07,0x16,0x12}, + {0x00,0x07,0x10,0x12}, + {0xFF,0xFF,0xFF,0xFF} }} +}; + +/* ---------------------- Prototypes ------------------------- */ + +/* Interface used by the world */ +#ifndef MODULE +SISINITSTATIC int sisfb_setup(char *options); +#endif + +/* Interface to the low level console driver */ +SISINITSTATIC int sisfb_init(void); + + +/* fbdev routines */ +static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +static int sisfb_get_fix(struct fb_fix_screeninfo *fix, + int con, + struct fb_info *info); +static int sisfb_get_var(struct fb_var_screeninfo *var, + int con, + struct fb_info *info); +static int sisfb_set_var(struct fb_var_screeninfo *var, + int con, + struct fb_info *info); +static void sisfb_crtc_to_var(struct sis_video_info *ivideo, + struct fb_var_screeninfo *var); +static int sisfb_get_cmap(struct fb_cmap *cmap, + int kspc, + int con, + struct fb_info *info); +static int sisfb_set_cmap(struct fb_cmap *cmap, + int kspc, + int con, + struct fb_info *info); +static int sisfb_update_var(int con, + struct fb_info *info); +static int sisfb_switch(int con, + struct fb_info *info); +static void sisfb_blank(int blank, + struct fb_info *info); +static void sisfb_set_disp(int con, + struct fb_var_screeninfo *var, + struct fb_info *info); +static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, + unsigned *blue, unsigned *transp, + struct fb_info *fb_info); +static void sisfb_do_install_cmap(int con, + struct fb_info *info); +static int sisfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +static int sisfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + struct fb_info *info); +static int sisfb_set_par(struct fb_info *info); +static int sisfb_blank(int blank, + struct fb_info *info); +extern void fbcon_sis_fillrect(struct fb_info *info, + const struct fb_fillrect *rect); +extern void fbcon_sis_copyarea(struct fb_info *info, + const struct fb_copyarea *area); +extern int fbcon_sis_sync(struct fb_info *info); +#endif + +/* Internal 2D accelerator functions */ +extern int sisfb_initaccel(struct sis_video_info *ivideo); +extern void sisfb_syncaccel(struct sis_video_info *ivideo); + +/* Internal general routines */ +static void sisfb_search_mode(char *name, BOOLEAN quiet); +static int sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags); +static u8 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, + int index); +static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *fb_info); +static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, + struct fb_info *info); +static void sisfb_pre_setmode(struct sis_video_info *ivideo); +static void sisfb_post_setmode(struct sis_video_info *ivideo); +static BOOLEAN sisfb_CheckVBRetrace(struct sis_video_info *ivideo); +static BOOLEAN sisfbcheckvretracecrt2(struct sis_video_info *ivideo); +static BOOLEAN sisfbcheckvretracecrt1(struct sis_video_info *ivideo); +static BOOLEAN sisfb_bridgeisslave(struct sis_video_info *ivideo); +static void sisfb_detect_VB_connect(struct sis_video_info *ivideo); +static void sisfb_get_VB_type(struct sis_video_info *ivideo); +static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val); +static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val); + +/* SiS-specific exported functions */ +void sis_malloc(struct sis_memreq *req); +void sis_free(u32 base); + +/* Internal heap routines */ +static int sisfb_heap_init(struct sis_video_info *ivideo); +static SIS_OH *sisfb_poh_new_node(void); +static SIS_OH *sisfb_poh_allocate(u32 size); +static void sisfb_delete_node(SIS_OH *poh); +static void sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh); +static SIS_OH *sisfb_poh_free(u32 base); +static void sisfb_free_node(SIS_OH *poh); + +/* Sensing routines */ +static void SiS_Sense30x(struct sis_video_info *ivideo); +static void SiS_SenseCh(struct sis_video_info *ivideo); + +/* Routines from init.c/init301.c */ +extern USHORT SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, + BOOLEAN FSTN, USHORT CustomT, int LCDwith, int LCDheight); +extern USHORT SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth); +extern USHORT SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth); + +extern void SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr); +extern BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo, USHORT ModeNo); +extern void SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable); +extern void SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable); + +extern BOOLEAN SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); + +extern BOOLEAN sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension, + unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +extern int sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, + PSIS_HW_INFO HwDeviceExtension, + unsigned char modeno, unsigned char rateindex); +extern int sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension, + unsigned char modeno, unsigned char rateindex, + struct fb_var_screeninfo *var); +#endif + +/* Chrontel TV, DDC and DPMS functions */ +extern USHORT SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx); +extern void SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx); +extern USHORT SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx); +extern void SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx); +extern void SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh); +extern void SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime); +extern void SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo); +extern USHORT SiS_HandleDDC(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine, + USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer); +extern USHORT SiS_ReadDDC1Bit(SiS_Private *SiS_Pr); +extern void SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo); +extern void SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr); +extern void SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo); +extern void SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo); +#endif + + diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h new file mode 100644 index 000000000000..507bba1a71b5 --- /dev/null +++ b/drivers/video/sis/vgatypes.h @@ -0,0 +1,242 @@ +/* $XFree86$ */ +/* $XdotOrg$ */ +/* + * General type definitions for universal mode switching modules + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the named License, + * * or any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program; if not, write to the Free Software + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Otherwise, the following license terms apply: + * + * * Redistribution and use in source and binary forms, with or without + * * modification, are permitted provided that the following conditions + * * are met: + * * 1) Redistributions of source code must retain the above copyright + * * notice, this list of conditions and the following disclaimer. + * * 2) Redistributions in binary form must reproduce the above copyright + * * notice, this list of conditions and the following disclaimer in the + * * documentation and/or other materials provided with the distribution. + * * 3) The name of the author may not be used to endorse or promote products + * * derived from this software without specific prior written permission. + * * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + */ + +#ifndef _VGATYPES_ +#define _VGATYPES_ + +#ifdef LINUX_KERNEL /* We don't want the X driver to depend on kernel source */ +#include <linux/ioctl.h> +#include <linux/version.h> +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef CHAR +typedef char CHAR; +#endif + +#ifndef SHORT +typedef short SHORT; +#endif + +#ifndef LONG +typedef long LONG; +#endif + +#ifndef UCHAR +typedef unsigned char UCHAR; +#endif + +#ifndef USHORT +typedef unsigned short USHORT; +#endif + +#ifndef ULONG +typedef unsigned long ULONG; +#endif + +#ifndef BOOLEAN +typedef unsigned char BOOLEAN; +#endif + +#define SISIOMEMTYPE + +#ifdef LINUX_KERNEL +typedef unsigned long SISIOADDRESS; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) +#include <linux/types.h> /* Need __iomem */ +#undef SISIOMEMTYPE +#define SISIOMEMTYPE __iomem +#endif +#endif + +#ifdef LINUX_XF86 +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0) +typedef unsigned long IOADDRESS; +typedef unsigned long SISIOADDRESS; +#else +typedef IOADDRESS SISIOADDRESS; +#endif +#endif + +enum _SIS_CHIP_TYPE { + SIS_VGALegacy = 0, + SIS_530, + SIS_OLD, + SIS_300, + SIS_630, + SIS_730, + SIS_540, + SIS_315H, /* SiS 310 */ + SIS_315, + SIS_315PRO, + SIS_550, + SIS_650, + SIS_740, + SIS_330, + SIS_661, + SIS_741, + SIS_660, + SIS_760, + SIS_761, + SIS_340, + MAX_SIS_CHIP +}; + +#ifndef SIS_HW_INFO +typedef struct _SIS_HW_INFO SIS_HW_INFO, *PSIS_HW_INFO; + +struct _SIS_HW_INFO +{ +#ifdef LINUX_XF86 + PCITAG PciTag; /* PCI Tag */ +#endif + + UCHAR *pjVirtualRomBase; /* ROM image */ + + BOOLEAN UseROM; /* Use the ROM image if provided */ + +#ifdef LINUX_KERNEL + UCHAR SISIOMEMTYPE *pjVideoMemoryAddress; + /* base virtual memory address */ + /* of Linear VGA memory */ + + ULONG ulVideoMemorySize; /* size, in bytes, of the memory on the board */ +#endif + + SISIOADDRESS ulIOAddress; /* base I/O address of VGA ports (0x3B0; relocated) */ + + UCHAR jChipType; /* Used to Identify SiS Graphics Chip */ + /* defined in the enum "SIS_CHIP_TYPE" (above or sisfb.h) */ + + UCHAR jChipRevision; /* Used to Identify SiS Graphics Chip Revision */ + + BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */ +}; +#endif + +/* Addtional IOCTLs for communication sisfb <> X driver */ +/* If changing this, sisfb.h must also be changed (for sisfb) */ + +#ifdef LINUX_XF86 /* We don't want the X driver to depend on the kernel source */ + +/* ioctl for identifying and giving some info (esp. memory heap start) */ +#define SISFB_GET_INFO_SIZE 0x8004f300 +#define SISFB_GET_INFO 0x8000f301 /* Must be patched with result from ..._SIZE at D[29:16] */ +/* deprecated ioctl number (for older versions of sisfb) */ +#define SISFB_GET_INFO_OLD 0x80046ef8 + +/* ioctls for tv parameters (position) */ +#define SISFB_SET_TVPOSOFFSET 0x4004f304 + +/* lock sisfb from register access */ +#define SISFB_SET_LOCK 0x4004f306 + +/* Structure argument for SISFB_GET_INFO ioctl */ +typedef struct _SISFB_INFO sisfb_info, *psisfb_info; + +struct _SISFB_INFO { + CARD32 sisfb_id; /* for identifying sisfb */ +#ifndef SISFB_ID +#define SISFB_ID 0x53495346 /* Identify myself with 'SISF' */ +#endif + CARD32 chip_id; /* PCI ID of detected chip */ + CARD32 memory; /* video memory in KB which sisfb manages */ + CARD32 heapstart; /* heap start (= sisfb "mem" argument) in KB */ + CARD8 fbvidmode; /* current sisfb mode */ + + CARD8 sisfb_version; + CARD8 sisfb_revision; + CARD8 sisfb_patchlevel; + + CARD8 sisfb_caps; /* sisfb's capabilities */ + + CARD32 sisfb_tqlen; /* turbo queue length (in KB) */ + + CARD32 sisfb_pcibus; /* The card's PCI ID */ + CARD32 sisfb_pcislot; + CARD32 sisfb_pcifunc; + + CARD8 sisfb_lcdpdc; + + CARD8 sisfb_lcda; + + CARD32 sisfb_vbflags; + CARD32 sisfb_currentvbflags; + + CARD32 sisfb_scalelcd; + CARD32 sisfb_specialtiming; + + CARD8 sisfb_haveemi; + CARD8 sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33; + CARD8 sisfb_haveemilcd; + + CARD8 sisfb_lcdpdca; + + CARD16 sisfb_tvxpos, sisfb_tvypos; /* Warning: Values + 32 ! */ + + CARD8 reserved[208]; /* for future use */ +}; +#endif + +#endif + diff --git a/drivers/video/sis/vstruct.h b/drivers/video/sis/vstruct.h new file mode 100644 index 000000000000..d4d55c98bce6 --- /dev/null +++ b/drivers/video/sis/vstruct.h @@ -0,0 +1,676 @@ +/* $XFree86$ */ +/* $XdotOrg$ */ +/* + * General structure definitions for universal mode switching modules + * + * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria + * + * If distributed as part of the Linux kernel, the following license terms + * apply: + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the named License, + * * or any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program; if not, write to the Free Software + * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + * + * Otherwise, the following license terms apply: + * + * * Redistribution and use in source and binary forms, with or without + * * modification, are permitted provided that the following conditions + * * are met: + * * 1) Redistributions of source code must retain the above copyright + * * notice, this list of conditions and the following disclaimer. + * * 2) Redistributions in binary form must reproduce the above copyright + * * notice, this list of conditions and the following disclaimer in the + * * documentation and/or other materials provided with the distribution. + * * 3) The name of the author may not be used to endorse or promote products + * * derived from this software without specific prior written permission. + * * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + */ + +#ifndef _VSTRUCT_ +#define _VSTRUCT_ + +typedef struct _SiS_PanelDelayTblStruct +{ + UCHAR timer[2]; +} SiS_PanelDelayTblStruct; + +typedef struct _SiS_LCDDataStruct +{ + USHORT RVBHCMAX; + USHORT RVBHCFACT; + USHORT VGAHT; + USHORT VGAVT; + USHORT LCDHT; + USHORT LCDVT; +} SiS_LCDDataStruct; + +typedef struct _SiS_TVDataStruct +{ + USHORT RVBHCMAX; + USHORT RVBHCFACT; + USHORT VGAHT; + USHORT VGAVT; + USHORT TVHDE; + USHORT TVVDE; + USHORT RVBHRS; + UCHAR FlickerMode; + USHORT HALFRVBHRS; + UCHAR RY1COE; + UCHAR RY2COE; + UCHAR RY3COE; + UCHAR RY4COE; +} SiS_TVDataStruct; + +typedef struct _SiS_LVDSDataStruct +{ + USHORT VGAHT; + USHORT VGAVT; + USHORT LCDHT; + USHORT LCDVT; +} SiS_LVDSDataStruct; + +typedef struct _SiS_LVDSDesStruct +{ + USHORT LCDHDES; + USHORT LCDVDES; +} SiS_LVDSDesStruct; + +typedef struct _SiS_LVDSCRT1DataStruct +{ + UCHAR CR[15]; +} SiS_LVDSCRT1DataStruct; + +typedef struct _SiS_LCDACRT1DataStruct +{ + UCHAR CR[17]; +} SiS_LCDACRT1DataStruct; + +typedef struct _SiS_CHTVRegDataStruct +{ + UCHAR Reg[16]; +} SiS_CHTVRegDataStruct; + +typedef struct _SiS_StStruct +{ + UCHAR St_ModeID; + USHORT St_ModeFlag; + UCHAR St_StTableIndex; + UCHAR St_CRT2CRTC; + UCHAR St_ResInfo; + UCHAR VB_StTVFlickerIndex; + UCHAR VB_StTVEdgeIndex; + UCHAR VB_StTVYFilterIndex; + UCHAR St_PDC; +} SiS_StStruct; + +typedef struct _SiS_VBModeStruct +{ + UCHAR ModeID; + UCHAR VB_TVDelayIndex; + UCHAR VB_TVFlickerIndex; + UCHAR VB_TVPhaseIndex; + UCHAR VB_TVYFilterIndex; + UCHAR VB_LCDDelayIndex; + UCHAR _VB_LCDHIndex; + UCHAR _VB_LCDVIndex; +} SiS_VBModeStruct; + +typedef struct _SiS_StandTableStruct +{ + UCHAR CRT_COLS; + UCHAR ROWS; + UCHAR CHAR_HEIGHT; + USHORT CRT_LEN; + UCHAR SR[4]; + UCHAR MISC; + UCHAR CRTC[0x19]; + UCHAR ATTR[0x14]; + UCHAR GRC[9]; +} SiS_StandTableStruct; + +typedef struct _SiS_ExtStruct +{ + UCHAR Ext_ModeID; + USHORT Ext_ModeFlag; + USHORT Ext_VESAID; + UCHAR Ext_RESINFO; + UCHAR VB_ExtTVFlickerIndex; + UCHAR VB_ExtTVEdgeIndex; + UCHAR VB_ExtTVYFilterIndex; + UCHAR VB_ExtTVYFilterIndexROM661; + UCHAR REFindex; + CHAR ROMMODEIDX661; +} SiS_ExtStruct; + +typedef struct _SiS_Ext2Struct +{ + USHORT Ext_InfoFlag; + UCHAR Ext_CRT1CRTC; + UCHAR Ext_CRTVCLK; + UCHAR Ext_CRT2CRTC; + UCHAR Ext_CRT2CRTC_NS; + UCHAR ModeID; + USHORT XRes; + USHORT YRes; + UCHAR Ext_PDC; +} SiS_Ext2Struct; + +typedef struct _SiS_Part2PortTblStruct +{ + UCHAR CR[12]; +} SiS_Part2PortTblStruct; + +typedef struct _SiS_CRT1TableStruct +{ + UCHAR CR[17]; +} SiS_CRT1TableStruct; + +typedef struct _SiS_MCLKDataStruct +{ + UCHAR SR28,SR29,SR2A; + USHORT CLOCK; +} SiS_MCLKDataStruct; + +typedef struct _SiS_VCLKDataStruct +{ + UCHAR SR2B,SR2C; + USHORT CLOCK; +} SiS_VCLKDataStruct; + +typedef struct _SiS_VBVCLKDataStruct +{ + UCHAR Part4_A,Part4_B; + USHORT CLOCK; +} SiS_VBVCLKDataStruct; + +typedef struct _SiS_StResInfoStruct +{ + USHORT HTotal; + USHORT VTotal; +} SiS_StResInfoStruct; + +typedef struct _SiS_ModeResInfoStruct +{ + USHORT HTotal; + USHORT VTotal; + UCHAR XChar; + UCHAR YChar; +} SiS_ModeResInfoStruct; + + + +typedef UCHAR DRAM4Type[4]; + +/* Defines for SiS_CustomT */ +/* Never change these for sisfb compatibility */ +#define CUT_NONE 0 +#define CUT_FORCENONE 1 +#define CUT_BARCO1366 2 +#define CUT_BARCO1024 3 +#define CUT_COMPAQ1280 4 +#define CUT_COMPAQ12802 5 +#define CUT_PANEL848 6 +#define CUT_CLEVO1024 7 +#define CUT_CLEVO10242 8 +#define CUT_CLEVO1400 9 +#define CUT_CLEVO14002 10 +#define CUT_UNIWILL1024 11 +#define CUT_ASUSL3000D 12 +#define CUT_UNIWILL10242 13 +#define CUT_ACER1280 14 +#define CUT_COMPAL1400_1 15 +#define CUT_COMPAL1400_2 16 +#define CUT_ASUSA2H_1 17 +#define CUT_ASUSA2H_2 18 + +typedef struct _SiS_Private +{ +#ifdef LINUX_KERNEL + SISIOADDRESS RelIO; +#endif + SISIOADDRESS SiS_P3c4; + SISIOADDRESS SiS_P3d4; + SISIOADDRESS SiS_P3c0; + SISIOADDRESS SiS_P3ce; + SISIOADDRESS SiS_P3c2; + SISIOADDRESS SiS_P3ca; + SISIOADDRESS SiS_P3c6; + SISIOADDRESS SiS_P3c7; + SISIOADDRESS SiS_P3c8; + SISIOADDRESS SiS_P3c9; + SISIOADDRESS SiS_P3cb; + SISIOADDRESS SiS_P3cd; + SISIOADDRESS SiS_P3da; + SISIOADDRESS SiS_Part1Port; + SISIOADDRESS SiS_Part2Port; + SISIOADDRESS SiS_Part3Port; + SISIOADDRESS SiS_Part4Port; + SISIOADDRESS SiS_Part5Port; + SISIOADDRESS SiS_VidCapt; + SISIOADDRESS SiS_VidPlay; + USHORT SiS_IF_DEF_LVDS; + USHORT SiS_IF_DEF_CH70xx; + USHORT SiS_IF_DEF_CONEX; + USHORT SiS_IF_DEF_TRUMPION; + USHORT SiS_IF_DEF_DSTN; + USHORT SiS_IF_DEF_FSTN; + USHORT SiS_SysFlags; + UCHAR SiS_VGAINFO; +#ifdef LINUX_XF86 + USHORT SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4; +#endif + BOOLEAN SiS_UseROM; + BOOLEAN SiS_ROMNew; + BOOLEAN SiS_NeedRomModeData; + BOOLEAN PanelSelfDetected; + int SiS_CHOverScan; + BOOLEAN SiS_CHSOverScan; + BOOLEAN SiS_ChSW; + BOOLEAN SiS_UseLCDA; + int SiS_UseOEM; + ULONG SiS_CustomT; + USHORT SiS_Backup70xx; + BOOLEAN HaveEMI; + BOOLEAN HaveEMILCD; + BOOLEAN OverruleEMI; + UCHAR EMI_30,EMI_31,EMI_32,EMI_33; + USHORT SiS_EMIOffset; + SHORT PDC, PDCA; + UCHAR SiS_MyCR63; + USHORT SiS_CRT1Mode; + USHORT SiS_flag_clearbuffer; + int SiS_RAMType; + UCHAR SiS_ChannelAB; + UCHAR SiS_DataBusWidth; + USHORT SiS_ModeType; + USHORT SiS_VBInfo; + USHORT SiS_TVMode; + USHORT SiS_LCDResInfo; + USHORT SiS_LCDTypeInfo; + USHORT SiS_LCDInfo; + USHORT SiS_LCDInfo661; + USHORT SiS_VBType; + USHORT SiS_VBExtInfo; + USHORT SiS_YPbPr; + USHORT SiS_SelectCRT2Rate; + USHORT SiS_SetFlag; + USHORT SiS_RVBHCFACT; + USHORT SiS_RVBHCMAX; + USHORT SiS_RVBHRS; + USHORT SiS_VGAVT; + USHORT SiS_VGAHT; + USHORT SiS_VT; + USHORT SiS_HT; + USHORT SiS_VGAVDE; + USHORT SiS_VGAHDE; + USHORT SiS_VDE; + USHORT SiS_HDE; + USHORT SiS_NewFlickerMode; + USHORT SiS_RY1COE; + USHORT SiS_RY2COE; + USHORT SiS_RY3COE; + USHORT SiS_RY4COE; + USHORT SiS_LCDHDES; + USHORT SiS_LCDVDES; + USHORT SiS_DDC_Port; + USHORT SiS_DDC_Index; + USHORT SiS_DDC_Data; + USHORT SiS_DDC_NData; + USHORT SiS_DDC_Clk; + USHORT SiS_DDC_NClk; + USHORT SiS_DDC_DeviceAddr; + USHORT SiS_DDC_ReadAddr; + USHORT SiS_DDC_SecAddr; + USHORT SiS_ChrontelInit; + BOOLEAN SiS_SensibleSR11; + USHORT SiS661LCD2TableSize; + + USHORT SiS_PanelMinLVDS; + USHORT SiS_PanelMin301; + + const SiS_StStruct *SiS_SModeIDTable; + const SiS_StandTableStruct *SiS_StandTable; + const SiS_ExtStruct *SiS_EModeIDTable; + const SiS_Ext2Struct *SiS_RefIndex; + const SiS_VBModeStruct *SiS_VBModeIDTable; + const SiS_CRT1TableStruct *SiS_CRT1Table; + const SiS_MCLKDataStruct *SiS_MCLKData_0; + const SiS_MCLKDataStruct *SiS_MCLKData_1; + SiS_VCLKDataStruct *SiS_VCLKData; + SiS_VBVCLKDataStruct *SiS_VBVCLKData; + const SiS_StResInfoStruct *SiS_StResInfo; + const SiS_ModeResInfoStruct *SiS_ModeResInfo; + + const UCHAR *pSiS_OutputSelect; + const UCHAR *pSiS_SoftSetting; + + const DRAM4Type *SiS_SR15; /* pointer : point to array */ +#ifdef LINUX_KERNEL + UCHAR *pSiS_SR07; + const DRAM4Type *SiS_CR40; /* pointer : point to array */ + UCHAR *SiS_CR49; + UCHAR *SiS_SR25; + UCHAR *pSiS_SR1F; + UCHAR *pSiS_SR21; + UCHAR *pSiS_SR22; + UCHAR *pSiS_SR23; + UCHAR *pSiS_SR24; + UCHAR *pSiS_SR31; + UCHAR *pSiS_SR32; + UCHAR *pSiS_SR33; + UCHAR *pSiS_CRT2Data_1_2; + UCHAR *pSiS_CRT2Data_4_D; + UCHAR *pSiS_CRT2Data_4_E; + UCHAR *pSiS_CRT2Data_4_10; + const USHORT *pSiS_RGBSenseData; + const USHORT *pSiS_VideoSenseData; + const USHORT *pSiS_YCSenseData; + const USHORT *pSiS_RGBSenseData2; + const USHORT *pSiS_VideoSenseData2; + const USHORT *pSiS_YCSenseData2; +#endif + + const SiS_PanelDelayTblStruct *SiS_PanelDelayTbl; + const SiS_PanelDelayTblStruct *SiS_PanelDelayTblLVDS; + + /* SiS bridge */ + + const UCHAR *SiS_NTSCPhase; + const UCHAR *SiS_PALPhase; + const UCHAR *SiS_NTSCPhase2; + const UCHAR *SiS_PALPhase2; + const UCHAR *SiS_PALMPhase; + const UCHAR *SiS_PALNPhase; + const UCHAR *SiS_PALMPhase2; + const UCHAR *SiS_PALNPhase2; + const UCHAR *SiS_SpecialPhase; + const UCHAR *SiS_SpecialPhaseM; + const UCHAR *SiS_SpecialPhaseJ; + const SiS_LCDDataStruct *SiS_ExtLCD1024x768Data; + const SiS_LCDDataStruct *SiS_St2LCD1024x768Data; + const SiS_LCDDataStruct *SiS_LCD1280x720Data; + const SiS_LCDDataStruct *SiS_StLCD1280x768_2Data; + const SiS_LCDDataStruct *SiS_ExtLCD1280x768_2Data; + const SiS_LCDDataStruct *SiS_LCD1280x800Data; + const SiS_LCDDataStruct *SiS_LCD1280x800_2Data; + const SiS_LCDDataStruct *SiS_LCD1280x960Data; + const SiS_LCDDataStruct *SiS_ExtLCD1280x1024Data; + const SiS_LCDDataStruct *SiS_St2LCD1280x1024Data; + const SiS_LCDDataStruct *SiS_StLCD1400x1050Data; + const SiS_LCDDataStruct *SiS_ExtLCD1400x1050Data; + const SiS_LCDDataStruct *SiS_StLCD1600x1200Data; + const SiS_LCDDataStruct *SiS_ExtLCD1600x1200Data; + const SiS_LCDDataStruct *SiS_LCD1680x1050Data; + const SiS_LCDDataStruct *SiS_NoScaleData; + const SiS_TVDataStruct *SiS_StPALData; + const SiS_TVDataStruct *SiS_ExtPALData; + const SiS_TVDataStruct *SiS_StNTSCData; + const SiS_TVDataStruct *SiS_ExtNTSCData; + const SiS_TVDataStruct *SiS_St1HiTVData; + const SiS_TVDataStruct *SiS_St2HiTVData; + const SiS_TVDataStruct *SiS_ExtHiTVData; + const SiS_TVDataStruct *SiS_St525iData; + const SiS_TVDataStruct *SiS_St525pData; + const SiS_TVDataStruct *SiS_St750pData; + const SiS_TVDataStruct *SiS_Ext525iData; + const SiS_TVDataStruct *SiS_Ext525pData; + const SiS_TVDataStruct *SiS_Ext750pData; + const UCHAR *SiS_NTSCTiming; + const UCHAR *SiS_PALTiming; + const UCHAR *SiS_HiTVExtTiming; + const UCHAR *SiS_HiTVSt1Timing; + const UCHAR *SiS_HiTVSt2Timing; + const UCHAR *SiS_HiTVGroup3Data; + const UCHAR *SiS_HiTVGroup3Simu; +#if 0 + const UCHAR *SiS_HiTVTextTiming; + const UCHAR *SiS_HiTVGroup3Text; +#endif + + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_1; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_1; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_2; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_2; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_3; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_3; + + /* LVDS, Chrontel */ + + const SiS_LVDSDataStruct *SiS_LVDS800x600Data_1; + const SiS_LVDSDataStruct *SiS_LVDS800x600Data_2; + const SiS_LVDSDataStruct *SiS_LVDS1024x768Data_1; + const SiS_LVDSDataStruct *SiS_LVDS1024x768Data_2; + const SiS_LVDSDataStruct *SiS_LVDS1280x1024Data_1; + const SiS_LVDSDataStruct *SiS_LVDS1280x1024Data_2; + const SiS_LVDSDataStruct *SiS_LVDS1280x960Data_1; + const SiS_LVDSDataStruct *SiS_LVDS1280x960Data_2; + const SiS_LVDSDataStruct *SiS_LVDS1400x1050Data_1; + const SiS_LVDSDataStruct *SiS_LVDS1400x1050Data_2; + const SiS_LVDSDataStruct *SiS_LVDS1600x1200Data_1; + const SiS_LVDSDataStruct *SiS_LVDS1600x1200Data_2; + const SiS_LVDSDataStruct *SiS_LVDS1280x768Data_1; + const SiS_LVDSDataStruct *SiS_LVDS1280x768Data_2; + const SiS_LVDSDataStruct *SiS_LVDS1024x600Data_1; + const SiS_LVDSDataStruct *SiS_LVDS1024x600Data_2; + const SiS_LVDSDataStruct *SiS_LVDS1152x768Data_1; + const SiS_LVDSDataStruct *SiS_LVDS1152x768Data_2; + const SiS_LVDSDataStruct *SiS_LVDS640x480Data_1; + const SiS_LVDSDataStruct *SiS_LVDS640x480Data_2; + const SiS_LVDSDataStruct *SiS_LVDS320x480Data_1; + const SiS_LVDSDataStruct *SiS_LVDSXXXxXXXData_1; + const SiS_LVDSDataStruct *SiS_LVDSBARCO1366Data_1; + const SiS_LVDSDataStruct *SiS_LVDSBARCO1366Data_2; + const SiS_LVDSDataStruct *SiS_LVDSBARCO1024Data_1; + const SiS_LVDSDataStruct *SiS_LVDSBARCO1024Data_2; + const SiS_LVDSDataStruct *SiS_LVDS848x480Data_1; + const SiS_LVDSDataStruct *SiS_LVDS848x480Data_2; + const SiS_LVDSDataStruct *SiS_CHTVUNTSCData; + const SiS_LVDSDataStruct *SiS_CHTVONTSCData; + const SiS_LVDSDataStruct *SiS_CHTVUPALData; + const SiS_LVDSDataStruct *SiS_CHTVOPALData; + const SiS_LVDSDataStruct *SiS_CHTVUPALMData; + const SiS_LVDSDataStruct *SiS_CHTVOPALMData; + const SiS_LVDSDataStruct *SiS_CHTVUPALNData; + const SiS_LVDSDataStruct *SiS_CHTVOPALNData; + const SiS_LVDSDataStruct *SiS_CHTVSOPALData; + + const SiS_LVDSDesStruct *SiS_PanelType00_1; + const SiS_LVDSDesStruct *SiS_PanelType01_1; + const SiS_LVDSDesStruct *SiS_PanelType02_1; + const SiS_LVDSDesStruct *SiS_PanelType03_1; + const SiS_LVDSDesStruct *SiS_PanelType04_1; + const SiS_LVDSDesStruct *SiS_PanelType05_1; + const SiS_LVDSDesStruct *SiS_PanelType06_1; + const SiS_LVDSDesStruct *SiS_PanelType07_1; + const SiS_LVDSDesStruct *SiS_PanelType08_1; + const SiS_LVDSDesStruct *SiS_PanelType09_1; + const SiS_LVDSDesStruct *SiS_PanelType0a_1; + const SiS_LVDSDesStruct *SiS_PanelType0b_1; + const SiS_LVDSDesStruct *SiS_PanelType0c_1; + const SiS_LVDSDesStruct *SiS_PanelType0d_1; + const SiS_LVDSDesStruct *SiS_PanelType0e_1; + const SiS_LVDSDesStruct *SiS_PanelType0f_1; + const SiS_LVDSDesStruct *SiS_PanelTypeNS_1; + const SiS_LVDSDesStruct *SiS_PanelType00_2; + const SiS_LVDSDesStruct *SiS_PanelType01_2; + const SiS_LVDSDesStruct *SiS_PanelType02_2; + const SiS_LVDSDesStruct *SiS_PanelType03_2; + const SiS_LVDSDesStruct *SiS_PanelType04_2; + const SiS_LVDSDesStruct *SiS_PanelType05_2; + const SiS_LVDSDesStruct *SiS_PanelType06_2; + const SiS_LVDSDesStruct *SiS_PanelType07_2; + const SiS_LVDSDesStruct *SiS_PanelType08_2; + const SiS_LVDSDesStruct *SiS_PanelType09_2; + const SiS_LVDSDesStruct *SiS_PanelType0a_2; + const SiS_LVDSDesStruct *SiS_PanelType0b_2; + const SiS_LVDSDesStruct *SiS_PanelType0c_2; + const SiS_LVDSDesStruct *SiS_PanelType0d_2; + const SiS_LVDSDesStruct *SiS_PanelType0e_2; + const SiS_LVDSDesStruct *SiS_PanelType0f_2; + const SiS_LVDSDesStruct *SiS_PanelTypeNS_2; + const SiS_LVDSDesStruct *SiS_CHTVUNTSCDesData; + const SiS_LVDSDesStruct *SiS_CHTVONTSCDesData; + const SiS_LVDSDesStruct *SiS_CHTVUPALDesData; + const SiS_LVDSDesStruct *SiS_CHTVOPALDesData; + + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_1; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_1; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_1; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11400x1050_1; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x768_1; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x600_1; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11152x768_1; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11600x1200_1; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_1_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_1_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_1_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11400x1050_1_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x768_1_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x600_1_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11152x768_1_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11600x1200_1_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_2; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_2; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_2; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11400x1050_2; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x768_2; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x600_2; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11152x768_2; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11600x1200_2; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1800x600_2_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x768_2_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x1024_2_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11400x1050_2_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11280x768_2_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11024x600_2_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11152x768_2_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11600x1200_2_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1XXXxXXX_1; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1XXXxXXX_1_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_1; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_1_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_2; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_2_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_3; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_3_H; + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1320x480_1; + const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1UNTSC; + const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1ONTSC; + const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1UPAL; + const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1OPAL; + const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1SOPAL; + + const SiS_CHTVRegDataStruct *SiS_CHTVReg_UNTSC; + const SiS_CHTVRegDataStruct *SiS_CHTVReg_ONTSC; + const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPAL; + const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPAL; + const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPALM; + const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPALM; + const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPALN; + const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPALN; + const SiS_CHTVRegDataStruct *SiS_CHTVReg_SOPAL; + + const UCHAR *SiS_CHTVVCLKUNTSC; + const UCHAR *SiS_CHTVVCLKONTSC; + const UCHAR *SiS_CHTVVCLKUPAL; + const UCHAR *SiS_CHTVVCLKOPAL; + const UCHAR *SiS_CHTVVCLKUPALM; + const UCHAR *SiS_CHTVVCLKOPALM; + const UCHAR *SiS_CHTVVCLKUPALN; + const UCHAR *SiS_CHTVVCLKOPALN; + const UCHAR *SiS_CHTVVCLKSOPAL; + + USHORT PanelXRes, PanelHT; + USHORT PanelYRes, PanelVT; + USHORT PanelHRS, PanelHRE; + USHORT PanelVRS, PanelVRE; + USHORT PanelVCLKIdx300; + USHORT PanelVCLKIdx315; + + BOOLEAN UseCustomMode; + BOOLEAN CRT1UsesCustomMode; + USHORT CHDisplay; + USHORT CHSyncStart; + USHORT CHSyncEnd; + USHORT CHTotal; + USHORT CHBlankStart; + USHORT CHBlankEnd; + USHORT CVDisplay; + USHORT CVSyncStart; + USHORT CVSyncEnd; + USHORT CVTotal; + USHORT CVBlankStart; + USHORT CVBlankEnd; + ULONG CDClock; + ULONG CFlags; + UCHAR CCRT1CRTC[17]; + UCHAR CSR2B; + UCHAR CSR2C; + USHORT CSRClock; + USHORT CSRClock_CRT1; + USHORT CModeFlag; + USHORT CModeFlag_CRT1; + USHORT CInfoFlag; + + int LVDSHL; + + BOOLEAN Backup; + UCHAR Backup_Mode; + UCHAR Backup_14; + UCHAR Backup_15; + UCHAR Backup_16; + UCHAR Backup_17; + UCHAR Backup_18; + UCHAR Backup_19; + UCHAR Backup_1a; + UCHAR Backup_1b; + UCHAR Backup_1c; + UCHAR Backup_1d; + + int UsePanelScaler; + int CenterScreen; + + USHORT CP_Vendor, CP_Product; + BOOLEAN CP_HaveCustomData; + int CP_PreferredX, CP_PreferredY, CP_PreferredIndex; + int CP_MaxX, CP_MaxY, CP_MaxClock; + UCHAR CP_PrefSR2B, CP_PrefSR2C; + USHORT CP_PrefClock; + BOOLEAN CP_Supports64048075; + int CP_HDisplay[7], CP_VDisplay[7]; /* For Custom LCD panel dimensions */ + int CP_HTotal[7], CP_VTotal[7]; + int CP_HSyncStart[7], CP_VSyncStart[7]; + int CP_HSyncEnd[7], CP_VSyncEnd[7]; + int CP_HBlankStart[7], CP_VBlankStart[7]; + int CP_HBlankEnd[7], CP_VBlankEnd[7]; + int CP_Clock[7]; + BOOLEAN CP_DataValid[7]; + BOOLEAN CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7]; +} SiS_Private; + +#endif + |