diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
commit | d1473b7bcf205215781d461eb62f8dba0fb78931 (patch) | |
tree | 3e20c3e5811215076b10a98c5f1dfe7553d44e94 | |
parent | 727bfe5d006d0e5c0167c2472af9d8ba69c9e109 (diff) |
Initial revision
-rw-r--r-- | man/sis.man | 413 | ||||
-rw-r--r-- | src/300vtbl.h | 3314 | ||||
-rw-r--r-- | src/310vtbl.h | 4673 | ||||
-rw-r--r-- | src/init.c | 5968 | ||||
-rw-r--r-- | src/init.h | 316 | ||||
-rw-r--r-- | src/init301.c | 10798 | ||||
-rw-r--r-- | src/init301.h | 285 | ||||
-rw-r--r-- | src/initdef.h | 434 | ||||
-rw-r--r-- | src/oem300.h | 1005 | ||||
-rw-r--r-- | src/oem310.h | 377 | ||||
-rw-r--r-- | src/osdef.h | 169 | ||||
-rw-r--r-- | src/sis.h | 710 | ||||
-rw-r--r-- | src/sis300_accel.c | 1397 | ||||
-rw-r--r-- | src/sis300_accel.h | 297 | ||||
-rw-r--r-- | src/sis310_accel.c | 894 | ||||
-rw-r--r-- | src/sis310_accel.h | 341 | ||||
-rw-r--r-- | src/sis6326_video.c | 1662 | ||||
-rw-r--r-- | src/sis_accel.c | 651 | ||||
-rw-r--r-- | src/sis_accel.h | 237 | ||||
-rw-r--r-- | src/sis_cursor.c | 1106 | ||||
-rw-r--r-- | src/sis_cursor.h | 427 | ||||
-rw-r--r-- | src/sis_dac.c | 2148 | ||||
-rw-r--r-- | src/sis_dac.h | 53 | ||||
-rw-r--r-- | src/sis_dga.c | 412 | ||||
-rw-r--r-- | src/sis_dri.c | 616 | ||||
-rw-r--r-- | src/sis_dri.h | 69 | ||||
-rw-r--r-- | src/sis_driver.c | 7648 | ||||
-rw-r--r-- | src/sis_driver.h | 512 | ||||
-rw-r--r-- | src/sis_opt.c | 774 | ||||
-rw-r--r-- | src/sis_regs.h | 587 | ||||
-rw-r--r-- | src/sis_setup.c | 528 | ||||
-rw-r--r-- | src/sis_shadow.c | 250 | ||||
-rw-r--r-- | src/sis_vb.c | 353 | ||||
-rw-r--r-- | src/sis_vga.c | 1535 | ||||
-rw-r--r-- | src/sis_video.c | 2454 | ||||
-rw-r--r-- | src/vgatypes.h | 368 | ||||
-rw-r--r-- | src/vstruct.h | 571 |
37 files changed, 54352 insertions, 0 deletions
diff --git a/man/sis.man b/man/sis.man new file mode 100644 index 0000000..7663044 --- /dev/null +++ b/man/sis.man @@ -0,0 +1,413 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis.man,v 1.10 2003/01/29 15:42:16 eich Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH SIS __drivermansuffix__ __vendorversion__ +.SH NAME +sis \- SiS video driver +.SH SYNOPSIS +.nf +.B "Section \*qDevice\*q" +.BI " Identifier \*q" devname \*q +.B " Driver \*qsis\*q" +\ \ ... +.B EndSection +.fi +.SH DESCRIPTION +.B sis +is an XFree86 driver for SiS video chips. The driver is accelerated, and +provides support for 8, 16 and 24 colordepths. XVideo, Render and other +extensions are supported as well. +.SH SUPPORTED HARDWARE +The +.B sis +driver supports PCI and AGP video cards based on the following chipsets: +.PP +.B SiS5597/5598 +.B SiS530/620 +.B SiS6326/AGP/DVD +.B SiS300/305 +.B SiS540 +.B SiS630/730 +.B SiS315/H/PRO +.B SiS550 +.B SiS650/651/650M/740 +.B SiS330 (Xabre) +.PP +In the following text, the following terms are used: +.PP +.B old series +for SiS5597/5598, 530/620 and 6326/AGP/DVD +.PP +.B 300 series +for SiS300/305, 540 and 630/730 +.PP +.B 310/325/330 series +for SiS315/H/PRO, 550 and 650/651/650M/740, 330 +.SH CONFIGURATION DETAILS +Please refer to XF86Config(__filemansuffix__) for general configuration +details. This section only covers configuration details specific to this +driver. Please note that support for the SiS330 is new and there may be +some problems. +.PP +.I "1. For all supported chipsets" +.PP +The following driver +.B Options +are supported on all chipsets: +.TP +.BI "Option \*qNoAccel\*q \*q" boolean \*q +Disable or enable 2D acceleration. Please note: On chipsets with XVideo +support, this also disables XVideo. Default: acceleration is enabled. +.TP +.BI "Option \*qHWCursor\*q \*q" boolean \*q +Enable or disable the HW cursor. Default: HWCursor is on. +.TP +.BI "Option \*qSWCursor\*q \*q" boolean \*q +The opposite of HWCursor. Default: SWCursor is off. +.TP +.BI "Option \*qRotate\*q \*qCW\*q" +Rotate the display clockwise. This mode is unaccelerated, and uses +the Shadow Frame Buffer layer. +Default: no rotation. +.TP +.BI "Option \*qRotate\*q \*qCCW\*q" +Rotate the display counterclockwise. This mode is unaccelerated, and +uses the Shadow Frame Buffer layer. +Default: no rotation. +.TP +.BI "Option \*qShadowFB\*q \*q" boolean \*q +Enable or disable use of the shadow framebuffer layer. +Default: Shadow framebuffer is off. +.PP +.I "2. Old series specific information" +.PP +The driver will auto-detect the amount of video memory present for all +these chips, but in the 6326 case, it will limit the memory size to 4MB. +This is because the 6326's 2D engine can only address 4MB. The remaining +memory seems to be intended for 3D texture data, since only the 3D +engine can address RAM above 4MB. However, you can override this forced +limitation using the +.B \*qVideoRAM\*q +option in the device section if your board has more than +4MB and you need to use it. However, 2D acceleration, Xvideo and the +HWCursor will be disabled in this case. +.PP +The driver will also auto-detect the maximum dotclock and DAC speed. +If you have problems getting high resolutions because of dot clock +limitations, try using the +.B \*qDacSpeed\*q +option, also in the device section. However, this is not recommended +for the 6326. For this chipset, the driver has two built-in modes for +high resolutions which you should use instead. These are named +.B \*qSIS1280x1024-75\*q +and +.B \*qSIS1600x1200-60\*q +and they will be added to the list of default modes. To use these modes, +just place them in your Screen section. Example: +.PP +.BI "Modes \*qSIS1600x1200-60\*q \*qSIS1280x1024x75\*q \*q1024x768\*q ... +.PP +1280x1024 is only available at 8, 15 and 16bpp. 1600x1200 is available +at 8bpp only. +.PP +TV support for the 6326 +.PP +TV output is supported on the 6326. The driver will auto detect a +TV connected, and in this case add the following modes to the list +of default modes: "PAL800x600", "PAL800x600U", "PAL720x540", +"PAL640x480", "NTSC640x480", "NTSC640x480U" and "NTSC640x400". +Use these modes like the hi-res modes described above. +.PP +The following driver +.B Options +are supported on the old series: +.TP +.BI "Option \*qTurboQueue\*q \*q" boolean \*q +Enable or disable TurboQueue mode. Default: off for SIS530/620, on for +the others +.TP +.BI "Option \*qFastVram\*q \*q" boolean \*q +Enable or disable FastVram mode. Enabling this sets the video RAM timing +to only one cycle per read operation instead of two cycles. Disabling +this will set 2 cycles for read and write operations. Leaving this +option out uses the default. +Default: off for read, on for write. +.TP +.BI "Option \*qNoHostBus\*q \*q" boolean \*q +(SiS5597/5598 only). Disable CPU-to-VGA host bus support. This +speeds up CPU to video RAM transfers. Default: Host bus is enabled. +.TP +.BI "Option \*qNoXVideo\*q \*q" boolean \*q +Disable XV (XVideo) extension support. Default: XVideo is on. +.TP +.BI "Option \*qTVStandard\*q \*q" string \*q +(6326 only) Possible parameters are +.B PAL +or +.B NTSC. +The default is set by a jumper on the card. +.TP +.BI "Option \*qTVXPosOffset\*q \*q" integer \*q +(6326 only) This option allows horizontal relocation the TV output. +The range is from -16 to 16. +.TP +.BI "Option \*qTVYPosOffset\*q \*q" integer \*q +(6326 only) This option allows vertical relocation the TV output. +The range is from -16 to 16. +.TP +.BI "Option \*qSIS6326TVEnableYFilter\*q \*q" boolean \*q +(6326 only) This option allows enabling/disabling the Y filter for +TV output. +.TP +.BI "Option \*qSIS6326TVAntiFlicker\*q \*q" string \*q +(6326 only) This option allow enabling/disabling the anti flicker +facility for TV output. Possible parameters are +.B OFF, LOW, MED, HIGH +or +.B ADAPTIVE. +By experience, +.B ADAPTIVE +yields the best results. +.PP +.I "2. 300 and 310/325/330 series specific information" +.PP +The 300 and 310/325/330 series very often come with a video bridge for +controlling LCD and TV output. Hereinafter, the term +.B CRT1 +refers to the VGA output of the chip, and +.B CRT2 +refers to either LCD, TV or secondary VGA. Due to timing reasons, +only one CRT2 output can be active at the same time. But this +limitation does not apply to using CRT1 and CRT2 at the same time +which makes it possible to run the driver in dual head mode. +.PP +The driver supports the following video bridges: +.PP +.B SiS301 +.B SiS301B +.B SiS301LV +.B SiS302B +.B SiS302LV +.PP +Instead of a video bridge, some machines have a +.B LVDS +transmitter to control LCD panels, and a +.B "Chrontel 7005" +or +.B "7019" +for TV output. All these are supported as well. +.PP +About TV output +.PP +On the SiS301 and the Chrontel 7005, only resolutions up to 800x600 +are supported. On all others, resolutions up to 1024x768 are supported. +.PP +About XVideo support +.PP +XVideo is supported on all chipsets of both families. However, there +are some differences in hardware features which cause limitations. +The 300 series as well as the SiS550, 650M, 651 and 330 support two video +overlays. The SiS315/H/PRO and 650/740 support only one such overlay. +On chips with two overlays, one overlay is used for CRT1, the other +for CRT2. On the other chipsets, the option +.B \*qXvOnCRT2\*q +can be used to select the desired output channel. +.PP +About dual-head support +.PP +Dual head mode has some limitations as regards color depth and +resolution. Due to memory bandwidth limits, CRT1 might have a +reduced refresh rate if running on higher resolutions than +1280x1024. +.PP +Colordepth 8 is not supported when running in dual head mode. +.PP +The following driver +.B Options +are supported on the 300 and 310/325 series: +.TP +.BI "Option \*qNoXVideo\*q \*q" boolean \*q +Disable XV (XVideo) extension support. +Default: XVideo is on. +.TP +.BI "Option \*qXvOnCRT2\*q \*q" boolean \*q +On chipsets with only one video overlay, this option can +used to bind the overlay to CRT1 ( if a monitor is detected +and if this option is either unset or set to +.B false +) or CRT2 ( if a CRT2 device is detected or forced, and if this +option is set to +.B true +). If either only CRT1 or CRT2 is detected, the driver decides +automatically. +Default: overlay is used on CRT1 +.TP +.BI "Option \*qForceCRT1\*q \*q" boolean \*q +The BIOS detects VGA monitors connected to CRT1 at boot time +and the X driver by default relies on the information passed +by the BIOS. However, some old monitors are not detected +correctly. If this is the case, or if you connected the VGA +monitor after you booted the machine, you may set this +option to +.B true +in order to make the X driver ignore the +information from the BIOS and initialize CRT1 anyway. +If this option is set to +.B false +, the driver will switch +off CRT1 and thus save memory bandwidth. +Default: auto detect CRT1 +.TP +.BI "Option \*qForceCRT2Type\*q \*q" string \*q +Force display type to one of: +.B NONE +, +.B TV +, +.B SVIDEO +, +.B COMPOSITE +, +.B SCART, +, +.B LCD +, +.B VGA +; +.B NONE +will disable CRT2. The SVIDEO, COMPOSITE and SCART parameters +can be used to force the driver to use a specific TV output +connector (if present). +Default: auto detect. +.TP +.BI "Option \*qPanelDelayCompensation\*q \*q" integer \*q +This option is only for machines with a 300 series chipset +and either a SiS301B video bridge or a LVDS transmitter. +Different LCD panels require different delay compensation +values. In most cases, the driver can autodetect this value. +However, due to bad BIOS design this might fail in rare +cases. If your LCD shows small horizontal waves, set the +parameter of this option first to +.B 4 +, +.B 32 +or +.B 24 +and if the problem persists, try using other values between +4 and 60 in steps of 4. +.TP +.BI "Option \*qUseROMData\*q \*q" boolean \*q +The driver reads some data from the BIOS ROM, especially +LCD dependent information. If the folks at SiS some day +decide to change the location of this data inside the +BIOS image, the display might not be initialized correctly. +In order to prevent this, set this option's parameter to +.B false. +Default: ROM data is used +.TP +.BI "Option \*qTVStandard\*q \*q" string \*q +Force the TV standard to either +.B PAL +or +.B NTSC. +On some machines with 630, 730 or 650/740, +.B PALM +and +.B PALN +are supported as well. Default: BIOS setting. +.TP +.BI "Option \*qTVXPosOffset\*q \*q" integer \*q +This option allows horizontal relocation the TV output. +The range is from -32 to 32. Not supported on the Chrontel +7019 yet. +.TP +.BI "Option \*qTVYPosOffset\*q \*q" integer \*q +This option allows vertical relocation the TV output. +The range is from -32 to 32. Not supported on the Chrontel +7019 yet. +.TP +.BI "Option \*qCHTVOverscan\*q \*q" boolean \*q +On machines with a Chrontel TV encoder, this can be used to +force the TV mode to overscan or underscan. +.B True +means overscan, +.B false +means underscan. +Default: BIOS setting. +.TP +.BI "Option \*qCHTVSuperOverscan\*q \*q" boolean \*q +On machines with a Chrontel 7005 TV encoder, this option +enables a super-overscan mode. This is only supported if +the TV standard is PAL. Super overscan will produce an +image on the TV which is larger than the viewable area. +.PP +.I "3. 300 series specific information" +.PP +DRI is supported on the 300 series only. DRI requires +the kernel's SiS framebuffer driver ( +.B sisfb +) and some other modules +which come with either the kernel or XFree86. +.PP +Sisfb takes care of memory management for texture +data. In order to prevent the X driver and sisfb from +overwriting each others video memory, sisfb reserves +an amount of video memory for the X driver. This amount +can either be selected using sisfb's mem parameter, or +auto-selected depending on the amount of total video RAM +available. However, the X driver needs to know about the +amount of RAM sisfb reserved. For this purpose, the +.TP +.BI "Option \*qMaxXFBMem\*q \*q" integer \*q +.PP +exists. +.PP +At the moment (2002), the SiS DRI driver is not +maintained, lacks support for memory swapping and +has a few bugs. If you intend to use DRI, I recommend +setting the total video memory in the BIOS to 64MB +in order to at least overcome the lack of memory +swap functions. +.PP +Sisfb can be used for memory management only, or as +a complete framebuffer driver. If you start sisfb +with a valid mode (ie you gain a graphical console), +the X driver can communicate with sisfb and doesn't +require setting the +.B \*qMaxXFBMem\*q +option at all. The X driver will receive enough information +from sisfb in this case. +.PP +However, if you use sisfb for memory management only, ie +you started sisfb with mode=none and still have a text +mode console, there is no communication between sisfb +and the X driver. In this case, you need to set +.B \*qMaxXFBMem\*q +to the same value as you gave sisfb with its mem +parameter. If you didn't specify any mem parameter, +sisfb will reserve +.TP +12288KB if more than 16MB of total video RAM is available, +.TP +8192KB if between 12 and 16MB of video RAM is available, +.TP +4096KB in all other cases. +.PP +Then you need to specify any of these amounts as the +parameter for the +.B \*qMaxXFBMem\*q +option. The value is to be given without 'KB'. +.SH "KNOWN BUGS" +For some reason, PAL TV output on the SiS301LV bridge is +only black and white. NTSC is OK, though. +.PP +LCD panels with a resolution of 1280x1024 do not work +correctly. +.SH "SEE ALSO" +XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__) +.PP +.B "http://www.winischhofer.net" +for more information and updates +.SH AUTHORS +Authors include: Alan Hourihane, Mike Chapman, Juanjo Santamarta, Mitani +Hiroshi, David Thomas, Sung-Ching Lin, Ademar Reis, Thomas Winischhofer diff --git a/src/300vtbl.h b/src/300vtbl.h new file mode 100644 index 0000000..a6989da --- /dev/null +++ b/src/300vtbl.h @@ -0,0 +1,3314 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/300vtbl.h,v 1.6 2003/02/10 01:14:16 tsi Exp $ */ + + +/* Register settings for SiS 300 series */ + + +typedef struct _SiS300_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; +} SiS300_StStruct; + +static const SiS300_StStruct SiS300_SModeIDTable[] = +{ + {0x01,0x9208,0x01,0x00,0x00,0x00,0x00,0x00}, + {0x01,0x1210,0x14,0x01,0x01,0x00,0x00,0x00}, + {0x01,0x1010,0x17,0x02,0x02,0x00,0x00,0x00}, + {0x03,0x8208,0x03,0x00,0x00,0x00,0x00,0x00}, + {0x03,0x0210,0x16,0x01,0x01,0x00,0x00,0x00}, + {0x03,0x0010,0x18,0x02,0x02,0x00,0x00,0x00}, + {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x00}, + {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x00}, + {0x07,0x0000,0x07,0x03,0x03,0x00,0x00,0x00}, + {0x07,0x0000,0x19,0x02,0x02,0x00,0x00,0x00}, + {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x00}, + {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x00}, + {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x00}, + {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x00}, + {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x00}, + {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x00}, + {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x00}, + {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x00}, + {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x00}, + {0xff, 0, 0, 0, 0, 0, 0, 0} +}; + +typedef struct _SiS300_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]; +} SiS300_StandTableStruct; + +static const SiS300_StandTableStruct SiS300_StandTable[] = +{ + {0x28,0x18,0x08,0x0800, /* 0x00 */ + {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} }, + {0x28,0x18,0x08,0x0800, /* 0x01 */ + {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} }, + {0x50,0x18,0x08,0x1000, /* 0x02 */ + {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} }, + {0x50,0x18,0x08,0x1000, /* 0x03 */ + {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} }, + {0x28,0x18,0x08,0x4000, /* 0x04 */ + {0x09,0x03,0x00,0x02}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f, + 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} }, + {0x28,0x18,0x08,0x4000, /* 0x05 */ + {0x09,0x03,0x00,0x02}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f, + 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} }, + {0x50,0x18,0x08,0x4000, /* 0x06 */ + {0x01,0x01,0x00,0x06}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f, + 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} }, + {0x50,0x18,0x0e,0x1000, /* 0x07 */ + {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} }, +/* MDA_DAC*/ + {0x00,0x00,0x00,0x0000, /* 0x08 */ + {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} }, +/* CGA_DAC*/ + {0x00,0x10,0x04,0x0114, /* 0x09 */ + {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} }, +/* EGA_DAC*/ + {0x00,0x10,0x04,0x0114, /* 0x0a */ + {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} }, +/* VGA_DAC*/ + {0x00,0x10,0x04,0x0114, /* 0x0b */ + {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,0x0a08, /* 0x0c */ + {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} }, + {0x28,0x18,0x08,0x2000, /* 0x0d */ + {0x09,0x0f,0x00,0x06}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f, + 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} }, + {0x50,0x18,0x08,0x4000, /* 0x0e */ + {0x01,0x0f,0x00,0x06}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f, + 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} }, + {0x00,0x00,0x00,0x0000, /* 0x0f */ /* TW: Standtable for VGA modes */ + {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} }, + {0x4a,0x36,0x00,0x00c0, /* 0x10 */ + {0x00,0x00,0x00,0x00}, + 0x00, + {0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x3a, + 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1a,0x00,0x57,0x39,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} }, + {0x50,0x18,0x0e,0x8000, /* 0x11 */ + {0x01,0x0f,0x00,0x06}, + 0xa2, + {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x83,0x85,0x5d,0x28,0x0f,0x63,0xba,0xe3, + 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} }, + {0x50,0x18,0x0e,0x8000, /* 0x12 */ + {0x01,0x0f,0x00,0x06}, + 0xa3, + {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x83,0x85,0x5d,0x28,0x0f,0x63,0xba,0xe3, + 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} }, + {0x28,0x18,0x0e,0x0800, /* 0x13 */ + {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} }, + {0x28,0x18,0x0e,0x0800, /* 0x14 */ + {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} }, + {0x50,0x18,0x0e,0x1000, /* 0x15 */ + {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} }, + {0x50,0x18,0x0e,0x1000, /* 0x16 */ + {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} }, + {0x28,0x18,0x10,0x0800, /* 0x17 */ + {0x08,0x03,0x00,0x02}, + 0x67, + {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, + 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} }, + {0x50,0x18,0x10,0x1000, /* 0x18 */ + {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} }, + {0x50,0x18,0x10,0x1000, /* 0x19 */ + {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} }, + {0x50,0x1d,0x10,0xa000, /* 0x1a */ + {0x01,0x0f,0x00,0x06}, + 0xe3, + {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xea,0x8c,0xdf,0x28,0x00,0xe7,0x04,0xc3, + 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} }, + {0x50,0x1d,0x10,0xa000, /* 0x1b */ + {0x01,0x0f,0x00,0x06}, + 0xe3, + {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xea,0x8c,0xdf,0x28,0x00,0xe7,0x04,0xe3, + 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} }, + {0x28,0x18,0x08,0x2000, /* 0x1c */ + {0x01,0x0f,0x00,0x0e}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f, + 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} } +}; + +typedef struct _SiS300_ExtStruct +{ + UCHAR Ext_ModeID; + USHORT Ext_ModeFlag; + USHORT Ext_ModeInfo; + USHORT Ext_Point; + USHORT Ext_VESAID; + UCHAR Ext_VESAMEMSize; + UCHAR Ext_RESINFO; + UCHAR VB_ExtTVFlickerIndex; + UCHAR VB_ExtTVEdgeIndex; + UCHAR VB_ExtTVYFilterIndex; + UCHAR REFindex; +} SiS300_ExtStruct; + +static const SiS300_ExtStruct SiS300_EModeIDTable[] = +{ + {0x6a,0x2212,0x47,0x3563,0x0102,0x08,0x07,0x00,0x00,0x00,0x00}, /* 800x600x? */ + {0x2e,0x0a1b,0x36,0x3539,0x0101,0x08,0x06,0x00,0x00,0x00,0x08}, + {0x2f,0x021b,0x35,0x3532,0x0100,0x08,0x05,0x00,0x00,0x00,0x10}, /* 640x400x8 */ + {0x30,0x2a1b,0x47,0x3563,0x0103,0x08,0x07,0x00,0x00,0x00,0x00}, + {0x31,0x0a1b,0xad,0x3630,0x0000,0x08,0x0c,0x00,0x00,0x00,0x11}, /* 720x480x8 */ + {0x32,0x2a1b,0xae,0x3637,0x0000,0x08,0x0d,0x00,0x00,0x00,0x12}, /* 720x576x8 */ + {0x33,0x0a1d,0xad,0x3630,0x0000,0x08,0x0c,0x00,0x00,0x00,0x11}, /* 720x480x16 */ + {0x34,0x2a1d,0xae,0x3637,0x0000,0x08,0x0d,0x00,0x00,0x00,0x12}, /* 720x576x16 */ + {0x35,0x0a1f,0xad,0x3630,0x0000,0x08,0x0c,0x00,0x00,0x00,0x11}, /* 720x480x32 */ + {0x36,0x2a1f,0xae,0x3637,0x0000,0x08,0x0d,0x00,0x00,0x00,0x12}, /* 720x576x32 */ + {0x37,0x0212,0x58,0x358d,0x0104,0x08,0x08,0x00,0x00,0x00,0x13}, /* 1024x768x? */ + {0x38,0x0a1b,0x58,0x358d,0x0105,0x08,0x08,0x00,0x00,0x00,0x13}, /* 1024x768x8 */ + {0x3a,0x0e3b,0x69,0x35be,0x0107,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */ + {0x3c,0x063b,0x7a,0x35d4,0x0130,0x08,0x0a,0x00,0x00,0x00,0x1e}, + {0x3d,0x067d,0x7a,0x35d4,0x0131,0x08,0x0a,0x00,0x00,0x00,0x1e}, + {0x40,0x921c,0x00,0x3516,0x010d,0x08,0x00,0x00,0x00,0x00,0x23}, + {0x41,0x921d,0x00,0x3516,0x010e,0x08,0x00,0x00,0x00,0x00,0x23}, + {0x43,0x0a1c,0x36,0x3539,0x0110,0x08,0x06,0x00,0x00,0x00,0x08}, + {0x44,0x0a1d,0x36,0x3539,0x0111,0x08,0x06,0x00,0x00,0x00,0x08}, + {0x46,0x2a1c,0x47,0x3563,0x0113,0x08,0x07,0x00,0x00,0x00,0x00}, /* 800x600 */ + {0x47,0x2a1d,0x47,0x3563,0x0114,0x08,0x07,0x00,0x00,0x00,0x00}, /* 800x600 */ + {0x49,0x0a3c,0x58,0x358d,0x0116,0x08,0x08,0x00,0x00,0x00,0x13}, + {0x4a,0x0a3d,0x58,0x358d,0x0117,0x08,0x08,0x00,0x00,0x00,0x13}, + {0x4c,0x0e7c,0x69,0x35be,0x0119,0x08,0x09,0x00,0x00,0x00,0x1a}, + {0x4d,0x0e7d,0x69,0x35be,0x011a,0x08,0x09,0x00,0x00,0x00,0x1a}, + {0x50,0x921b,0x01,0x351d,0x0132,0x08,0x01,0x00,0x00,0x00,0x24}, + {0x51,0xb21b,0x13,0x3524,0x0133,0x08,0x03,0x00,0x00,0x00,0x25}, /* 400x300 */ + {0x52,0x921b,0x24,0x352b,0x0134,0x08,0x04,0x00,0x00,0x00,0x26}, + {0x56,0x921d,0x01,0x351d,0x0135,0x08,0x01,0x00,0x00,0x00,0x24}, + {0x57,0xb21d,0x13,0x3524,0x0136,0x08,0x03,0x00,0x00,0x00,0x25}, /* 400x300 */ + {0x58,0x921d,0x24,0x352b,0x0137,0x08,0x04,0x00,0x00,0x00,0x26}, + {0x59,0x921b,0x00,0x3516,0x0138,0x08,0x00,0x00,0x00,0x00,0x23}, + {0x5c,0x921f,0x24,0x352b,0x0000,0x08,0x04,0x00,0x00,0x00,0x26}, /* TW: inserted 512x384x32 */ + {0x5d,0x021d,0x35,0x3532,0x0139,0x08,0x05,0x00,0x00,0x00,0x10}, /* 640x400x16 */ + {0x5e,0x021f,0x35,0x3532,0x0000,0x08,0x05,0x00,0x00,0x00,0x10}, /* TW: inserted 640x400x32 */ + {0x62,0x0a3f,0x36,0x3539,0x013a,0x08,0x06,0x00,0x00,0x00,0x08}, + {0x63,0x2a3f,0x47,0x3563,0x013b,0x08,0x07,0x00,0x00,0x00,0x00}, /* 800x600 */ + {0x64,0x0a7f,0x58,0x358d,0x013c,0x08,0x08,0x00,0x00,0x00,0x13}, + {0x65,0x0eff,0x69,0x35be,0x013d,0x08,0x09,0x00,0x00,0x00,0x1a}, + {0x66,0x06ff,0x7a,0x35d4,0x013e,0x08,0x0a,0x00,0x00,0x00,0x1e}, + {0x68,0x067b,0x8b,0x35ef,0x013f,0x08,0x0b,0x00,0x00,0x00,0x27}, + {0x69,0x06fd,0x8b,0x35ef,0x0140,0x08,0x0b,0x00,0x00,0x00,0x27}, + {0x6b,0x07ff,0x8b,0x35ef,0x0000,0x10,0x0b,0x00,0x00,0x00,0x27}, + {0x6c,0x067b,0x9c,0x35f6,0x0000,0x08,0x11,0x00,0x00,0x00,0x28}, /* TW: 2048x1536x8 - not in BIOS! */ + {0x6d,0x06fd,0x9c,0x35f6,0x0000,0x10,0x11,0x00,0x00,0x00,0x28}, /* TW: 2048x1536x16 - not in BIOS! */ + {0x6e,0x0a3b,0x6f,0x35b2,0x0000,0x08,0x0e,0x00,0x00,0x00,0x29}, /* 1280x960x8 */ + {0x6f,0x0a7d,0x6f,0x35b2,0x0000,0x08,0x0e,0x00,0x00,0x00,0x29}, /* 1280x960x16 */ + /* TW: 16:9 modes copied from 310/325 series - not in ANY BIOS */ + {0x70,0x2a1b,0x40,0x3b52,0x0000,0x08,0x12,0x00,0x00,0x07,0x2d}, /* 800x480x8 */ + {0x71,0x0a1b,0x51,0x3b63,0x0000,0x08,0x13,0x00,0x00,0x00,0x30}, /* 1024x576x8 */ + {0x74,0x0a1d,0x51,0x3b63,0x0000,0x08,0x13,0x00,0x00,0x00,0x30}, /* 1024x576x16 */ + {0x75,0x0e3d,0x62,0x3b74,0x0000,0x08,0x14,0x00,0x00,0x00,0x33}, /* 1280x720x16 */ + {0x76,0x2a1f,0x40,0x3b52,0x0000,0x08,0x12,0x00,0x00,0x07,0x2d}, /* 800x480x32 */ + {0x77,0x0a3f,0x51,0x3b63,0x0000,0x08,0x13,0x00,0x00,0x00,0x30}, /* 1024x576x32 */ + {0x78,0x0eff,0x62,0x3b74,0x0000,0x08,0x14,0x00,0x00,0x00,0x33}, /* 1280x720x32 */ + {0x79,0x0e3b,0x62,0x3b74,0x0000,0x08,0x14,0x00,0x00,0x00,0x33}, /* 1280x720x8 */ + {0x7a,0x2a1d,0x40,0x3b52,0x0000,0x08,0x12,0x00,0x00,0x07,0x2d}, /* 800x480x16 */ + /* TW: End of new 16:9 modes */ + {0x7b,0x0aff,0x6f,0x35b2,0x0000,0x08,0x0e,0x00,0x00,0x00,0x29}, /* 1280x960x32 */ + {0x20,0x0a1b,0x54,0x0000,0x0000,0x08,0x0f,0x00,0x00,0x00,0x2b}, /* 1024x600 */ + {0x21,0x0a3d,0x54,0x0000,0x0000,0x08,0x0f,0x00,0x00,0x00,0x2b}, + {0x22,0x0a7f,0x54,0x0000,0x0000,0x08,0x0f,0x00,0x00,0x00,0x2b}, + {0x23,0x0a1b,0xc5,0x0000,0x0000,0x08,0x10,0x00,0x00,0x00,0x2c}, /* 1152x768 */ + {0x24,0x0a3d,0xc5,0x431d,0x0000,0x08,0x10,0x00,0x00,0x00,0x2c}, + {0x25,0x0a7f,0xc5,0x431d,0x0000,0x08,0x10,0x00,0x00,0x00,0x2c}, + {0x29,0x0e1b,0xc5,0x0000,0x0000,0x08,0x15,0x00,0x00,0x00,0x36}, /* TW: NEW 1152x864 - not in BIOS */ + {0x2a,0x0e3d,0xc5,0x0000,0x0000,0x08,0x15,0x00,0x00,0x00,0x36}, + {0x2b,0x0e7f,0xc5,0x0000,0x0000,0x08,0x15,0x00,0x00,0x00,0x36}, + {0x39,0x2a1b,0xd6,0x0000,0x0000,0x08,0x16,0x00,0x00,0x00,0x38}, /* TW: NEW 848x480 - not in BIOS */ + {0x3b,0x2a3d,0xd6,0x0000,0x0000,0x08,0x16,0x00,0x00,0x00,0x38}, + {0x3e,0x2a7f,0xd6,0x0000,0x0000,0x08,0x16,0x00,0x00,0x00,0x38}, + {0x3f,0x2a1b,0xd7,0x0000,0x0000,0x08,0x17,0x00,0x00,0x00,0x3a}, /* TW: NEW 856x480 - not in BIOS */ + {0x42,0x2a3d,0xd7,0x0000,0x0000,0x08,0x17,0x00,0x00,0x00,0x3a}, + {0x45,0x2a7f,0xd7,0x0000,0x0000,0x08,0x17,0x00,0x00,0x00,0x3a}, + {0x48,0x223b,0xe8,0x0000,0x0000,0x08,0x18,0x00,0x00,0x00,0x3c}, /* TW: NEW 1360x768 - not in BIOS */ + {0x4b,0x227d,0xe8,0x0000,0x0000,0x08,0x18,0x00,0x00,0x00,0x3c}, + {0x4e,0x22ff,0xe8,0x0000,0x0000,0x08,0x18,0x00,0x00,0x00,0x3c}, + {0xff,0x0000,0x00,0x0000,0xffff,0x00,0x00,0x00,0x00,0x00,0x00} +}; + +typedef struct _SiS300_Ext2Struct +{ + USHORT Ext_InfoFlag; + UCHAR Ext_CRT1CRTC; /* TW: Index in SiS300_CRT1Table */ + UCHAR Ext_CRTVCLK; /* TW: Index in VCLK array */ + UCHAR Ext_CRT2CRTC; /* TW: Index in LCD Paneltype arrays (&3f) */ + UCHAR ModeID; + USHORT XRes; + USHORT YRes; + USHORT ROM_OFFSET; +} SiS300_Ext2Struct; + +static const SiS300_Ext2Struct SiS300_RefIndex[] = +{ /* TW: Don't ever insert anything here, table is indexed */ + {0x085f,0x0d,0x03,0x05,0x6a, 800, 600,0x3563}, /* 00 */ + {0x0467,0x0e,0x44,0x05,0x6a, 800, 600,0x3568}, /* 01 */ + {0x0067,0x0f,0x07,0x48,0x6a, 800, 600,0x356d}, /* 02 - CRT1CRTC was 0x4f */ + {0x0067,0x10,0x06,0x8b,0x6a, 800, 600,0x3572}, /* 03 */ + {0x0147,0x11,0x08,0x00,0x6a, 800, 600,0x3577}, /* 04 */ + {0x0147,0x12,0x0c,0x00,0x6a, 800, 600,0x357c}, /* 05 */ + {0x0047,0x11,0x4e,0x00,0x6a, 800, 600,0x3581}, /* 06 - CRT1CRTC was 0x51 */ + {0x0047,0x11,0x13,0x00,0x6a, 800, 600,0x3586}, /* 07 */ + {0xc85f,0x05,0x00,0x04,0x2e, 640, 480,0x3539}, /* 08 */ + {0xc067,0x06,0x02,0x04,0x2e, 640, 480,0x353e}, /* 09 */ + {0xc067,0x07,0x02,0x47,0x2e, 640, 480,0x3543}, /* 0a */ + {0xc067,0x08,0x03,0x8a,0x2e, 640, 480,0x3548}, /* 0b */ + {0xc047,0x09,0x05,0x00,0x2e, 640, 480,0x354d}, /* 0c */ + {0xc047,0x0a,0x08,0x00,0x2e, 640, 480,0x3552}, /* 0d */ + {0xc047,0x0b,0x0a,0x00,0x2e, 640, 480,0x3557}, /* 0e */ + {0xc047,0x0c,0x10,0x00,0x2e, 640, 480,0x355c}, /* 0f */ + {0x487f,0x04,0x00,0x00,0x2f, 640, 400,0x3532}, /* 10 */ + {0xc00f,0x31,0x01,0x06,0x31, 720, 480,0x3630}, /* 11 */ + {0x000f,0x32,0x03,0x06,0x32, 720, 576,0x3637}, /* 12 */ + {0x0187,0x15,0x05,0x00,0x37,1024, 768,0x358d}, /* 13 */ + {0xc877,0x16,0x09,0x06,0x37,1024, 768,0x3592}, /* 14 */ + {0xc067,0x17,0x0b,0x49,0x37,1024, 768,0x3597}, /* 15 - CRT1CRTC was 0x97 */ + {0x0267,0x18,0x0d,0x00,0x37,1024, 768,0x359c}, /* 16 */ + {0x0047,0x19,0x11,0x8c,0x37,1024, 768,0x35a1}, /* 17 - CRT1CRTC was 0x59 */ + {0x0047,0x1a,0x52,0x00,0x37,1024, 768,0x35a6}, /* 18 */ + {0x0047,0x1b,0x16,0x00,0x37,1024, 768,0x35ab}, /* 19 - CRT1CRTC was 0x5b */ + {0x0387,0x1c,0x4d,0x00,0x3a,1280,1024,0x35be}, /* 1a - CRT1CRTC was 0x5c */ + {0x0077,0x1d,0x14,0x07,0x3a,1280,1024,0x35c3}, /* 1b */ + {0x0047,0x1e,0x17,0x00,0x3a,1280,1024,0x35c8}, /* 1c */ + {0x0007,0x1f,0x98,0x00,0x3a,1280,1024,0x35cd}, /* 1d */ + {0x0007,0x20,0x59,0x00,0x3c,1600,1200,0x35d4}, /* 1e - CRT1CRTC was 0x60 */ + {0x0007,0x21,0x5a,0x00,0x3c,1600,1200,0x35d9}, /* 1f */ + {0x0007,0x22,0x1b,0x00,0x3c,1600,1200,0x35de}, /* 20 */ + {0x0007,0x23,0x1d,0x00,0x3c,1600,1200,0x35e3}, /* 21 - CRT1CRTC was 0x63 */ + {0x0007,0x24,0x1e,0x00,0x3c,1600,1200,0x35e8}, /* 22 */ + {0x407f,0x00,0x00,0x00,0x40, 320, 200,0x3516}, /* 23 */ + {0xc07f,0x01,0x00,0x04,0x50, 320, 240,0x351d}, /* 24 */ + {0x0077,0x02,0x04,0x05,0x51, 400, 300,0x3524}, /* 25 */ + {0xc877,0x03,0x09,0x06,0x52, 512, 384,0x352b}, /* 26 */ /* was c077 */ + {0x8207,0x25,0x1f,0x00,0x68,1920,1440,0x35ef}, /* 27 */ + {0x0007,0x26,0x20,0x00,0x6c,2048,1536,0x35f6}, /* 28 */ + {0x0027,0x27,0x14,0x08,0x6e,1280, 960,0x35b7}, /* 29 - TW: 1280x960-60 */ + {0x0047,0x45,0x3c,0x08,0x6e,1280, 960,0x35b7}, /* 2a - TW: 1280x960-85 */ + {0xc077,0x33,0x09,0x06,0x20,1024, 600,0x0000}, /* 2b */ + {0xc077,0x34,0x0b,0x06,0x23,1152, 768,0x0000}, /* 2c */ /* VCLK 0x09 */ + {0x0057,0x35,0x27,0x08,0x70, 800, 480,0x3b52}, /* 2d - TW: 16:9 modes */ + {0x0047,0x36,0x37,0x08,0x70, 800, 480,0x3b57}, /* 2e */ + {0x0047,0x37,0x08,0x08,0x70, 800, 480,0x3b5c}, /* 2f */ + {0x0057,0x38,0x09,0x09,0x71,1024, 576,0x3b63}, /* 30 */ + {0x0047,0x39,0x38,0x09,0x71,1024, 576,0x3b68}, /* 31 */ + {0x0047,0x3a,0x11,0x09,0x71,1024, 576,0x3b6d}, /* 32 */ + {0x0057,0x3b,0x39,0x0a,0x75,1280, 720,0x3b74}, /* 33 */ + {0x0047,0x3c,0x3a,0x0a,0x75,1280, 720,0x3b79}, /* 34 */ + {0x0047,0x3d,0x3b,0x0a,0x75,1280, 720,0x3b7e}, /* 35 - TW: END of 16:9 modes */ + {0x0047,0x3e,0x34,0x06,0x29,1152, 864,0x0000}, /* 36 TW: 1152x864-75Hz - Non-BIOS, new */ + {0x0047,0x44,0x3a,0x06,0x29,1152, 864,0x0000}, /* 37 TW: 1152x864-85Hz - Non-BIOS, new */ + {0x00c7,0x3f,0x28,0x00,0x39, 848, 480,0x0000}, /* 38 TW: 848x480-38Hzi - Non-BIOS, new */ + {0xc047,0x40,0x3d,0x00,0x39, 848, 480,0x0000}, /* 39 TW: 848x480-60Hz - Non-BIOS, new */ + {0x00c7,0x41,0x28,0x00,0x3f, 856, 480,0x0000}, /* 3a TW: 856x480-38Hzi - Non-BIOS, new */ + {0xc047,0x42,0x28,0x00,0x3f, 856, 480,0x0000}, /* 3b TW: 856x480-60Hz - Non-BIOS, new */ + {0x0047,0x43,0x3e,0x00,0x48,1360, 768,0x0000}, /* 3c TW: 1360x768-60Hz - Non-BIOS, new */ + {0xffff,0,0,0,0,0,0,0} +}; + +/*add for 300 oem util*/ +typedef struct _SiS_VBModeIDTableStruct +{ + UCHAR ModeID; + UCHAR VB_TVDelayIndex; + UCHAR VB_TVFlickerIndex; + UCHAR VB_TVPhaseIndex; + UCHAR VB_TVYFilterIndex; + UCHAR VB_LCDDelayIndex; + UCHAR _VB_LCDHIndex; + UCHAR _VB_LCDVIndex; +}SiS_VBModeIDTableStruct; + +static const SiS_VBModeIDTableStruct 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}, + {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}, + {0x50,0x00,0x00,0x01,0x04,0x00,0x05,0x07}, + {0x51,0x00,0x00,0x01,0x07,0x00,0x07,0x09}, + {0x52,0x00,0x00,0x01,0x00,0x00,0x09,0x0b}, + {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}, + {0x5d,0x00,0x00,0x01,0x07,0x00,0x06,0x06}, + {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}, + {0x6e,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, + {0x6f,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, + {0x7b,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d}, + {0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00} /* TW: added! */ +}; +/*end*/ + +typedef struct _SiS300_CRT1TableStruct +{ + UCHAR CR[17]; +} SiS300_CRT1TableStruct; + +static const SiS300_CRT1TableStruct SiS300_CRT1Table[] = +{ + {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 0x00 */ + 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00, + 0x00}}, + {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, + 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, + 0x00}}, + {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, + 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05, + 0x01}}, + {{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, /* TW: 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}}, +#if 0 + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, /* 0x34 - 1152x768 */ + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, + 0x01}}, +#endif + {{0xa3,0x8f,0x8f,0x97,0x96,0x97,0x24,0xf5, /* 0x34 - 1152x768 - TW: corrected */ + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, + 0x01}}, + {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba, /* 0x35 - NEW 16:9 modes, not in BIOS ------ */ + 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, /* TW: 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 */ /* TW: End of 16:9 modes --------------- */ + {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* TW: New, 1152x864-75 (not in any BIOS) */ + 0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07, + 0x01}}, /* 0x3e */ + {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* TW: New, 848x480-38i, not in BIOS */ + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, + 0x00}}, /* 0x3f */ +#if 0 + {{0x81,0x69,0x69,0x85,0x70,0x00,0x0F,0x3E, /* TW: New, 848x480-60, not in BIOS - incorrect for Philips panel */ + 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02, + 0x00}}, /* 0x40 */ +#endif + {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* TW: New, 848x480-60, not in BIOS */ + 0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06, + 0x00}}, /* 0x40 */ + {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* TW: New, 856x480-38i, not in BIOS */ + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, + 0x00}}, /* 0x41 */ + {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* TW: New, 856x480-60, not in BIOS */ + 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02, + 0x00}}, /* 0x42 */ + {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* TW: New, 1360x768-60, not in BIOS */ + 0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03, + 0x01}}, /* 0x43 */ + {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* TW: New, 1152x864-84 (not in any BIOS) */ + 0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03, + 0x01}}, /* 0x44 */ + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* TW: New, 1280x960-85 (not in any BIOS) */ + 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07, + 0x01}} /* 0x45 */ +}; + +typedef struct _SiS300_MCLKDataStruct +{ + UCHAR SR28,SR29,SR2A; + USHORT CLOCK; +} SiS300_MCLKDataStruct; + +static const SiS300_MCLKDataStruct SiS300_MCLKData_630[] = /* 630 */ +{ /* TW: at 0x54 in BIOS */ + { 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 SiS300_MCLKDataStruct SiS300_MCLKData_300[] = /* 300 */ +{ /* TW: at 0x54 in BIOS */ + { 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} +}; + +typedef struct _SiS300_ECLKDataStruct +{ + UCHAR SR2E,SR2F,SR30; + USHORT CLOCK; +} SiS300_ECLKDataStruct; + +static const SiS300_ECLKDataStruct SiS300_ECLKData[] = +{ + { 0x54,0x43,0x80,100}, + { 0x53,0x43,0x80,100}, + { 0x55,0x43,0x80,100}, + { 0x52,0x43,0x80,100}, + { 0x3f,0x42,0x80,100}, + { 0x54,0x43,0x80,100}, + { 0x54,0x43,0x80,100}, + { 0x54,0x43,0x80,100} +}; + +typedef struct _SiS300_VCLKDataStruct +{ + UCHAR SR2B,SR2C; + USHORT CLOCK; +} SiS300_VCLKDataStruct; + +static const SiS300_VCLKDataStruct SiS300_VCLKData[] = +{ + { 0x1b,0xe1, 25}, /* 0x00 */ + { 0x4e,0xe4, 28}, + { 0x57,0xe4, 32}, /* 0x02 */ + { 0xc3,0xc8, 36}, + { 0x42,0xc3, 40}, /* 0x04 */ + { 0x5d,0xc4, 45}, + { 0x52,0x65, 50}, /* 0x06 */ + { 0x53,0x65, 50}, + { 0x6d,0x66, 56}, /* 0x08 */ + { 0x5a,0x64, 65}, + { 0x46,0x44, 68}, /* 0x0a */ + { 0x3e,0x43, 75}, + { 0x6d,0x46, 76}, /* 0x0c: 800x600 | LVDS_2(CH), MITAC(CH); - 730, A901(301B): 0xb1,0x46, 76 */ + { 0x41,0x43, 79}, + { 0x31,0x42, 79}, /* 0x0e */ + { 0x46,0x25, 85}, + { 0x78,0x29, 87}, /* 0x10 */ + { 0x62,0x44, 95}, + { 0x2b,0x22,105}, /* 0x12 */ + { 0x49,0x24,106}, + { 0xc3,0x28,108}, /* 0x14 */ + { 0x3c,0x23,109}, + { 0xf7,0x2c,132}, /* 0x16 */ + { 0xd4,0x28,136}, + { 0x41,0x05,158}, /* 0x18 */ + { 0x43,0x05,162}, + { 0xe1,0x0f,175}, /* 0x1a */ + { 0xfc,0x12,189}, /* 0x1b */ + { 0xde,0x26,194}, /* 0x1c */ + { 0x54,0x05,203}, + { 0x3f,0x03,230}, /* 0x1e */ + { 0x30,0x02,234}, + { 0x24,0x01,266}, /* 0x20 */ + { 0x52,0x2a, 54}, /* 301 TV */ + { 0x52,0x6a, 27}, /* 301 TV */ + { 0x62,0x24, 70}, /* 301 TV */ + { 0x62,0x64, 70}, /* 301 TV */ + { 0xa8,0x4c, 30}, /* 301 TV */ + { 0x20,0x26, 33}, /* 301 TV */ + { 0x31,0xc2, 39}, + { 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}, + { 0x9f,0x46, 44}, + { 0x97,0x2c, 26}, + { 0x44,0xe4, 25}, + { 0x7e,0x32, 47}, + { 0x8a,0x24, 31}, /* 0x2f CH/PAL TEXT | LVDS_2(CH), Mitac(CH) - 730, A901(301B): 0x57, 0xe4, 31 */ + { 0x97,0x2c, 26}, + { 0xce,0x3c, 39}, + { 0x52,0x4a, 36}, /* 0x32 CH/PAL 800x600 5/6 */ + { 0x34,0x61, 95}, + { 0x78,0x27,108}, + { 0xce,0x25,189}, /* 0x35 */ + { 0x45,0x6b, 21}, /* 0x36 */ /* TW: Added from Mitac */ + { 0x52,0xe2, 49}, /* 0x37 - added for 16:9 modes (not in any BIOS) */ + { 0x2b,0x61, 78}, /* 0x38 - added for 16:9 modes (not in any BIOS) */ + { 0x70,0x44,108}, /* 0x39 - added for 16:9 modes (not in any BIOS) */ + { 0x54,0x42,135}, /* 0x3a - added for 16:9 modes (not in any BIOS) */ + { 0x41,0x22,157}, /* 0x3b - added for 16:9 modes (not in any BIOS) */ + { 0x52,0x07,149}, /* 0x3c - added for 1280x960-85 (not in any BIOS)*/ + { 0x62,0xc6, 34}, /* 0x3d - added for 848x480-60 (not in any BIOS) */ + { 0x30,0x23, 88}, /* 0x3e - added for 1360x768-60 (not in any BIOS)*/ + { 0x3f,0x64, 46}, /* 0x3f - added for 640x480-100 (not in any BIOS)*/ + { 0x72,0x2a, 76}, /* 0x40 - test for SiS730 */ + { 0x15,0x21, 79}, /* 0x41 - test for SiS730 */ + { 0xff,0x00, 0} +}; + +#if 0 /* TW: This table is in all BIOSes, but not used */ +static const SiS300_VCLKDataStruct SiS300_VBVCLKData[] = +{ + { 0x1b,0xe1, 25}, + { 0x4e,0xe4, 28}, + { 0x57,0xe4, 31}, + { 0xc3,0xc8, 36}, + { 0x42,0x47, 40}, + { 0x5d,0xc4, 44}, + { 0x52,0x47, 49}, + { 0x53,0x47, 50}, + { 0x6d,0x66, 56}, + { 0x5a,0x64, 65}, + { 0x46,0x44, 67}, + { 0x29,0x61, 75}, + { 0x6d,0x46, 75}, + { 0x41,0x43, 78}, + { 0x31,0x42, 79}, + { 0x46,0x25, 84}, + { 0x78,0x29, 86}, /* 0x10 */ + { 0x62,0x44, 94}, + { 0x2b,0x22,104}, + { 0x49,0x24,105}, + { 0x43,0x42,108}, + { 0x3c,0x23,109}, + { 0xe0,0x46,132}, + { 0x70,0x25,135}, + { 0x41,0x22,157}, + { 0x43,0x22,162}, + { 0x30,0x21,175}, + { 0xc1,0x24,189}, + { 0xde,0x26,194}, + { 0x70,0x07,202}, + { 0x3f,0x03,229}, + { 0x30,0x02,234}, /* 0x1f */ + { 0x24,0x01,265}, /* 0x20 */ + { 0x52,0x2a, 54}, + { 0x52,0x6a, 27}, + { 0x62,0x24, 70}, + { 0x62,0x64, 70}, + { 0xa8,0x4c, 30}, + { 0x20,0x26, 33}, + { 0x31,0xc2, 39}, + { 0x2e,0x48, 25}, /* 0x28 */ + { 0x24,0x46, 25}, /* 0x29 */ + { 0x26,0x64, 28}, + { 0x37,0x64, 40}, + { 0xa1,0x42,108}, + { 0x37,0x61,100}, + { 0x78,0x27,108}, + { 0xff,0x00, 0} +}; +#endif + +static const UCHAR SiS300_ScreenOffset[] = +{ + 0x14,0x19,0x20,0x28,0x32,0x40,0x50, + 0x64,0x78,0x80,0x2d,0x35,0x48,0x35, /* 0x35 for 848 and 856 */ + 0x55,0xff /* 0x55 for 1360 */ +}; + +typedef struct _SiS300_StResInfoStruct +{ + USHORT HTotal; + USHORT VTotal; +} SiS300_StResInfoStruct; + +static const SiS300_StResInfoStruct SiS300_StResInfo[] = +{ + { 640,400}, + { 640,350}, + { 720,400}, + { 720,350}, + { 640,480} +}; + +typedef struct _SiS300_ModeResInfoStruct +{ + USHORT HTotal; + USHORT VTotal; + UCHAR XChar; + UCHAR YChar; +} SiS300_ModeResInfoStruct; + +static const SiS300_ModeResInfoStruct SiS300_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 */ + { 720, 480, 8,16}, /* 0x0c */ + { 720, 576, 8,16}, /* 0x0d */ + { 1280, 960, 8,16}, /* 0x0e */ + { 1024, 600, 8,16}, /* 0x0f */ + { 1152, 768, 8,16}, /* 0x10 */ + { 2048,1536, 8,16}, /* 0x11 - TW: Not in BIOS! */ + { 800, 480, 8,16}, /* 0x12 - TW: New, not in any BIOS */ + { 1024, 576, 8,16}, /* 0x13 - TW: New, not in any BIOS */ + { 1280, 720, 8,16}, /* 0x14 - TW: New, not in any BIOS */ + { 1152, 864, 8,16}, /* 0x15 - TW: New, not in any BIOS */ + { 848, 480, 8,16}, /* 0x16 - TW: New, not in any BIOS */ + { 856, 480, 8,16}, /* 0x17 - TW: New, not in any BIOS */ + { 1360, 768, 8,16} /* 0x18 - TW: New, not in any BIOS */ +}; + +static const UCHAR SiS300_OutputSelect = 0x40; + +static const UCHAR SiS300_SoftSetting = 0x30; + +#ifndef LINUX_XF86 +static UCHAR SiS300_SR07 = 0x10; +#endif + +static const UCHAR SiS300_SR15[8][4] = +{ + {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} +}; + +#ifndef LINUX_XF86 +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; /*301b*/ +static const USHORT SiS300_VideoSenseData2 = 0x0174; +static const USHORT SiS300_YCSenseData2 = 0x016b; + +static const UCHAR SiS300_CR40[5][4]; + +static UCHAR SiS300_CR49[2]; +#endif + +static const UCHAR SiS300_NTSCPhase[] = {0x21,0xed,0xba,0x08}; /* TW: Was {0x21,0xed,0x8a,0x08}; */ +static const UCHAR SiS300_PALPhase[] = {0x2a,0x05,0xe3,0x00}; /* TW: Was {0x2a,0x05,0xd3,0x00}; */ +static const UCHAR SiS300_PALMPhase[] = {0x21,0xE4,0x2E,0x9B}; /* palmn */ +static const UCHAR SiS300_PALNPhase[] = {0x21,0xF4,0x3E,0xBA}; +static const UCHAR SiS300_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6}; /* 301b */ +static const UCHAR SiS300_PALPhase2[] = {0x2a,0x09,0x86,0xe9}; /* 301b */ +static const UCHAR SiS300_PALMPhase2[] = {0x21,0xE6,0xEF,0xA4}; /* TW: palm 301b*/ +static const UCHAR SiS300_PALNPhase2[] = {0x21,0xF6,0x94,0x46}; /* TW: paln 301b*/ + +typedef struct _SiS300_PanelDelayTblStruct +{ + UCHAR timer[2]; +} SiS300_PanelDelayTblStruct; + +static const SiS300_PanelDelayTblStruct SiS300_PanelDelayTbl[] = +{ + {{0x05,0xaa}}, /* TW: From 2.04.5a */ + {{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}} +}; + +static const SiS300_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}} +}; + +typedef struct _SiS300_LCDDataStruct +{ + USHORT RVBHCMAX; + USHORT RVBHCFACT; + USHORT VGAHT; + USHORT VGAVT; + USHORT LCDHT; + USHORT LCDVT; +} SiS300_LCDDataStruct; + +static const SiS300_LCDDataStruct SiS300_StLCD1024x768Data[] = +{ + { 66, 31, 992, 510,1320, 816}, + { 66, 31, 992, 510,1320, 816}, + { 176, 75, 900, 510,1320, 816}, + { 176, 75, 900, 510,1320, 816}, + { 66, 31, 992, 510,1320, 816}, + { 27, 16,1024, 650,1350, 832}, + { 1, 1,1344, 806,1344, 806} +}; + +static const SiS300_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 SiS300_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 SiS300_LCDDataStruct SiS300_StLCD1280x1024Data[] = +{ + { 4, 1, 880, 510,1650,1088}, + { 4, 1, 880, 510,1650,1088}, + { 176, 45, 900, 510,1650,1088}, + { 176, 45, 900, 510,1650,1088}, + { 4, 1, 880, 510,1650,1088}, + { 13, 5,1024, 675,1560,1152}, + { 16, 9,1266, 804,1688,1072}, + { 1, 1,1688,1066,1688,1066} +}; + +static const SiS300_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 SiS300_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 SiS300_LCDDataStruct SiS300_NoScaleData1024x768[] = +{ + { 1, 1, 800, 449, 800, 449}, + { 1, 1, 800, 449, 800, 449}, + { 1, 1, 900, 449, 900, 449}, + { 1, 1, 900, 449, 900, 449}, + { 1, 1, 800, 525, 800, 525}, + { 1, 1,1056, 628,1056, 628}, + { 1, 1,1344, 806,1344, 806}, + { 1, 1,1688,1066,1688,1066} +}; + +static const SiS300_LCDDataStruct SiS300_NoScaleData1280x1024[] = /* TW: Fake */ +{ + { 1, 1, 800, 449, 800, 449}, + { 1, 1, 800, 449, 800, 449}, + { 1, 1, 900, 449, 900, 449}, + { 1, 1, 900, 449, 900, 449}, + { 1, 1, 800, 525, 800, 525}, + { 1, 1,1056, 628,1056, 628}, + { 1, 1,1344, 806,1344, 806}, + { 1, 1,1688,1066,1688,1066} +}; + +static const SiS300_LCDDataStruct SiS300_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 SiS300_LCDDataStruct SiS300_ExtLCD1400x1050Data[] = /* TW: New */ +{ + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0} +}; + +static const SiS300_LCDDataStruct SiS300_ExtLCD1600x1200Data[] = /* TW: New */ +{ + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0} +}; + +static const SiS300_LCDDataStruct SiS300_StLCD1400x1050Data[] = /* TW: New */ +{ + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0} +}; + +static const SiS300_LCDDataStruct SiS300_StLCD1600x1200Data[] = /* TW: New */ +{ + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0} +}; + +static const SiS300_LCDDataStruct SiS300_NoScaleData1400x1050[] = /* TW: New */ +{ + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0} +}; + +static const SiS300_LCDDataStruct SiS300_NoScaleData1600x1200[] = /* TW: New */ +{ + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0} +}; + + +typedef struct _SiS300_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; +} SiS300_TVDataStruct; + +static const SiS300_TVDataStruct SiS300_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 SiS300_TVDataStruct SiS300_ExtPALData[] = +{ + { 27, 10, 848, 448,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22}, + { 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}, + { 36, 25,1060, 648,1316, 530, 438, 0, 438,0xeb,0x05,0x25,0x16}, + { 3, 2,1080, 619,1270, 540, 438, 0, 438,0xf3,0x00,0x1d,0x20}, + { 1, 1,1170, 821,1270, 520, 686, 0, 686,0xF3,0x00,0x1D,0x20} + +}; + +static const SiS300_TVDataStruct SiS300_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 SiS300_TVDataStruct SiS300_ExtNTSCData[] = +{ + { 143, 65, 858, 443,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18}, + { 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}, + { 143, 120,1056, 643,1270, 440, 0, 128, 0,0xf4,0x10,0x1c,0x00}, + { 143, 76, 836, 523,1270, 440, 0, 128, 0,0xee,0x0c,0x22,0x08}, + { 65, 64,1056, 791,1270, 480, 638, 0, 0,0xf1,0x04,0x1f,0x18} +}; + +static const SiS_TVDataStruct SiS300_St1HiTVData[] = +{ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} +}; + +static const SiS_TVDataStruct SiS300_St2HiTVData[] = +{ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} +}; + +static const SiS_TVDataStruct SiS300_ExtHiTVData[] = +{ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} +}; + +static const UCHAR SiS300_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, /* (in 2.06.50) */ +/* 0x0c,0x50,0x00,0x99,0x00,0xec,0x4a,0x17, (in 2.04.5a) */ + 0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02, /* (in 2.06.50) */ +/* 0x88,0x00,0x4b,0x00,0x00,0xe2,0x00,0x02, (in 2.04.5a) */ + 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 SiS300_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, /* (in 2.06.50) */ +/* 0x70,0x50,0x00,0x97,0x00,0xd7,0x5d,0x17, (in 2.04.5a) */ + 0x7d,0x05,0x45,0x00,0x00,0xe8,0x00,0x02, /* (in 2.06.50) */ +/* 0x88,0x00,0x45,0x00,0x00,0xe8,0x00,0x02, (in 2.04.5a) */ + 0x0d,0x00,0x68,0xb0,0x0b,0x92,0x8f,0x40, + 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63, + 0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00 +}; + +#ifdef oldHV +static const UCHAR SiS300_HiTVExtTiming[] = /* TW: New */ +{ + 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 SiS300_HiTVSt1Timing[] = /* TW: New */ +{ + 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 SiS300_HiTVSt2Timing[] = /* TW: New */ +{ + 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 SiS300_HiTVTextTiming[] = /* TW: New */ +{ + 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 +}; + +static const UCHAR SiS300_HiTVGroup3Data[] = /* TW: New */ +{ + 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 SiS300_HiTVGroup3Simu[] = /* TW: New */ +{ + 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 +}; + +static const UCHAR SiS300_HiTVGroup3Text[] = /* TW: New */ +{ + 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 + +typedef struct _SiS300_LVDSDataStruct +{ + USHORT VGAHT; + USHORT VGAVT; + USHORT LCDHT; + USHORT LCDVT; +} SiS300_LVDSDataStruct; + +static const SiS300_LVDSDataStruct SiS300_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 SiS300_LVDSDataStruct SiS300_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}, + {800, 449,1000, 644}, + {800, 525,1000, 635} +}; + +static const SiS300_LVDSDataStruct SiS300_LVDS800x600Data_2[] = +{ + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {800, 449,1000, 644}, + {800, 525,1000, 635} +}; + +static const SiS300_LVDSDataStruct SiS300_LVDS1024x768Data_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 SiS300_LVDSDataStruct SiS300_LVDS1024x768Data_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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +static const SiS300_LVDSDataStruct SiS300_LVDS1280x1024Data_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 SiS300_LVDSDataStruct SiS300_LVDS1280x1024Data_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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +static const SiS300_LVDSDataStruct SiS300_LVDS1400x1050Data_1[] = /* TW: New */ +{ + {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 SiS300_LVDSDataStruct SiS300_LVDS1400x1050Data_2[] = /* TW: New */ +{ + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, +}; + +static const SiS300_LVDSDataStruct SiS300_LVDS1280x768Data_1[]= /* TW: New - TODO */ +{ /* TW: Temp data, invalid (is identical to 1024x768) */ + {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 SiS300_LVDSDataStruct SiS300_LVDS1280x768Data_2[]= /* TW: New - TODO */ +{ /* TW: Temp data, invalid (is identical to 1024x768) */ + {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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +/* TW: New: */ +static const SiS300_LVDSDataStruct SiS300_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}, + {800, 449,1280, 789}, + {800, 525,1280, 785} +}; + +/* TW: New: */ +static const SiS300_LVDSDataStruct SiS300_LVDS1024x600Data_2[] = +{ + {1344, 800,1344, 800}, + {1344, 800,1344, 800}, + {1344, 800,1344, 800}, + {1344, 800,1344, 800}, + {1344, 800,1344, 800}, + {1344, 800,1344, 800}, + {1344, 800,1344, 800}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +/* TW: New: */ +static const SiS300_LVDSDataStruct SiS300_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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +/* TW: New: */ +static const SiS300_LVDSDataStruct SiS300_LVDS1152x768Data_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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +/* TW: New in 650/LVDS BIOS - 1:1 */ +static const SiS300_LVDSDataStruct SiS300_LVDSXXXxXXXData_1[] = /* TW: New */ +{ + { 800, 449, 800, 449}, + { 800, 449, 800, 449}, + { 900, 449, 900, 449}, + { 900, 449, 900, 449}, + { 800, 525, 800, 525}, + {1056, 628,1056, 628}, + {1344, 806,1344, 806}, + {1688, 806,1688, 806} +}; + +static const SiS300_LVDSDataStruct SiS300_LVDS640x480Data_1[] = +{ + {800, 449, 800, 449}, + {800, 449, 800, 449}, + {800, 449, 800, 449}, + {800, 449, 800, 449}, + {800, 525, 800, 525}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628} +}; + +static const SiS300_LVDSDataStruct SiS300_LVDS1280x960Data_1[] = /* TW: New */ +{ + {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 SiS300_LVDSDataStruct SiS300_LVDS1280x960Data_2[] = /* TW: New */ +{ + {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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +static const SiS300_LVDSDataStruct SiS300_LCDA1400x1050Data_1[] = /* TW: New */ +{ /* TW: Might be temporary (invalid) data */ + {928, 416, 1688, 1066}, + {928, 366, 1688, 1066}, + {1008, 416, 1688, 1066}, + {1008, 366, 1688, 1066}, + {1200, 530, 1688, 1066}, + {1088, 616, 1688, 1066}, + {1312, 784, 1688, 1066}, + {1568, 1040, 1688, 1066}, + {1688, 1066, 1688, 1066} +}; + +static const SiS300_LVDSDataStruct SiS300_LCDA1400x1050Data_2[] = /* TW: New */ +{ /* TW: Temporary data. Not valid */ + {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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +static const SiS300_LVDSDataStruct SiS300_LCDA1600x1200Data_1[] = /* TW: New */ +{ /* TW: Temporary data. Not valid */ + {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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +static const SiS300_LVDSDataStruct SiS300_LCDA1600x1200Data_2[] = /* TW: New */ +{ /* TW: Temporary data. Not valid */ + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0} +}; + + +/* TW: New: */ +static const SiS300_LVDSDataStruct SiS300_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} +}; + +static const SiS300_LVDSDataStruct SiS300_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} +}; + +static const SiS300_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 SiS300_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 SiS300_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} +}; + +/* TW: new end */ + +typedef struct _SiS300_LVDSDesStruct +{ + USHORT LCDHDES; + USHORT LCDVDES; +} SiS300_LVDSDesStruct; + +static const SiS300_LVDSDesStruct SiS300_PanelType00_1[] = +{ + {0, 626}, + {0, 624}, + {0, 626}, + {0, 624}, + {0, 624}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType01_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType02_1[] = +{ + {0, 626}, + {0, 624}, + {0, 626}, + {0, 624}, + {0, 624}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType03_1[] = +{ + { 8, 436}, + { 8, 440}, + { 8, 436}, + { 8, 440}, + { 8, 512}, + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType04_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType05_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType06_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType07_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType08_1[] = +{ + {1059, 626}, + {1059, 624}, + {1059, 626}, + {1059, 624}, + {1059, 624}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType09_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType0a_1[] = +{ + {1059, 626}, + {1059, 624}, + {1059, 626}, + {1059, 624}, + {1059, 624}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType0b_1[] = +{ + {1343, 0}, + {1343, 0}, + {1343, 0}, + {1343, 0}, + {1343, 0}, /* 640x480 - BIOS 1343, 0 */ + {1343, 0}, + { 0, 799}, + { 0, 0}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType0c_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType0d_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_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 SiS300_LVDSDesStruct SiS300_PanelType0f_1[] = +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType00_2[] = +{ + {976, 527}, + {976, 502}, + {976, 527}, + {976, 502}, + {976, 567}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType01_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType02_2[] = +{ + {976, 527}, + {976, 502}, + {976, 527}, + {976, 502}, + {976, 567}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType03_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + {1152, 622}, + {1152, 597} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType04_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType05_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType06_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType07_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType08_2[] = +{ + {976, 527}, + {976, 502}, + {976, 527}, + {976, 502}, + {976, 567}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType09_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType0a_2[] = +{ + {976, 527}, + {976, 502}, + {976, 527}, + {976, 502}, + {976, 567}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType0b_2[] = +{ + { 1152, 700}, + { 1152, 675}, + { 1152, 700}, + { 1152, 675}, + { 1152, 740}, + { 1232, 799}, + { 0, 799}, + { 0, 0}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType0c_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType0d_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType0e_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType0f_2[] = +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType1076_1[] = /* TW: New */ +{ + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType1076_2[] = /* TW: New */ +{ + { 1152, 622 }, + { 1152, 597 }, + { 1152, 622 }, + { 1152, 597 }, + { 1152, 622 }, + { 1232, 722 }, + { 0, 0 }, + { 0, 794 }, + { 0, 0 } +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType1210_1[] = /* TW: New */ +{ + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType1210_2[] = /* TW: New */ +{ + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType1296_1[] = /* TW: New */ +{ + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0} +}; + +static const SiS300_LVDSDesStruct SiS300_PanelType1296_2[] = /* TW: New */ +{ + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0} +}; + + +/* TW: New */ +static const SiS300_LVDSDesStruct SiS300_CHTVUNTSCDesData[] = +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_CHTVONTSCDesData[] = +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_CHTVUPALDesData[] = +{ + {256, 0}, + {256, 0}, + {256, 0}, + {256, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS300_LVDSDesStruct SiS300_CHTVOPALDesData[] = +{ + {256, 0}, + {256, 0}, + {256, 0}, + {256, 0}, + { 0, 0}, + { 0, 0} +}; +/* TW: New end */ + +/* TW: New for SiS300+301LV */ +typedef struct _SiS300_Part2PortTblStruct +{ + UCHAR CR[12]; +} SiS300_Part2PortTblStruct; + +static const SiS300_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 SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_1[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_1[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_1[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_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 SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_2[] = +{ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_2[] = +{ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_2[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1024x768_3[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_3[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_3[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_3[] = +{ /* TW: Temporary data, invalid */ + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +typedef struct _SiS300_LVDSCRT1DataStruct +{ +UCHAR CR[15]; +} SiS300_LVDSCRT1DataStruct; + +static const SiS300_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 SiS300_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 SiS300_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 SiS300_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 SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1_H[] = +{ + {{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 }} +}; + +static const SiS300_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 SiS300_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 SiS300_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 SiS300_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 SiS300_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 SiS300_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 SiS300_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 SiS300_LVDSCRT1DataStruct SiS300_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 SiS300_LVDSCRT1DataStruct SiS300_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 SiS300_LVDSCRT1DataStruct SiS300_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 SiS300_LVDSCRT1DataStruct SiS300_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 SiS300_LVDSCRT1DataStruct SiS300_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 SiS300_LVDSCRT1DataStruct SiS300_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 SiS300_LVDSCRT1DataStruct SiS300_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 SiS300_LVDSCRT1DataStruct SiS300_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}} +}; + +/* TW: New */ +static const SiS300_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 SiS300_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 SiS300_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 SiS300_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 SiS300_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 }} +}; +/* TW: New end */ + +/* TW: New */ +typedef struct _SiS300_CHTVRegDataStruct +{ + UCHAR Reg[16]; +} SiS300_CHTVRegDataStruct; + +static const SiS300_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 SiS300_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 SiS300_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 SiS300_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 SiS300_CHTVRegDataStruct SiS300_CHTVReg_SOPAL[] = +{ + {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 5/4 */ + {{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 */ +}; +/* TW: New end */ + +/* TW: New */ +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}; +/* TW: New end */ + + diff --git a/src/310vtbl.h b/src/310vtbl.h new file mode 100644 index 0000000..5bb9d77 --- /dev/null +++ b/src/310vtbl.h @@ -0,0 +1,4673 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/310vtbl.h,v 1.5 2003/02/10 01:14:16 tsi Exp $ */ + + +/* Register settings for SiS 310/325 series */ + + +typedef struct _SiS310_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; +} SiS310_StStruct; + +static const SiS310_StStruct SiS310_SModeIDTable[]= +{ + {0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00}, + {0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00}, + {0x01,0x1010,0x17,0x02,0x02,0x00,0x01,0x01}, + {0x03,0x8208,0x03,0x00,0x00,0x00,0x01,0x02}, + {0x03,0x0210,0x16,0x01,0x01,0x00,0x01,0x02}, + {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03}, + {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x04}, + {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x05}, + {0x07,0x0000,0x07,0x03,0x03,0x00,0x01,0x03}, + {0x07,0x0000,0x19,0x02,0x02,0x00,0x01,0x03}, + {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x04}, + {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x05}, + {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x05}, + {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x05}, + {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x05}, + {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x05}, + {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x04}, + {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x05}, + {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x05}, + {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00} +}; + +typedef struct _SiS310_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]; +} SiS310_StandTableStruct; + +static const SiS310_StandTableStruct SiS310_StandTable[]= +{ +/* 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} + }, +/* 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} + }, +/* 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} + }, +/* MD_3_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} + }, +/* MD_4 */ + { + 0x28,0x18,0x08,0x4000, + {0x09,0x03,0x00,0x02}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, + 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} + }, +/* MD_5 */ + { + 0x28,0x18,0x08,0x4000, + {0x09,0x03,0x00,0x02}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, + 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} + }, +/* MD_6 */ + { + 0x50,0x18,0x08,0x4000, + {0x01,0x01,0x00,0x06}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 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} + }, +/* 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} + }, +/* 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} + }, +/* 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} + }, +/* 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} + }, +/* 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} + }, + { + 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} + }, +/* MD_D */ + { + 0x28,0x18,0x08,0x2000, + {0x09,0x0f,0x00,0x06}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, + 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} + }, +/* MD_E */ + { + 0x50,0x18,0x08,0x4000, + {0x01,0x0f,0x00,0x06}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 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} + }, +/* ExtVGATable */ + { + 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} + }, +/* ROM_SAVEPTR */ + { + 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} + }, +/* MD_F */ + { + 0x50,0x18,0x0e,0x8000, + {0x01,0x0f,0x00,0x06}, + 0xa2, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3, + 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} + }, +/* MD_10 */ + { + 0x50,0x18,0x0e,0x8000, + {0x01,0x0f,0x00,0x06}, + 0xa3, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3, + 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} + }, +/* MD_0_350 */ + { + 0x28,0x18,0x0e,0x0800, + {0x09,0x03,0x00,0x02}, + 0xa3, + {0x2d,0x27,0x28,0x90,0x2b,0xb1,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} + }, +/* 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} + }, +/* 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} + }, +/* MD_3_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} + }, +/* MD_0_1_400 */ + { + 0x28,0x18,0x10,0x0800, + {0x08,0x03,0x00,0x02}, + 0x67, + {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f, + 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} + }, +/* MD_2_3_400 */ + { + 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} + }, +/* 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} + }, +/* MD_11 */ + { + 0x50,0x1d,0x10,0xa000, + {0x01,0x0f,0x00,0x06}, + 0xe3, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xc3, + 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} + }, +/* ExtEGATable */ + { + 0x50,0x1d,0x10,0xa000, + {0x01,0x0f,0x00,0x06}, + 0xe3, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3, + 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} + }, +/* MD_13 */ + { + 0x28,0x18,0x08,0x2000, + {0x01,0x0f,0x00,0x0e}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 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} + } +}; + +typedef struct _SiS310_ExtStruct +{ + UCHAR Ext_ModeID; + USHORT Ext_ModeFlag; + USHORT Ext_ModeInfo; + USHORT Ext_Point; /* TW: Address of table entry in (older) BIOS image */ + USHORT Ext_VESAID; + UCHAR Ext_VESAMEMSize; + UCHAR Ext_RESINFO; + UCHAR VB_ExtTVFlickerIndex; + UCHAR VB_ExtTVEdgeIndex; + UCHAR VB_ExtTVYFilterIndex; + UCHAR REFindex; +} SiS310_ExtStruct; + +/* TW: Checked with 650/LVDS and 650/301LVx 1.10.6s */ +static const SiS310_ExtStruct SiS310_EModeIDTable[]= +{ + {0x6a,0x2212,0x0407,0x3a81,0x0102,0x08,0x07,0x00,0x00,0x07,0x00}, /* 800x600x? */ + {0x2e,0x0a1b,0x0306,0x3a57,0x0101,0x08,0x06,0x00,0x00,0x05,0x08}, /* 640x480x8 */ +/* {0x2e,0x021b,0x0306,0x3a57,0x0101,0x08,0x06,0x00,0x00,0x05,0x08}, */ /* 640x480x8 - 650/LVDS BIOS (no CRt2Mode) */ + {0x2f,0x0a1b,0x0305,0x3a50,0x0100,0x08,0x05,0x00,0x00,0x05,0x10}, /* 640x400x8 */ +/* {0x2f,0x021b,0x0305,0x3a50,0x0100,0x08,0x05,0x00,0x00,0x05,0x10}, */ /* 640x400x8 - 650/LVDS BIOS (no CRt2Mode) */ + {0x30,0x2a1b,0x0407,0x3a81,0x0103,0x08,0x07,0x00,0x00,0x07,0x00}, /* 800x600x8 */ +/* {0x30,0x221b,0x0407,0x3a81,0x0103,0x08,0x07,0x00,0x00,0x07,0x00}, */ /* 800x600x8 - 650/LVDS BIOS (no CRt2Mode) */ +/* {0x31,0x0a1b,0x030d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x11}, */ /* 720x480x8 */ + {0x31,0x0a1b,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x11}, /* 720x480x8 BIOS (301/LVDS) */ + {0x32,0x0a1b,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x12}, /* 720x576x8 */ + {0x33,0x0a1d,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x11}, /* 720x480x16 */ + {0x34,0x2a1d,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x12}, /* 720x576x16 */ + {0x35,0x0a1f,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x11}, /* 720x480x32 */ + {0x36,0x2a1f,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x12}, /* 720x576x32 */ + {0x37,0x0212,0x0508,0x3aab,0x0104,0x08,0x08,0x00,0x00,0x08,0x13}, /* 1024x768x? */ + {0x38,0x0a1b,0x0508,0x3aab,0x0105,0x08,0x08,0x00,0x00,0x08,0x13}, /* 1024x768x8 */ +/* {0x38,0x021b,0x0508,0x3aab,0x0105,0x08,0x08,0x00,0x00,0x00,0x13}, */ /* 1024x768x8 - 650/LVDS BIOS (no CRt2Mode) */ + {0x3a,0x0e3b,0x0609,0x3adc,0x0107,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */ +/* {0x3a,0x063b,0x0609,0x3adc,0x0107,0x08,0x09,0x00,0x00,0x00,0x1a}, */ /* 1280x1024x8 - 650/LVDS BIOS*/ + {0x3c,0x0e3b,0x070a,0x3af2,0x0130,0x08,0x0a,0x00,0x00,0x00,0x1e}, /* 1600x1200x8 */ +/* {0x3c,0x063b,0x070a,0x3af2,0x0130,0x08,0x0a,0x00,0x00,0x00,0x1e}, */ /* 1600x1200x8 - 650/LVDS BIOS */ + {0x3d,0x067d,0x070a,0x3af2,0x0131,0x08,0x0a,0x00,0x00,0x00,0x1e}, /* 1600x1200x16 - 650/301LVx - no CRT2Mode? */ + {0x40,0x9a1c,0x0000,0x3a34,0x010d,0x08,0x00,0x00,0x00,0x04,0x25}, + {0x41,0x9a1d,0x0000,0x3a34,0x010e,0x08,0x00,0x00,0x00,0x04,0x25}, + {0x43,0x0a1c,0x0306,0x3a57,0x0110,0x08,0x06,0x00,0x00,0x05,0x08}, + {0x44,0x0a1d,0x0306,0x3a57,0x0111,0x08,0x06,0x00,0x00,0x05,0x08}, /* 640x480x16 */ + {0x46,0x2a1c,0x0407,0x3a81,0x0113,0x08,0x07,0x00,0x00,0x07,0x00}, + {0x47,0x2a1d,0x0407,0x3a81,0x0114,0x08,0x07,0x00,0x00,0x07,0x00}, /* 800x600x16 */ + {0x49,0x0a3c,0x0508,0x3aab,0x0116,0x08,0x08,0x00,0x00,0x00,0x13}, + {0x4a,0x0a3d,0x0508,0x3aab,0x0117,0x08,0x08,0x00,0x00,0x08,0x13}, /* 1024x768x16 */ + {0x4c,0x0e7c,0x0609,0x3adc,0x0119,0x08,0x09,0x00,0x00,0x00,0x1a}, + {0x4d,0x0e7d,0x0609,0x3adc,0x011a,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 1280x1024x16 */ + {0x50,0x9a1b,0x0001,0x3a3b,0x0132,0x08,0x01,0x00,0x00,0x04,0x26}, +/* {0x50,0x921b,0x0001,0x3a3b,0x0132,0x08,0x01,0x00,0x00,0x04,0x26}, */ /* 650/LVDS BIOS */ + {0x51,0xba1b,0x0103,0x3a42,0x0133,0x08,0x03,0x00,0x00,0x07,0x27}, +/* {0x52,0x9a1b,0x0204,0x3a49,0x0134,0x08,0x04,0x00,0x00,0x00,0x28}, */ + {0x52,0xba1b,0x0204,0x3a49,0x0134,0x08,0x04,0x00,0x00,0x00,0x28}, /* 650/301 BIOS */ +/* {0x52,0xb21b,0x0204,0x3a49,0x0134,0x08,0x04,0x00,0x00,0x00,0x28}, */ /* 650/LVDS BIOS (no CRT2Mode) */ + {0x56,0x9a1d,0x0001,0x3a3b,0x0135,0x08,0x01,0x00,0x00,0x04,0x26}, + {0x57,0xba1d,0x0103,0x3a42,0x0136,0x08,0x03,0x00,0x00,0x07,0x27}, +/* {0x58,0x9a1d,0x0204,0x3a49,0x0137,0x08,0x04,0x00,0x00,0x00,0x28}, */ + {0x58,0xba1d,0x0204,0x3a49,0x0137,0x08,0x04,0x00,0x00,0x00,0x28}, /* BIOS (301+LVDS) */ + {0x59,0x9a1b,0x0000,0x3a34,0x0138,0x08,0x00,0x00,0x00,0x04,0x25}, +/* {0x59,0x921b,0x0000,0x3a34,0x0138,0x08,0x00,0x00,0x00,0x04,0x25}, */ /* 650/LVDS BIOS (no CRT2Mode) */ + {0x5A,0x021b,0x0014,0x3b83,0x0138,0x08,0x01,0x00,0x00,0x04,0x3f}, /* 320x480x8 fstn add new mode*/ + {0x5B,0x0a1d,0x0014,0x3b83,0x0135,0x08,0x01,0x00,0x00,0x04,0x3f}, /* 320x480x16 fstn add new mode*/ + {0x5c,0xba1f,0x0204,0x3a49,0x0000,0x08,0x04,0x00,0x00,0x00,0x28}, /* TW: inserted 512x384x32 */ + {0x5d,0x0a1d,0x0305,0x3a50,0x0139,0x08,0x05,0x00,0x00,0x07,0x10}, + {0x5e,0x0a1f,0x0305,0x3a50,0x0000,0x08,0x05,0x00,0x00,0x07,0x10}, /* TW: Inserted 640x400x32 */ + {0x62,0x0a3f,0x0306,0x3a57,0x013a,0x08,0x06,0x00,0x00,0x05,0x08}, /* 640x480x32 */ + {0x63,0x2a3f,0x0407,0x3a81,0x013b,0x08,0x07,0x00,0x00,0x07,0x00}, /* 800x600x32 */ + {0x64,0x0a7f,0x0508,0x3aab,0x013c,0x08,0x08,0x00,0x00,0x08,0x13}, /* 1024x768x32 */ + {0x65,0x0eff,0x0609,0x3adc,0x013d,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 1280x1024x32 */ + {0x66,0x06ff,0x070a,0x3af2,0x013e,0x08,0x0a,0x00,0x00,0x00,0x1e}, /* 1600x1200x32 */ + {0x68,0x067b,0x080b,0x3b17,0x013f,0x08,0x0b,0x00,0x00,0x00,0x29}, /* 1920x1440x8 */ + {0x69,0x06fd,0x080b,0x3b17,0x0140,0x08,0x0b,0x00,0x00,0x00,0x29}, /* 1920x1440x16 */ + {0x6b,0x07ff,0x080b,0x3b17,0x0141,0x10,0x0b,0x00,0x00,0x00,0x29}, /* 1920x1440x32 */ + {0x6c,0x067b,0x090c,0x3b37,0x0000,0x08,0x0c,0x00,0x00,0x00,0x2f}, /* 2048x1536x8 */ + {0x6d,0x06fd,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f}, /* 2048x1536x16 */ + {0x6e,0x07ff,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f}, /* 2048x1536x32 */ + {0x70,0x2a1b,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34}, /* 800x480x8 */ + {0x71,0x0a1b,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, /* 1024x576x8 */ + {0x74,0x0a1d,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, /* 1024x576x16 */ + {0x75,0x0a3d,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a}, /* 1280x720x16 */ + {0x76,0x2a1f,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34}, /* 800x480x32 */ + {0x77,0x0a1f,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, /* 1024x576x32 */ + {0x78,0x0a3f,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a}, /* 1280x720x32 */ + {0x79,0x0a3b,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a}, /* 1280x720x8 */ + {0x7a,0x2a1d,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34}, /* 800x480x16 */ + {0x7c,0x0e3b,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x3d}, /* 1280x960x8 - TW */ + {0x7d,0x0e7d,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x3d}, /* 1280x960x16 - TW */ + {0x7e,0x0eff,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x3d}, /* 1280x960x32 - TW */ + /* TW: 650/LVDS BIOS new modes */ +/* {0x23,0x063b,0x0614,0x36f7,0x0000,0x08,0x14,0x00,0x00,0x00,0x40}, */ /* 1280x768x8 - 650/LVDS BIOS */ + {0x23,0x0e3b,0x0614,0x36f7,0x0000,0x08,0x14,0x00,0x00,0x00,0x40}, /* 1280x768x8 */ + {0x24,0x0e7d,0x0614,0x36f7,0x0000,0x08,0x14,0x00,0x00,0x00,0x40}, /* 1280x768x16 */ + {0x25,0x0eff,0x0614,0x36f7,0x0000,0x08,0x14,0x00,0x00,0x00,0x40}, /* 1280x768x32 */ + {0x26,0x0e3b,0x0c15,0x36fe,0x0000,0x08,0x15,0x00,0x00,0x00,0x41}, /* 1400x1050x8 */ +/* {0x26,0x063b,0x0c15,0x36fe,0x0000,0x08,0x15,0x00,0x00,0x00,0x41}, */ /* 1400x1050x8 - 650/LVDS BIOS */ + {0x27,0x0e7d,0x0c15,0x36fe,0x0000,0x08,0x15,0x00,0x00,0x00,0x41}, /* 1400x1050x16 */ + {0x28,0x0eff,0x0c15,0x36fe,0x0000,0x08,0x15,0x00,0x00,0x00,0x41}, /* 1400x1050x32*/ + {0x29,0x0e1b,0x0d16,0x0000,0x0000,0x08,0x16,0x00,0x00,0x00,0x43}, /* TW: NEW 1152x864 - not in BIOS */ + {0x2a,0x0e3d,0x0d16,0x0000,0x0000,0x08,0x16,0x00,0x00,0x00,0x43}, + {0x2b,0x0e7f,0x0d16,0x0000,0x0000,0x08,0x16,0x00,0x00,0x00,0x43}, + {0x39,0x2a1b,0x0b17,0x0000,0x0000,0x08,0x17,0x00,0x00,0x00,0x45}, /* TW: NEW 848x480 - not in BIOS */ + {0x3b,0x2a3d,0x0b17,0x0000,0x0000,0x08,0x17,0x00,0x00,0x00,0x45}, + {0x3e,0x2a7f,0x0b17,0x0000,0x0000,0x08,0x17,0x00,0x00,0x00,0x45}, + {0x3f,0x2a1b,0x0b13,0x0000,0x0000,0x08,0x13,0x00,0x00,0x00,0x47}, /* TW: NEW 856x480 - not in BIOS */ + {0x42,0x2a3d,0x0b13,0x0000,0x0000,0x08,0x13,0x00,0x00,0x00,0x47}, + {0x45,0x2a7f,0x0b13,0x0000,0x0000,0x08,0x13,0x00,0x00,0x00,0x47}, + {0x48,0x2a1b,0x0e18,0x0000,0x0000,0x08,0x18,0x00,0x00,0x00,0x49}, /* TW: NEW 1360x768 - not in BIOS */ + {0x4b,0x2a3d,0x0e18,0x0000,0x0000,0x08,0x18,0x00,0x00,0x00,0x49}, + {0x4e,0x2a7f,0x0e18,0x0000,0x0000,0x08,0x18,0x00,0x00,0x00,0x49}, + {0xff,0x0000,0x0000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00} +}; + +typedef struct _SiS310_Ext2Struct +{ + USHORT Ext_InfoFlag; + UCHAR Ext_CRT1CRTC; + UCHAR Ext_CRTVCLK; + UCHAR Ext_CRT2CRTC; + UCHAR ModeID; + USHORT XRes; + USHORT YRes; + USHORT ROM_OFFSET; +} SiS310_Ext2Struct; + +static const SiS310_Ext2Struct SiS310_RefIndex[]= +{ +/* {0x005f,0x0d,0x03,0x05,0x6a, 800, 600,0x3a81}, 0x0 - TW: Patch for Chrontel 7019 */ + {0x085f,0x0d,0x03,0x05,0x6a, 800, 600,0x3a81}, /* 0x0 */ + {0x0467,0x0e,0x04,0x05,0x6a, 800, 600,0x3a86}, /* 0x1 */ + {0x0067,0x0f,0x08,0x48,0x6a, 800, 600,0x3a8b}, /* 0x2 */ + {0x0067,0x10,0x07,0x8b,0x6a, 800, 600,0x3a90}, /* 0x3 */ + {0x0147,0x11,0x0a,0x00,0x6a, 800, 600,0x3a95}, /* 0x4 */ + {0x0147,0x12,0x0d,0x00,0x6a, 800, 600,0x3a9a}, /* 0x5 - 4147 TW: Test sync change */ + {0x0047,0x13,0x13,0x00,0x6a, 800, 600,0x3a9f}, /* 0x6 - 4047 */ + {0x0047,0x14,0x1c,0x00,0x6a, 800, 600,0x3aa4}, /* 0x7 - 4047 */ +/* {0xc05f,0x05,0x00,0x04,0x2e, 640, 480,0x3a57}, 0x8 - TW: Patch for Chrontel 7019 */ + {0xc85f,0x05,0x00,0x04,0x2e, 640, 480,0x3a57}, /* 0x8 */ + {0xc067,0x06,0x02,0x04,0x2e, 640, 480,0x3a5c}, /* 0x9 */ + {0xc067,0x07,0x02,0x47,0x2e, 640, 480,0x3a61}, /* 0xa */ + {0xc067,0x08,0x03,0x8a,0x2e, 640, 480,0x3a66}, /* 0xb */ + {0xc047,0x09,0x05,0x00,0x2e, 640, 480,0x3a6b}, /* 0xc - 4047 */ + {0xc047,0x0a,0x09,0x00,0x2e, 640, 480,0x3a70}, /* 0xd - 4047 */ + {0xc047,0x0b,0x0e,0x00,0x2e, 640, 480,0x3a75}, /* 0xe - 4047 */ + {0xc047,0x0c,0x15,0x00,0x2e, 640, 480,0x3a7a}, /* 0xf */ + {0x407f,0x04,0x00,0x00,0x2f, 640, 400,0x3a50}, /* 0x10 */ + {0xc00f,0x3c,0x01,0x06,0x31, 720, 480,0x3b85}, /* 0x11 */ + {0x000f,0x3d,0x03,0x06,0x32, 720, 576,0x3b8c}, /* 0x12 */ + {0x0187,0x15,0x06,0x00,0x37,1024, 768,0x3aab}, /* 0x13 */ + {0xc877,0x16,0x0b,0x06,0x37,1024, 768,0x3ab0}, /* 0x14 301b TV1024x768*/ + {0xc067,0x17,0x0f,0x49,0x37,1024, 768,0x3ab5}, /* 0x15 */ + {0x0267,0x18,0x11,0x00,0x37,1024, 768,0x3aba}, /* 0x16 */ + {0x0047,0x19,0x16,0x8c,0x37,1024, 768,0x3abf}, /* 0x17 */ + {0x0047,0x1a,0x1b,0x00,0x37,1024, 768,0x3ac4}, /* 0x18 - 4047 */ + {0x0047,0x1b,0x1f,0x00,0x37,1024, 768,0x3ac9}, /* 0x19 - 4047 */ + {0x0387,0x1c,0x11,0x00,0x3a,1280,1024,0x3adc}, /* 0x1a */ + {0x0077,0x1d,0x19,0x07,0x3a,1280,1024,0x3ae1}, /* 0x1b */ + {0x0047,0x1e,0x1e,0x00,0x3a,1280,1024,0x3ae6}, /* 0x1c */ + {0x0007,0x1f,0x20,0x00,0x3a,1280,1024,0x3aeb}, /* 0x1d */ + {0x0007,0x20,0x21,0x00,0x3c,1600,1200,0x3af2}, /* 0x1e */ + {0x0007,0x21,0x22,0x00,0x3c,1600,1200,0x3af7}, /* 0x1f */ + {0x0007,0x22,0x23,0x00,0x3c,1600,1200,0x3afc}, /* 0x20 */ + {0x0007,0x23,0x25,0x00,0x3c,1600,1200,0x3b01}, /* 0x21 */ + {0x0007,0x24,0x26,0x00,0x3c,1600,1200,0x3b06}, /* 0x22 */ + {0x0007,0x25,0x2c,0x00,0x3c,1600,1200,0x3b0b}, /* 0x23 */ + {0x0007,0x26,0x34,0x00,0x3c,1600,1200,0x3b10}, /* 0x24 */ + {0x407f,0x00,0x00,0x00,0x40, 320, 200,0x3a34}, /* 0x25 */ + {0xc07f,0x01,0x00,0x04,0x50, 320, 240,0x3a3b}, /* 0x26 */ + {0x007f,0x02,0x04,0x05,0x51, 400, 300,0x3a42}, /* 0x27 */ + {0xc077,0x03,0x0b,0x06,0x52, 512, 384,0x3a49}, /* 0x28 */ + {0x8007,0x27,0x27,0x00,0x68,1920,1440,0x3b17}, /* 0x29 */ + {0x4007,0x28,0x29,0x00,0x68,1920,1440,0x3b1c}, /* 0x2a */ + {0x4007,0x29,0x2e,0x00,0x68,1920,1440,0x3b21}, /* 0x2b */ + {0x4007,0x2a,0x30,0x00,0x68,1920,1440,0x3b26}, /* 0x2c */ + {0x4007,0x2b,0x35,0x00,0x68,1920,1440,0x3b2b}, /* 0x2d */ + {0x4005,0x2c,0x39,0x00,0x68,1920,1440,0x3b30}, /* 0x2e */ + {0x4007,0x2d,0x2b,0x00,0x6c,2048,1536,0x3b37}, /* 0x2f */ + {0x4007,0x2e,0x31,0x00,0x6c,2048,1536,0x3b3c}, /* 0x30 */ + {0x4007,0x2f,0x33,0x00,0x6c,2048,1536,0x3b41}, /* 0x31 */ + {0x4007,0x30,0x37,0x00,0x6c,2048,1536,0x3b46}, /* 0x32 */ + {0x4005,0x31,0x38,0x00,0x6c,2048,1536,0x3b4b}, /* 0x33 */ + {0x0057,0x32,0x40,0x08,0x70, 800, 480,0x3b52}, /* 0x34 */ + {0x0047,0x33,0x07,0x08,0x70, 800, 480,0x3b57}, /* 0x35 */ + {0x0047,0x34,0x0a,0x08,0x70, 800, 480,0x3b5c}, /* 0x36 */ + {0x0057,0x35,0x0b,0x09,0x71,1024, 576,0x3b63}, /* 0x37 */ + {0x0047,0x36,0x11,0x09,0x71,1024, 576,0x3b68}, /* 0x38 */ + {0x0047,0x37,0x16,0x09,0x71,1024, 576,0x3b6d}, /* 0x39 */ + {0x0057,0x38,0x19,0x0a,0x75,1280, 720,0x3b74}, /* 0x3a */ + {0x0047,0x39,0x1e,0x0a,0x75,1280, 720,0x3b79}, /* 0x3b */ + {0x0047,0x3a,0x20,0x0a,0x75,1280, 720,0x3b7e}, /* 0x3c */ + {0x0027,0x3b,0x19,0x08,0x7c,1280, 960,0x3ad0}, /* 0x3d */ + {0x0047,0x4c,0x59,0x08,0x7c,1280, 960,0x3ad0}, /* 0x3e */ + {0xc07f,0x01,0x00,0x06,0x5a, 320, 480,0x3b83}, /* 0x3f */ /* FSTN mode */ + {0x0077,0x42,0x12,0x07,0x23,1280, 768,0x0000}, /* 0x40 */ /* TW: 650/LVDS/301LVx new mode */ + {0x0067,0x43,0x4d,0x08,0x26,1400,1050,0x0000}, /* 0x41 */ /* TW: 650/LVDS/301LVx new mode */ + {0x0067,0x4b,0x5a,0x08,0x26,1400,1050,0x0000}, /* 0x42 */ /* TW: new, not in any BIOS */ + {0x0047,0x44,0x19,0x06,0x29,1152, 864,0x0000}, /* 0x43 TW: Non-BIOS, new */ + {0x0047,0x4a,0x1e,0x06,0x29,1152, 864,0x0000}, /* 0x44 TW: Non-BIOS, new */ + {0x00c7,0x45,0x57,0x00,0x39, 848, 480,0x0000}, /* 0x45 TW: 848x480-38Hzi - Non-BIOS, new */ + {0xc047,0x46,0x55,0x00,0x39, 848, 480,0x0000}, /* 0x46 TW: 848x480-60Hz - Non-BIOS, new */ + {0x00c7,0x47,0x57,0x00,0x3f, 856, 480,0x0000}, /* 0x47 TW: 856x480-38Hzi - Non-BIOS, new */ + {0xc047,0x48,0x57,0x00,0x3f, 856, 480,0x0000}, /* 0x48 TW: 856x480-60Hz - Non-BIOS, new */ + {0x0047,0x49,0x58,0x00,0x48,1360, 768,0x0000}, /* 0x49 TW: 1360x768-60Hz - Non-BIOS, new */ + {0xffff,0x00,0x00,0x00,0x00, 0, 0,0x0000} +}; + +typedef struct _SiS310_CRT1TableStruct +{ + UCHAR CR[17]; +} SiS310_CRT1TableStruct; + +static const SiS310_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, /* TW: 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, /* TW: Corrected VBE */ + 0x61}}, /* 0xb */ + {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f, + 0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01, /* TW: 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, /* TW: 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, /* TW: The following from 650/LVDS BIOS */ + 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, /* TW: New, 1152x864-75, not in any BIOS */ + 0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07, + 0x01}}, /* 0x44 */ + {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* TW: New, 848x480-38i, not in BIOS */ + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, + 0x00}}, /* 0x45 */ +#if 0 + {{0x81,0x69,0x69,0x85,0x70,0x00,0x0F,0x3E, /* TW: New, 848x480-60, not in BIOS - incorrect for Philips panel */ + 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02, + 0x00}}, /* 0x46 */ +#endif + {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* TW: New, 848x480-60, not in BIOS */ + 0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06, + 0x00}}, /* 0x46 */ + {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* TW: New, 856x480-38i, not in BIOS */ + 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02, + 0x00}}, /* 0x47 */ + {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* TW: New, 856x480-60, not in BIOS */ + 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02, + 0x00}}, /* 0x48 */ + {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* TW: New, 1360x768-60, not in BIOS */ + 0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03, + 0x01}}, /* 0x49 */ + {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* TW: New, 1152x864-84, not in any BIOS */ + 0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03, + 0x01}}, /* 0x4a */ + {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10, /* TW: New, 1400x1050-75, not in any BIOS */ + 0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03, + 0x00}}, /* 0x4b */ + {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* TW: New, 1280x960-85, not in any BIOS */ + 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07, + 0x01}} /* 0x4c */ +}; + + +typedef struct _SiS310_MCLKDataStruct +{ + UCHAR SR28,SR29,SR2A; + USHORT CLOCK; +} SiS310_MCLKDataStruct; + +static const SiS310_MCLKDataStruct SiS310_MCLKData_0_315[] = +{ + { 0x3b,0x22,0x01,143}, /* TW: Was { 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}, + { 0x5c,0x23,0x01,166} +}; + +static const SiS310_MCLKDataStruct SiS310_MCLKData_0_650[] = /* @ 0x54 */ +{ + { 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 SiS310_MCLKDataStruct SiS310_MCLKData_0_330[] = /* @ 0x54 */ +{ + { 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 SiS310_MCLKDataStruct SiS310_MCLKData_1[] = /* @ 0x155 */ +{ + { 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} +}; + +typedef struct _SiS310_ECLKDataStruct +{ + UCHAR SR2E,SR2F,SR30; + USHORT CLOCK; +} SiS310_ECLKDataStruct; + +static const SiS310_ECLKDataStruct SiS310_ECLKData[]= +{ + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166} +}; + +typedef struct _SiS310_VCLKDataStruct +{ + UCHAR SR2B,SR2C; + USHORT CLOCK; +} SiS310_VCLKDataStruct; + +static const SiS310_VCLKDataStruct SiS310_VCLKData[]= +{ + { 0x1b,0xe1, 25}, /* 0x0 */ /* 650/LVDS BIOS: @ 0x5647 */ + { 0x4e,0xe4, 28}, /* 0x1 */ + { 0x57,0xe4, 31}, /* 0x2 */ + { 0xc3,0xc8, 36}, /* 0x3 */ + { 0x42,0xe2, 40}, /* 0x4 */ + { 0xfe,0xcd, 43}, /* 0x5 */ + { 0x5d,0xc4, 44}, /* 0x6 */ + { 0x52,0xe2, 49}, /* 0x7 */ + { 0x53,0xe2, 50}, /* 0x8 */ + { 0x74,0x67, 52}, /* 0x9 */ + { 0x6d,0x66, 56}, /* 0xa */ + { 0x5a,0x64, 65}, /* 0xb */ /* TW: was 6c c3 - WRONG */ + { 0x46,0x44, 67}, /* 0xc */ + { 0xb1,0x46, 68}, /* 0xd */ + { 0xd3,0x4a, 72}, /* 0xe */ + { 0x29,0x61, 75}, /* 0xf */ + { 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 */ + { 0x52,0x6a, 27}, /* 0x3b */ + { 0x62,0x24, 70}, /* 0x3c */ + { 0x62,0x64, 70}, /* 0x3d */ + { 0xa8,0x4c, 30}, /* 0x3e */ + { 0x20,0x26, 33}, /* 0x3f */ + { 0x31,0xc2, 39}, /* 0x40 */ + /* TW: 650/LVDS BIOS @ 0x574b new: */ + { 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 */ /* TW: Last entry in 650/301 BIOS */ + { 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 - added for 848x480-60 (not in any BIOS) */ + { 0x6a,0xc6, 37}, /* 0x56 - added for 848x480-75 (not in any BIOS) - TEMP */ + { 0xbf,0xc8, 35}, /* 0x57 - added for 856x480-38i,60 (not in any BIOS) */ + { 0x30,0x23, 88}, /* 0x58 - added for 1360x768-62 (is 60Hz!) (not in any BIOS) - TEMP */ + { 0x52,0x07,149}, /* 0x59 - added for 1280x960-85 (Not in any BIOS) */ + { 0x56,0x07,156} /* 0x5a - added for 1400x1050-75 */ +}; + +typedef struct _SiS310_VBVCLKDataStruct +{ + UCHAR Part4_A,Part4_B; + USHORT CLOCK; +} SiS310_VBVCLKDataStruct; + +static const SiS310_VBVCLKDataStruct SiS310_VBVCLKData[]= +{ + { 0x1b,0xe1, 25}, /* 0x0 */ /* 650/LVDS BIOS: @ 0x579c */ + { 0x4e,0xe4, 28}, /* 0x1 */ + { 0x57,0xe4, 31}, /* 0x2 */ + { 0xc3,0xc8, 36}, /* 0x3 */ + { 0x42,0x47, 40}, /* 0x4 */ + { 0xfe,0xcd, 43}, /* 0x5 */ + { 0x5d,0xc4, 44}, /* 0x6 */ + { 0x52,0x47, 49}, /* 0x7 */ + { 0x53,0x47, 50}, /* 0x8 */ + { 0x74,0x67, 52}, /* 0x9 */ + { 0x6d,0x66, 56}, /* 0xa */ + { 0x35,0x62, 65}, /* 0xb */ /* Was 0x5a,0x64 - 650/LVDS+301 bios: 35,62 */ + { 0x46,0x44, 67}, /* 0xc */ + { 0xb1,0x46, 68}, /* 0xd */ + { 0xd3,0x4a, 72}, /* 0xe */ + { 0x29,0x61, 75}, /* 0xf */ + { 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 */ + { 0x3c,0x23,109}, /* 0x1a */ + { 0x5e,0x43,113}, /* 0x1b */ + { 0xbc,0x44,116}, /* 0x1c */ + { 0xe0,0x46,132}, /* 0x1d */ + { 0xd4,0x28,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 */ + { 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 */ + { 0x52,0x6a, 27}, /* 0x3b */ + { 0x62,0x24, 70}, /* 0x3c */ + { 0x62,0x64, 70}, /* 0x3d */ + { 0xa8,0x4c, 30}, /* 0x3e */ + { 0x20,0x26, 33}, /* 0x3f */ + { 0x31,0xc2, 39}, /* 0x40 */ + /* TW: 650/LVDS+301 BIOS (@ 0x58a0 in LVDS) new: */ + { 0x2e,0x48, 25}, /* 0x41 */ + { 0x24,0x46, 25}, /* 0x42 */ + { 0x26,0x64, 28}, /* 0x43 */ + { 0x37,0x64, 40}, /* 0x44 */ + { 0xa1,0x42,108}, /* 0x45 */ + { 0x37,0x61,100}, /* 0x46 */ + { 0x78,0x27,108} /* 0x47 */ + /* --- 0x58bc --- */ +}; + +static const UCHAR SiS310_ScreenOffset[] = +{ + 0x14,0x19,0x20,0x28,0x32,0x40,0x50,0x64, + 0x78,0x80,0x2d,0x35,0x57,0x48,0x55, + 0xff +}; /* TW: Added 1400x1050, 1152x864, 848/856x480, 1360x768 */ + +typedef struct _SiS310_StResInfoStruct +{ + USHORT HTotal; + USHORT VTotal; +} SiS310_StResInfoStruct; + +static const SiS310_StResInfoStruct SiS310_StResInfo[]= +{ + { 640,400}, + { 640,350}, + { 720,400}, + { 720,350}, + { 640,480} +}; + +typedef struct _SiS310_ModeResInfoStruct +{ + USHORT HTotal; + USHORT VTotal; + UCHAR XChar; + UCHAR YChar; +} SiS310_ModeResInfoStruct; + +static const SiS310_ModeResInfoStruct SiS310_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 - TW: New, not in any BIOS */ + { 1280, 768, 8,16}, /* 0x14 20; TW: New */ + { 1400,1050, 8,16}, /* 0x15 21; TW: New */ + { 1152, 864, 8,16}, /* 0x16 - TW: New, not in any BIOS */ + { 848, 480, 8,16}, /* 0x17 - TW: New, not in any BIOS */ + { 1360, 768, 8,16} /* 0x18 - TW: New, not in any BIOS */ +}; + +static const UCHAR SiS310_OutputSelect = 0x40; + +static const UCHAR SiS310_SoftSetting = 0x30; /* TW: RAM setting */ + +static const UCHAR SiS310_SR15[8][4]={ + {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} +}; + +#ifndef LINUX_XF86 + +static UCHAR SiS310_SR07 = 0x18; + +static const UCHAR SiS310_CR40[5][4]={ + {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; /*301b*/ +static const USHORT SiS310_VideoSenseData2 = 0x0174; +static const USHORT SiS310_YCSenseData2 = 0x016b; +#endif + +static const UCHAR SiS310_NTSCPhase[] = {0x21,0xed,0xba,0x08}; /* TW: Was {0x21,0xed,0x8a,0x08}; */ +static const UCHAR SiS310_PALPhase[] = {0x2a,0x05,0xe3,0x00}; /* TW: Was {0x2a,0x05,0xd3,0x00}; */ +static const UCHAR SiS310_PALMPhase[] = {0x21,0xE4,0x2E,0x9B}; /* TW: palm*/ +static const UCHAR SiS310_PALNPhase[] = {0x21,0xF4,0x3E,0xBA}; /* TW: paln*/ +static const UCHAR SiS310_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6}; +static const UCHAR SiS310_PALPhase2[] = {0x2a,0x09,0x86,0xe9}; +static const UCHAR SiS310_PALMPhase2[] = {0x21,0xE6,0xEF,0xA4}; /* TW: palm 301b*/ +static const UCHAR SiS310_PALNPhase2[] = {0x21,0xF6,0x94,0x46}; /* TW: paln 301b*/ +static const UCHAR SiS310_SpecialPhase[] = {0x1e,0x8c,0x5c,0x7a}; + +typedef struct _SiS310_LCDDataStruct +{ + USHORT RVBHCMAX; + USHORT RVBHCFACT; + USHORT VGAHT; + USHORT VGAVT; + USHORT LCDHT; + USHORT LCDVT; +} SiS310_LCDDataStruct; + +static const SiS310_LCDDataStruct SiS310_StLCD1024x768Data[]= +{ + { 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 SiS310_LCDDataStruct SiS310_ExtLCD1024x768Data[] = /* TW: Checked */ +{ + { 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 SiS310_LCDDataStruct SiS310_St2LCD1024x768Data[] = /* TW: Checked */ +{ + { 62, 25, 800, 546,1344, 806}, + { 32, 15, 930, 546,1344, 806}, +/* { 32, 15, 930, 546,1344, 806}, */ + { 62, 25, 800, 546,1344, 806}, /* TW: Different in 650/301LV BIOS */ + { 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 SiS310_LCDDataStruct SiS310_StLCD1280x1024Data[] = +{ + { 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 SiS310_LCDDataStruct SiS310_ExtLCD1280x1024Data[] = /* TW: Checked */ +{ + { 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 SiS310_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 SiS310_LCDDataStruct SiS310_NoScaleData1024x768[] = /* TW: Checked */ +{ + { 1, 1,1344, 806,1344, 806}, + { 1, 1,1344, 806,1344, 806}, + { 1, 1,1344, 806,1344, 806}, + { 1, 1,1344, 806,1344, 806}, + { 1, 1,1344, 806,1344, 806}, + { 1, 1,1344, 806,1344, 806}, + { 1, 1,1344, 806,1344, 806}, + { 1, 1,1344, 806,1344, 806} +}; + +static const SiS310_LCDDataStruct SiS310_NoScaleData1280x1024[] = /* TW: New; Checked */ +{ + { 1, 1,1688,1066,1688,1066}, + { 1, 1,1688,1066,1688,1066}, + { 1, 1,1688,1066,1688,1066}, + { 1, 1,1688,1066,1688,1066}, + { 1, 1,1688,1066,1688,1066}, + { 1, 1,1688,1066,1688,1066}, + { 1, 1,1688,1066,1688,1066}, + { 1, 1,1688,1066,1688,1066} +}; + +static const SiS310_LCDDataStruct SiS310_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 SiS310_LCDDataStruct SiS310_StLCD1400x1050Data[] = /* TW: New */ +{ /* TW: New from 1.11.6s */ + { 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 SiS310_LCDDataStruct SiS310_ExtLCD1400x1050Data[] = /* TW: New */ +{ /* TW: New from 1.11.6s */ + { 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 SiS310_LCDDataStruct SiS310_NoScaleData1400x1050[] = /* TW: New */ +{ /* TW: To be checked (BIOS uses 1280x1024 data, one line too short) */ + { 1, 1, 1688, 1066, 1688, 1066 }, + { 1, 1, 1688, 1066, 1688, 1066 }, + { 1, 1, 1688, 1066, 1688, 1066 }, + { 1, 1, 1688, 1066, 1688, 1066 }, + { 1, 1, 1688, 1066, 1688, 1066 }, + { 1, 1, 1688, 1066, 1688, 1066 }, + { 1, 1, 1688, 1066, 1688, 1066 }, + { 1, 1, 1688, 1066, 1688, 1066 }, + { 1, 1, 1688, 1066, 1688, 1066 } +}; + +static const SiS310_LCDDataStruct SiS310_StLCD1600x1200Data[] = /* TW: New */ +{ /* TODO */ + { 0, 0, 0, 0, 0, 0} +}; + +static const SiS310_LCDDataStruct SiS310_ExtLCD1600x1200Data[] = /* TW: New */ +{ /* TODO */ + { 0, 0, 0, 0, 0, 0} +}; + +static const SiS310_LCDDataStruct SiS310_NoScaleData1600x1200[] = /* TW: New */ +{ /* TODO */ + { 0, 0, 0, 0, 0, 0} +}; + +typedef struct _SiS310_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; +} SiS310_TVDataStruct; + +static const SiS310_TVDataStruct SiS310_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 SiS310_TVDataStruct SiS310_ExtPALData[] = /* TW: Verfied (1.10.7w) */ +{ + { 27, 10, 848, 448,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22}, + { 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 */ + { 36, 25,1060, 648,1316, 530, 438, 0, 438,0xeb,0x05,0x25,0x16}, /* 800x600 */ + { 3, 2,1080, 619,1270, 540, 438, 0, 438,0xf3,0x00,0x1d,0x20}, /* 720x480/576 */ + { 1, 1,1170, 821,1270, 520, 686, 0, 686,0xF3,0x00,0x1D,0x20} /* 1024x768 */ +}; + +static const SiS310_TVDataStruct SiS310_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 SiS310_TVDataStruct SiS310_ExtNTSCData[]= +{ + { 143, 65, 858, 443,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18}, + { 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 */ + { 143, 120,1056, 643,1270, 440, 0, 128, 0,0xf4,0x10,0x1c,0x00}, /* 800x600 */ + { 2, 1, 858, 503,1270, 480, 0, 128, 0,0xee,0x0c,0x22,0x08}, /* 720x480/576 */ + { 65, 64,1056, 791,1270, 480, 638, 0, 0,0xEE,0x0C,0x22,0x08} /* 1024x768 */ +}; + +/* TW: These tables will need data ! */ +static const SiS310_TVDataStruct SiS310_St1HiTVData[]= +{ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} +}; + +static const SiS310_TVDataStruct SiS310_St2HiTVData[]= +{ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} +}; + +static const SiS310_TVDataStruct SiS310_ExtHiTVData[]= +{ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} +}; + +static const UCHAR SiS310_NTSCTiming[] = { /* TW: New (checked 1.09, 1.10.6s) */ + 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 SiS310_PALTiming[] = { /* TW: New (checked 1.09, 1.10.6s) */ + 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 +}; + +#ifdef oldHV +static const UCHAR SiS310_HiTVExtTiming[] = { /* TW: New */ + 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 SiS310_HiTVSt1Timing[] = { /* TW: New */ + 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 SiS310_HiTVSt2Timing[] = { /* TW: New */ + 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 SiS310_HiTVTextTiming[] = { /* TW: New */ + 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 +}; + +static const UCHAR SiS310_HiTVGroup3Data[] = { /* TW: New */ + 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 SiS310_HiTVGroup3Simu[] = { /* TW: New */ + 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 +}; + +static const UCHAR SiS310_HiTVGroup3Text[] = { /* TW: New */ + 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 + +typedef struct _SiS310_PanelDelayTblStruct +{ + UCHAR timer[2]; +} SiS310_PanelDelayTblStruct; + +static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTbl[]= /* TW: New */ +{ + {{0x10,0x40}}, /* TW: from 650/301LVx 1.10.6s BIOS */ + {{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}} +#if 0 + {{0x28,0xc8}}, /* TW: from 650/301LV BIOS */ + {{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}} +#endif +}; + +static const SiS310_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}} +}; + +typedef struct _SiS310_LVDSDataStruct +{ + USHORT VGAHT; + USHORT VGAVT; + USHORT LCDHT; + USHORT LCDVT; +} SiS310_LVDSDataStruct; + +static const SiS310_LVDSDataStruct SiS310_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 SiS310_LVDSDataStruct SiS310_LVDS800x600Data_1[]= /* TW: New */ +{ + {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}, + {800, 449,1000, 644}, + {800, 525,1000, 635} +}; + +static const SiS310_LVDSDataStruct SiS310_LVDS800x600Data_2[]= /* TW: New */ +{ + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {800, 449,1000, 644}, + {800, 525,1000, 635} +}; + +static const SiS310_LVDSDataStruct SiS310_LVDS1024x768Data_1[]= /* TW: New */ +{ + {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 */ + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +static const SiS310_LVDSDataStruct SiS310_LVDS1024x768Data_2[]= /* TW: New */ +{ + {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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +static const SiS310_LVDSDataStruct SiS310_LVDS1280x1024Data_1[]= /* TW: New - TODO */ +{ /* TW: Temp data, invalid (is identical to 1024x768) */ + {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 SiS310_LVDSDataStruct SiS310_LVDS1280x1024Data_2[]= /* TW: New - TODO */ +{ /* TW: Temp data, invalid (is identical to 1024x768) */ + {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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +static const SiS310_LVDSDataStruct SiS310_LVDS1400x1050Data_1[]= /* TW: New */ +{ + {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 SiS310_LVDSDataStruct SiS310_LVDS1400x1050Data_2[]= /* TW: New */ +{ + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, + {1688,1066, 1688,1066}, +}; + +static const SiS310_LVDSDataStruct SiS310_LVDS1280x768Data_1[]= /* TW: New - TODO */ +{ /* TW: Temp data, invalid (is identical to 1024x768) */ + {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 SiS310_LVDSDataStruct SiS310_LVDS1280x768Data_2[]= /* TW: New - TODO */ +{ /* TW: Temp data, invalid (is identical to 1024x768) */ + {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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +/* TW: New: - from 300 series */ +static const SiS310_LVDSDataStruct SiS310_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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +/* TW: New: - from 300 series */ +static const SiS310_LVDSDataStruct SiS310_LVDS1024x600Data_2[]= +{ + {1344, 800,1344, 800}, + {1344, 800,1344, 800}, + {1344, 800,1344, 800}, + {1344, 800,1344, 800}, + {1344, 800,1344, 800}, + {1344, 800,1344, 800}, + {1344, 800,1344, 800}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +/* TW: New: - from 300 series */ +static const SiS310_LVDSDataStruct SiS310_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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +/* TW: New: - from 300 series */ +static const SiS310_LVDSDataStruct SiS310_LVDS1152x768Data_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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +/* TW: New in 650/LVDS BIOS - pass 1:1 data */ +static const SiS310_LVDSDataStruct SiS310_LVDSXXXxXXXData_1[]= /* TW: New */ +{ + { 800, 449, 800, 449}, + { 800, 449, 800, 449}, + { 900, 449, 900, 449}, + { 900, 449, 900, 449}, + { 800, 525, 800, 525}, + {1056, 628,1056, 628}, + {1344, 806,1344, 806}, + {1688, 806,1688, 806} +}; + +static const SiS310_LVDSDataStruct SiS310_LVDS640x480Data_1[]= /* TW: New */ +{ + {800, 449, 800, 449}, + {800, 449, 800, 449}, + {800, 449, 800, 449}, + {800, 449, 800, 449}, + {800, 525, 800, 525}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628} +}; + +static const SiS310_LVDSDataStruct SiS310_LVDS1280x960Data_1[]= /* TW: New */ +{ + {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 SiS310_LVDSDataStruct SiS310_LVDS1280x960Data_2[]= /* TW: New */ +{ + {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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +static const SiS310_LVDSDataStruct SiS310_LCDA1400x1050Data_1[]= /* TW: New */ +{ /* TW: Might be temporary (invalid) data */ + {928, 416, 1688, 1066}, + {928, 366, 1688, 1066}, + {1008, 416, 1688, 1066}, + {1008, 366, 1688, 1066}, + {1200, 530, 1688, 1066}, + {1088, 616, 1688, 1066}, + {1312, 784, 1688, 1066}, + {1568, 1040, 1688, 1066}, + {1688, 1066, 1688, 1066} +}; + +static const SiS310_LVDSDataStruct SiS310_LCDA1400x1050Data_2[]= /* TW: New */ +{ /* TW: Temporary data. Not valid */ + {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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +static const SiS310_LVDSDataStruct SiS310_LCDA1600x1200Data_1[]= /* TW: New */ +{ /* TW: Temporary data. Not valid */ + {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}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +static const SiS310_LVDSDataStruct SiS310_LCDA1600x1200Data_2[]= /* TW: New */ +{ /* TW: Temporary data. Not valid */ + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0} +}; + +static const SiS310_LVDSDataStruct SiS310_CHTVUNTSCData[]= /* TW: New */ +{ + { 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} /* TW: For Ch7019 1024 */ +}; + +static const SiS310_LVDSDataStruct SiS310_CHTVONTSCData[]= /* TW: New */ +{ + { 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} /* TW: For Ch7019 1024 */ +}; + +static const SiS310_LVDSDataStruct SiS310_CHTVUPALData[]= /* TW: New */ +{ + {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} /* TW: For Ch7019 1024 */ +}; + +static const SiS310_LVDSDataStruct SiS310_CHTVOPALData[]= /* TW: New */ +{ + {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} /* TW: For Ch7019 1024 */ +}; + +static const SiS310_LVDSDataStruct SiS310_CHTVUPALMData[]= /* TW: New */ +{ + { 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} /* TW: For Ch7019 1024 */ +}; + +static const SiS310_LVDSDataStruct SiS310_CHTVOPALMData[]= /* TW: New */ +{ + { 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} /* TW: For Ch7019 1024 */ +}; + +static const SiS310_LVDSDataStruct SiS310_CHTVUPALNData[]= /* TW: New */ +{ + {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} /* TW: For Ch7019 1024 */ +}; + +static const SiS310_LVDSDataStruct SiS310_CHTVOPALNData[]= /* TW: New */ +{ + {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} /* TW: For Ch7019 1024 */ +}; + +static const SiS310_LVDSDataStruct SiS310_CHTVSOPALData[]= /* TW: New (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} +}; + +typedef struct _SiS310_LVDSDesStruct +{ + USHORT LCDHDES; + USHORT LCDVDES; +} SiS310_LVDSDesStruct; + +/* TW: PanelType arrays taken from 650/LVDS BIOS 1.10.0 */ + +static const SiS310_LVDSDesStruct SiS310_PanelType00_1[]= /* TW: New */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType01_1[]= /* TW: New */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 805}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType02_1[]= /* TW: New */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 1065}, + { 0, 0}, + { 0, 0} +}; + + +static const SiS310_LVDSDesStruct SiS310_PanelType03_1[]= /* TW: New */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType04_1[]= /* TW: New */ +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType05_1[]= /* TW: New */ +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType06_1[]= /* TW: New */ +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType07_1[]= /* TW: New */ +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType08_1[]= /* TW: New */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType09_1[]= /* TW: New - to check (1280x768) */ +{ + { 0, 448}, + { 0, 448}, + { 0, 448}, + { 0, 448}, + { 0, 524}, + { 0, 627}, + { 0, 805}, + { 0, 805}, +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0a_1[]= /* TW: New */ +{ + {1059, 626}, + {1059, 624}, + {1059, 626}, + {1059, 624}, + {1059, 624}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0b_1[]= /* TW: New */ +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0c_1[]= /* TW: New */ +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0d_1[]= /* TW: New */ +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0e_1[]= /* TW: New */ +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0f_1[]= /* TW: New */ +{ + {1343, 798}, + {1343, 794}, + {1343, 798}, + {1343, 794}, + {1343, 0}, + {1343, 0}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType00_2[]= /* TW: New */ +{ + {980, 528}, + {980, 503}, + {980, 528}, + {980, 503}, + {980, 568}, + { 0, 628}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType01_2[]= /* TW: New */ +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 806}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType02_2[]= /* TW: New */ +{ + {1368, 754}, + {1368, 729}, + {1368, 754}, + {1368, 729}, + {1368, 794}, + {1448, 854}, + {1560, 938}, + { 0,1066}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType03_2[]= /* TW: New */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType04_2[]= /* TW: New */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType05_2[]= /* TW: New */ +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType06_2[]= /* TW: New */ +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType07_2[]= /* TW: New */ +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType08_2[]= /* TW: New */ +{ + {976, 527}, + {976, 502}, + {976, 527}, + {976, 502}, + {976, 567}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType09_2[]= /* TW: New - to check (1280x768) */ +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0a_2[]= /* TW: New */ +{ + {976, 527}, + {976, 502}, + {976, 527}, + {976, 502}, + {976, 567}, + { 0, 627}, + { 0, 627}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0b_2[]= /* TW: New */ +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0c_2[]= /* TW: New */ +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0d_2[]= /* TW: New */ +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0e_2[]= /* TW: New */ +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType0f_2[] = /* TW: New */ +{ + {1152, 622}, + {1152, 597}, + {1152, 622}, + {1152, 597}, + {1152, 662}, + {1232, 722}, + { 0, 805}, + { 0, 794}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType1076_1[]= /* TW: New */ +{ /* 1024x768 - Checked (1.10.6s) */ + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType1076_2[]= /* TW: New */ +{ /* 1024x768 - Checked (1.10.6s) */ + { 1184, 622 }, + { 1184, 597 }, + { 1184, 622 }, + { 1184, 597 }, + { 1152, 622 }, + { 1232, 722 }, + { 0, 0 }, + { 0, 794 }, + { 0, 0 } +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType1210_1[]= /* TW: New */ +{ /* 1280x1024 - Checked (1.10.6s) */ + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType1210_2[]= /* TW: New */ +{ /* 1280x1024 - Checked (1.10.6s) */ + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType1296_1[]= /* TW: New */ +{ /* 1400x1050 - Checked (1.10.6s) */ + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType1296_2[]= /* TW: New */ +{ /* 1400x1050 - Checked (1.10.6s) - looks heavily invalid */ + { 808 , 740}, + { 0 , 715}, + { 632 , 740}, + { 632 , 715}, + { 1307, 780}, + { 1387,1157}, + { 1499, 924}, + { 1627,1052}, + { 0 , 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType1600_1[]= /* TW: New */ +{ /* 1600x1200 - Checked (1.10.6s) */ + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0} +}; + +static const SiS310_LVDSDesStruct SiS310_PanelType1600_2[]= /* TW: New */ +{ /* 1600x1200 - Checked (1.10.6s) - looks heavily invalid */ + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0}, + { 0 , 0} +}; + +static const SiS310_LVDSDesStruct SiS310_CHTVUNTSCDesData[]= +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_CHTVONTSCDesData[]= +{ + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_CHTVUPALDesData[]= +{ + {256, 0}, + {256, 0}, + {256, 0}, + {256, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +static const SiS310_LVDSDesStruct SiS310_CHTVOPALDesData[]= +{ + {256, 0}, + {256, 0}, + {256, 0}, + {256, 0}, + { 0, 0}, + { 0, 0}, + { 0, 0} +}; + +typedef struct _SiS310_Part2PortTblStruct +{ + UCHAR CR[12]; +} SiS310_Part2PortTblStruct; + +static const SiS310_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}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}} +}; + +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_1[] = +{ /* TW: Temporary data, invalid */ + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}} +}; + +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_1[] = +{ /* TW: Temporary data, invalid */ + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}} +}; + +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_1[] = +{ /* TW: Temporary data, invalid */ + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}} +}; + +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_2[] = +{ + {{0x25,0x12,0x51,0x6e,0x48,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}}, + {{0x2c,0x12,0x38,0x55,0x2f,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}}, + {{0x25,0x12,0x51,0x6e,0x48,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}}, + {{0x2c,0x12,0x38,0x55,0x2f,0xc1,0x35,0xb1,0x47,0xe9,0x71,0x33}}, + {{0x2d,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}}, + {{0x29,0x12,0xb5,0xd2,0xac,0xe9,0x35,0xd9,0x47,0x11,0x99,0x33}}, + {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_2[] = +{ + {{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,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,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}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +}; + +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_2[] = +{ + {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x33,0x13,0x01,0x0d,0xfd,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x3f,0x1b,0x3d,0x49,0x39,0x54,0x23,0xc0,0x27,0x66,0x30,0x42}}, + {{0x33,0x1b,0x91,0x9d,0x8d,0x8c,0x23,0xf8,0x27,0x9e,0x68,0x42}}, + {{0x43,0x24,0x11,0x1d,0x0d,0xcc,0x23,0x38,0x37,0xde,0xa8,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}} +}; + +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_2[] = +{ /* TW: Temporary data, invalid */ + {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x33,0x13,0x01,0x0d,0xfd,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}}, + {{0x3f,0x1b,0x3d,0x49,0x39,0x54,0x23,0xc0,0x27,0x66,0x30,0x42}}, + {{0x33,0x1b,0x91,0x9d,0x8d,0x8c,0x23,0xf8,0x27,0x9e,0x68,0x42}}, + {{0x43,0x24,0x11,0x1d,0x0d,0xcc,0x23,0x38,0x37,0xde,0xa8,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}} +}; + + +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_3[] = +{ /* TW: Data from 650/301LVx 1.10.6s */ + {{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,0x24,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,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + {{0x25,0x13,0xc9,0x25,0xff,0xf9,0x45,0x09,0x07,0xf9,0x09,0x24}} +#if 0 /* TW: Data from 650/301LV */ + {{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,0x13,0x25,0xff,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}}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} +#endif +}; + +/* 1 2 4 5 6 1c 1d 1f 20 21 23 25 */ +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_3[] = +{ /* TW: Temporary data, invalid */ + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}} +}; + +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_3[] = +{ /* TW: Temporary data, invalid */ + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}} +}; + +static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_3[] = +{ /* TW: Temporary data, invalid */ + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}, + {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}} +}; + +typedef struct _SiS310_LCDACRT1DataStruct +{ + UCHAR CR[17]; +}SiS310_LCDACRT1DataStruct; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT1800x600_1[] = +{ + {{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,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,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_1[]= +{ /* TW: Checked (1.10.6s) */ + {{0x73,0x4f,0x4f,0x97,0x55,0x86,0xc4,0x1f, + 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05, + 0x00}}, + {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x97,0x1f, + 0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05, + 0x00}}, + {{0x73,0x4f,0x4f,0x97,0x55,0x86,0xc4,0x1f, + 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05, + 0x00}}, + {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x97,0x1f, + 0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05, + 0x00}}, + {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x04,0x3e, + 0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x05, + 0x00}}, + {{0x87,0x63,0x63,0x8B,0x69,0x1A,0x7c,0xf0, + 0x5A,0x8F,0x57,0x57,0x7D,0x20,0x00,0x26, + 0x01}}, + {{0xA3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xFf,0xFf,0x25,0x10,0x00,0x02, + 0x01}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_1[]= +{ /* Checked (1.10.6s) */ + {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0xb8,0x1f, + 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06, + 0x00}}, + {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x86,0x1f, + 0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06, + 0x00}}, + {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0xb8,0x1f, + 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06, + 0x00}}, + {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x86,0x1f, + 0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06, + 0x00}}, + {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x08,0x3e, + 0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x06, + 0x00}}, + {{0x92,0x63,0x63,0x96,0x6c,0x1a,0x80,0xf0, + 0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x06, + 0x01}}, + {{0xae,0x7f,0x7f,0x92,0x88,0x96,0x28,0xf5, + 0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x02, + 0x01}}, + {{0xce,0x9f,0x9f,0x92,0xa8,0x16,0x28,0x5a, + 0x00,0x84,0xff,0xff,0x29,0x01,0x00,0x07, + 0x01}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_1[]= +{ /* Checked (1.10.6s) */ + {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x9e,0x1f, + 0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x6c,0x1f, + 0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x9e,0x1f, + 0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x6c,0x1f, + 0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0xee,0x1f, + 0xe2,0x86,0xdf,0xdf,0xef,0x10,0x00,0x05, + 0x00}}, + {{0x83,0x63,0x63,0x87,0x68,0x16,0x66,0xf0, + 0x5a,0x8e,0x57,0x57,0x67,0x20,0x00,0x06, + 0x01}}, + {{0x9f,0x7f,0x7f,0x83,0x84,0x92,0x0e,0xf5, + 0x02,0x86,0xff,0xff,0x0f,0x10,0x00,0x02, + 0x01}}, + {{0xbf,0x9f,0x9f,0x83,0xa4,0x12,0x0e,0x5a, + 0x02,0x86,0xff,0xff,0x0f,0x09,0x00,0x07, + 0x01}}, + {{0xce,0xae,0xae,0x92,0xb3,0x01,0x28,0x10, + 0x1a,0x80,0x19,0x19,0x29,0x0f,0x00,0x03, + 0x00}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11600x1200_1[]= +{ /* MISSING */ + {{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,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,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,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,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,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT1800x600_1_H[]= +{ + {{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,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,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_1_H[]= +{ /* TW: Checked (1.10.6s) */ + {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0xc4,0x1f, + 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x44, + 0x00}}, + {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0x97,0x1f, + 0x60,0x87,0x5D,0x5D,0x83,0x01,0x00,0x44, + 0x00}}, + {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0xc4,0x1f, + 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x44, + 0x00}}, + {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0x97,0x1f, + 0x60,0x87,0x5D,0x5D,0x83,0x01,0x00,0x44, + 0x00}}, + {{0x4b,0x27,0x27,0x8f,0x32,0x1b,0x04,0x3e, + 0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x45, + 0x00}}, + {{0x55,0x31,0x31,0x99,0x46,0x1d,0x7c,0xf0, + 0x5A,0x8F,0x57,0x57,0x7D,0x20,0x00,0x55, + 0x01}}, + {{0x63,0x3F,0x3F,0x87,0x4a,0x93,0x24,0xf5, + 0x02,0x88,0xFf,0xFf,0x25,0x10,0x00,0x01, + 0x01}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_1_H[]= +{ /* Checked (1.10.6s) */ + {{0x56,0x27,0x27,0x9a,0x30,0x1e,0xb8,0x1f, + 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x3c,0x4f,0x4f,0x82,0x58,0x06,0x86,0xd1, /* <-- Invalid data - one byte missing in BIOS */ + 0xbc,0x80,0xbb,0xbb,0xe5,0x00,0x00,0x06, + 0x01}}, + {{0x56,0x27,0x27,0x9a,0x30,0x1e,0xb8,0x1f, + 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05, + 0x00}}, + {{0x3c,0x4f,0x4f,0x82,0x58,0x06,0x86,0xd1, + 0xbc,0x80,0xbb,0xbb,0xe5,0x00,0x00,0x06, + 0x01}}, + {{0x56,0x27,0x27,0x9a,0x30,0x1e,0x08,0x3e, + 0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x05, + 0x00}}, + {{0x60,0x31,0x31,0x84,0x3a,0x88,0x80,0xf0, + 0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x01, + 0x01}}, + {{0x6e,0x3f,0x3f,0x92,0x48,0x96,0x28,0xf5, + 0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x01, + 0x01}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_1_H[]= +{ /* Checked (1.10.6s) */ + {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x9e,0x1f, + 0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, + 0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x27,0x8b,0x30,0x1e,0x9e,0x1f, + 0x92,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x6c,0x1f, + 0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05, + 0x00}}, + {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0xee,0x1f, + 0xe2,0x86,0xdf,0xdf,0xef,0x10,0x00,0x05, + 0x00}}, + {{0x51,0x31,0x31,0x95,0x36,0x04,0x66,0xf0, + 0x5a,0x8e,0x57,0x57,0x67,0x20,0x00,0x01, + 0x01}}, + {{0x5f,0x3f,0x3f,0x83,0x44,0x92,0x0e,0xf5, + 0x02,0x86,0xff,0xff,0x0f,0x10,0x00,0x01, + 0x01}}, + {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x0e,0x5a, + 0x02,0x86,0xff,0xff,0x0f,0x09,0x00,0x05, + 0x01}}, + {{0x76,0x56,0x56,0x9a,0x5b,0x89,0x28,0x10, + 0x1c,0x80,0x19,0x19,0x29,0x0b,0x00,0x05, + 0x00}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11600x1200_1_H[]= +{ /* MISSING */ + {{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,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,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,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,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,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT1800x600_2[]= +{ + {{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,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,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_2[]= +{ /* Checked (1.10.6s) */ + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x63,0x63,0x87,0x78,0x89,0x24,0xf1, + 0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x02, + 0x01}}, + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, + 0x01}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_2[]= +{ /* Checked (1.10.6s) */ + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb, + 0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x06, + 0x00}}, + {{0xa3,0x63,0x63,0x87,0x78,0x89,0x24,0xf1, + 0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x02, + 0x01}}, + {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02, + 0x01}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_2[]= +{ /* Checked (1.10.6s) */ + {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a, + 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x03, + 0x00}}, + {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a, + 0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x03, + 0x01}}, + {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a, + 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x03, + 0x00}}, + {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a, + 0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x03, + 0x00}}, + {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9e, + 0x03,0x87,0xdf,0xdf,0x29,0x01,0x00,0x03, + 0x00}}, + {{0xce,0x63,0x63,0x92,0x96,0x04,0x28,0xd4, + 0x3f,0x83,0x57,0x57,0x29,0x01,0x00,0x07, + 0x01}}, + {{0xce,0x7f,0x7f,0x92,0xa4,0x12,0x28,0xd4, + 0x93,0x87,0xff,0xff,0x29,0x21,0x00,0x07, + 0x01}}, + {{0xce,0x9f,0x9f,0x92,0xb4,0x02,0x28,0x5a, + 0x13,0x87,0xff,0xff,0x29,0x29,0x00,0x03, + 0x01}}, + {{0xce,0xae,0xae,0x92,0xbc,0x0a,0x28,0x10, + 0x20,0x84,0x19,0x19,0x29,0x0f,0x00,0x03, + 0x00}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11600x1200_2[]= +{ /* MISSING */ + {{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,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,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,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,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,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT1800x600_2_H[]= +{ + {{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,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,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_2_H[]= +{ /* Checked (1.10.6s) */ + {{0x4f,0x27,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x31,0x87,0x8d,0x5d,0x25,0x30,0x00,0x01, /* <-- invalid data */ + 0x00 }}, + {{0x4f,0x27,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x27,0x93,0x39,0x01,0x24,0xbb, + 0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x31,0x31,0x93,0x3e,0x06,0x24,0xf1, + 0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x01, /* <-- invalid data */ + 0x01 }}, + {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5, + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01, + 0x01 }} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_2_H[]= +{ /* Checked (1.10.6s) */ + {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb, + 0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x01, + 0x00 }}, + {{0x4f,0x31,0x31,0x93,0x3e,0x86,0x24,0xf1, + 0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x01, + 0x01 }}, + {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5, + 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01, + 0x01 }} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_2_H[]= +{ /* Checked (1.10.6s) */ + {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a, + 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x06, + 0x00}}, + {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a, + 0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x06, + 0x00}}, + {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a, + 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x06, + 0x00}}, + {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a, + 0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x06, + 0x00}}, + {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9e, + 0x03,0x87,0xdf,0xdf,0x29,0x01,0x00,0x06, + 0x00}}, + {{0x9c,0x31,0x31,0x80,0x64,0x92,0x28,0xd4, + 0x3f,0x83,0x57,0x57,0x29,0x01,0x00,0x06, + 0x01}}, + {{0x8e,0x3f,0x3f,0x92,0x64,0x12,0x28,0xd4, + 0x93,0x87,0xff,0xff,0x29,0x21,0x00,0x06, + 0x01}}, + {{0x7e,0x4f,0x4f,0x82,0x64,0x12,0x28,0x5a, + 0x13,0x87,0xff,0xff,0x29,0x29,0x00,0x06, + 0x01}}, + {{0x76,0x56,0x56,0x9a,0x64,0x92,0x28,0x10, + 0x20,0x84,0x19,0x19,0x29,0x0f,0x00,0x05, + 0x00}} +}; + +static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11600x1200_2_H[]= +{ /* MISSING */ + {{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,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,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,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,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,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00}} +}; + +typedef struct _SiS310_LVDSCRT1DataStruct +{ + UCHAR CR[15]; +} SiS310_LVDSCRT1DataStruct; + +static const SiS310_LVDSCRT1DataStruct SiS310_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 SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1[] = /* TW: New */ +{ + {{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 SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1[] = /* TW: New */ +{ + {{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 SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1[] = /* TW: New */ +{ + {{0x7e,0x4f,0x82,0x56,0x04,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06, + 0x00 }}, + {{0x7e,0x4f,0x82,0x56,0x04,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06, + 0x00 }}, + {{0x7e,0x4f,0x82,0x56,0x04,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06, + 0x00 }}, + {{0x7e,0x4f,0x82,0x56,0x04,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06, + 0x00 }}, + {{0x7e,0x4f,0x82,0x56,0x04,0x08,0x3e, + 0xe0,0x84,0xdf,0x09,0x00,0x00,0x06, + 0x00 }}, + {{0x92,0x63,0x96,0x6a,0x18,0x80,0xf0, + 0x58,0x8c,0x57,0x81,0x20,0x00,0x06, + 0x01 }}, + {{0xae,0x7f,0x92,0x86,0x94,0x28,0xf5, + 0x00,0x84,0xff,0x29,0x10,0x00,0x02, + 0x01 }}, + {{0xce,0x9f,0x92,0xa6,0x14,0x28,0x5a, + 0x00,0x84,0xff,0x29,0x09,0x00,0x07, + 0x01}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1_H[] = /* TW: New */ +{ + {{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 SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_1_H[] = /* TW: New */ +{ + {{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 SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_1_H[] = /* TW: New */ +{ + {{0x56,0x27,0x9a,0x2e,0x1c,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05, + 0x00 }}, + {{0x56,0x27,0x9a,0x2e,0x1c,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05, + 0x00 }}, + {{0x56,0x27,0x9a,0x2e,0x1c,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05, + 0x00 }}, + {{0x56,0x27,0x9a,0x2e,0x1c,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05, + 0x01 }}, + {{0x56,0x27,0x9a,0x2e,0x1c,0x08,0x3e, + 0xe0,0x84,0xdf,0x09,0x00,0x00,0x05, + 0x00 }}, + {{0x60,0x31,0x84,0x38,0x86,0x80,0xf0, + 0x58,0x8c,0x57,0x81,0x20,0x00,0x01, + 0x01 }}, + {{0x6e,0x3f,0x92,0x46,0x94,0x28,0xf5, + 0x00,0x84,0xff,0x29,0x10,0x00,0x01, + 0x01 }} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2[]= /* TW: New */ +{ + {{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 SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2[] = /* TW: New */ +{ + {{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 SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2[] = /* TW: New */ +{ + {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9a, + 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03, + 0x00 }}, + {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9a, + 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03, + 0x00 }}, + {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9a, + 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03, + 0x00 }}, + {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9a, + 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03, + 0x00 }}, + {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9e, + 0x03,0x87,0xdf,0x29,0x01,0x00,0x03, + 0x00 }}, + {{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,0xa6,0x14,0x28,0x5a, + 0x00,0x84,0xff,0x29,0x09,0x00,0x07, + 0x01}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_2_H[] = /* TW: New */ +{ + {{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 SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x768_2_H[] = /* TW: New */ +{ + {{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 SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x1024_2_H[] = /* TW: New */ +{ + {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9a, + 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06, + 0x00 }}, + {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9a, + 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06, + 0x00 }}, + {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9a, + 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06, + 0x00 }}, + {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9a, + 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06, + 0x00 }}, + {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9e, + 0x03,0x87,0xdf,0x29,0x01,0x00,0x06, + 0x00 }}, + {{0x9c,0x31,0x80,0x59,0x87,0x28,0xd4, + 0x3f,0x83,0x57,0x29,0x01,0x00,0x06, + 0x01 }}, + {{0x8e,0x3f,0x92,0x79,0x07,0x28,0xd4, + 0x93,0x87,0xff,0x29,0x21,0x00,0x06, + 0x01}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1XXXxXXX_1[] = /* TW: New */ +{ + {{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,0xa9,0x17,0x24,0xf5, + 0x02,0x88,0xff,0x25,0x10,0x00,0x07, + 0x01}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1XXXxXXX_1_H[] = /* TW: New */ +{ + {{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 SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1[] = /* TW: New */ +{ + {{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}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1_H[] = /* TW: New */ +{ + {{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}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_2[] = /* TW: New */ +{ + {{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}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_2_H[] = /* TW: New */ +{ + {{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}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x768_1[] = /* TW: New */ +{ /* TW: Temp data, invalid */ + {{0x7e,0x4f,0x82,0x56,0x04,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06, + 0x00 }}, + {{0x7e,0x4f,0x82,0x56,0x04,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06, + 0x00 }}, + {{0x7e,0x4f,0x82,0x56,0x04,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x06, + 0x00 }}, + {{0x7e,0x4f,0x82,0x56,0x04,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x06, + 0x00 }}, + {{0x7e,0x4f,0x82,0x56,0x04,0x08,0x3e, + 0xe0,0x84,0xdf,0x09,0x00,0x00,0x06, + 0x00 }}, + {{0x92,0x63,0x96,0x6a,0x18,0x80,0xf0, + 0x58,0x8c,0x57,0x81,0x20,0x00,0x06, + 0x01 }}, + {{0xae,0x7f,0x92,0x86,0x94,0x28,0xf5, + 0x00,0x84,0xff,0x29,0x10,0x00,0x02, + 0x01 }}, + {{0xce,0x9f,0x92,0xa6,0x14,0x28,0x5a, + 0x00,0x84,0xff,0x29,0x09,0x00,0x07, + 0x01}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x768_1_H[] = /* TW: New */ +{ /* TW: Temp data, invalid */ + {{0x56,0x27,0x9a,0x2e,0x1c,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05, + 0x00 }}, + {{0x56,0x27,0x9a,0x2e,0x1c,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05, + 0x00 }}, + {{0x56,0x27,0x9a,0x2e,0x1c,0xb8,0x1f, + 0x90,0x84,0x8f,0xb9,0x30,0x00,0x05, + 0x00 }}, + {{0x56,0x27,0x9a,0x2e,0x1c,0x86,0x1f, + 0x5e,0x82,0x5d,0x87,0x10,0x00,0x05, + 0x01 }}, + {{0x56,0x27,0x9a,0x2e,0x1c,0x08,0x3e, + 0xe0,0x84,0xdf,0x09,0x00,0x00,0x05, + 0x00 }}, + {{0x60,0x31,0x84,0x38,0x86,0x80,0xf0, + 0x58,0x8c,0x57,0x81,0x20,0x00,0x01, + 0x01 }}, + {{0x6e,0x3f,0x92,0x46,0x94,0x28,0xf5, + 0x00,0x84,0xff,0x29,0x10,0x00,0x01, + 0x01 }} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x768_2[] = /* TW: New */ +{ /* TW: Temp data, invalid */ + {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9a, + 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03, + 0x00 }}, + {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9a, + 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03, + 0x00 }}, + {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9a, + 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03, + 0x00 }}, + {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9a, + 0xc2,0x86,0x5d,0x29,0x01,0x00,0x03, + 0x00 }}, + {{0xce,0x4f,0x92,0x81,0x0f,0x28,0x9e, + 0x03,0x87,0xdf,0x29,0x01,0x00,0x03, + 0x00 }}, + {{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,0xa6,0x14,0x28,0x5a, + 0x00,0x84,0xff,0x29,0x09,0x00,0x07, + 0x01}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x768_2_H[] = /* TW: New */ +{ /* TW: Temp data, invalid */ + {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9a, + 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06, + 0x00 }}, + {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9a, + 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06, + 0x00 }}, + {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9a, + 0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06, + 0x00 }}, + {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9a, + 0xc2,0x86,0x5d,0x29,0x01,0x00,0x06, + 0x00 }}, + {{0xa6,0x27,0x8a,0x59,0x87,0x28,0x9e, + 0x03,0x87,0xdf,0x29,0x01,0x00,0x06, + 0x00 }}, + {{0x9c,0x31,0x80,0x59,0x87,0x28,0xd4, + 0x3f,0x83,0x57,0x29,0x01,0x00,0x06, + 0x01 }}, + {{0x8e,0x3f,0x92,0x79,0x07,0x28,0xd4, + 0x93,0x87,0xff,0x29,0x21,0x00,0x06, + 0x01}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_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 SiS310_LVDSCRT1DataStruct SiS310_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 SiS310_LVDSCRT1DataStruct SiS310_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 SiS310_LVDSCRT1DataStruct SiS310_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 SiS310_LVDSCRT1DataStruct SiS310_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 SiS310_LVDSCRT1DataStruct SiS310_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 SiS310_LVDSCRT1DataStruct SiS310_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 SiS310_LVDSCRT1DataStruct SiS310_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 SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1[] = +{ /* TW: Temporary data - invalid */ + {{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}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1_H[] = +{ /* TW: Temporary data - invalid */ + {{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}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_2[] = +{ /* TW: Temporary data - invalid */ + {{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}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_2_H[] = /* TW: New */ +{ /* TW: Temporary data - invalid */ + {{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}} +}; + + +static const SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1UNTSC[] = /* TW: New */ +{ + {{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, /* TW: 1024x768 */ + 0x36,0x88,0xff,0xb0,0x10,0x00,0x02, + 0x01}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1ONTSC[] = /* TW: New */ +{ + {{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, /* TW: 1024x768 */ + 0x15,0x88,0xff,0x47,0x70,0x00,0x02, + 0x01 }} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1UPAL[] = /* TW: New */ +{ + {{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, /* TW: 1024x768 */ + 0x50,0x88,0xff,0xe7,0x10,0x00,0x02, + 0x01}} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1OPAL[] = /* TW: New */ +{ + {{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, /* TW: 1024x768 */ + 0x28,0x88,0xff,0x6a,0x10,0x00,0x02, + 0x01 }} +}; + +static const SiS310_LVDSCRT1DataStruct SiS310_CHTVCRT1SOPAL[] = /* TW: New */ +{ + {{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, /* TW: 1024x768 */ + 0x28,0x88,0xff,0x6a,0x10,0x00,0x02, + 0x01 }} +}; + +/* TW: New data for Chrontel 7019 (From 650/LVDS BIOS 1.10.0) */ +typedef struct _SiS310_CHTVRegDataStruct +{ + UCHAR Reg[16]; +} SiS310_CHTVRegDataStruct; + +static const SiS310_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}} +}; + +static const SiS310_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 SiS310_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 SiS310_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 SiS310_CHTVRegDataStruct SiS310_CHTVReg_SOPAL[] = +{ + {{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 SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] = +{ + {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{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}} +}; + +static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] = +{ + {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}}, + {{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}} +}; + +static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] = +{ + {{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,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}} +}; + +static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] = +{ + {{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,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}} +}; + +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_CHTVVCLKSOPAL[] = {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}; + +/* TW: New end */ diff --git a/src/init.c b/src/init.c new file mode 100644 index 0000000..74c302c --- /dev/null +++ b/src/init.c @@ -0,0 +1,5968 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/init.c,v 1.6 2003/02/04 02:44:28 dawes Exp $ */ +/* + * Mode switching code (CRT1 section) for SiS 300/540/630/730/315/550/650/740/330 + * (Universal module for Linux kernel framebuffer and XFree86 4.x) + * + * Assembler-To-C translation + * Copyright 2002 by Thomas Winischhofer <thomas@winischhofer.net> + * Minor parts Copyright SiS, Inc. + * + * Based on BIOS + * 1.10.07, 1.10a for SiS650/LVDS+CH7019 + * 1.11.05 for 650/LVDS (w/o Chrontel) + * 1.07.1b, 1.11.6s, 1.11.6w, 1.11.7w, 1.11.8r for SiS650/301(B/LV) + * 2.04.50 (I) and 2.04.5c (II) for SiS630/301(B) + * 2.06.50 for 630/301B (dual VGA) + * 2.02.3b, 2.03.02, 2.04.5c, 2.07a and 2.08.b3 for 630/LVDS/LVDS+CH7005 + * 2.04.5c, 2.04.6c for 730+LVDS+CH7005 + * 1.09b for 315/301(B) + * 1.16.51 for 300+301LVX (ECS A907) + * 1.01.03 for 330 (Xabre 400) + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holder not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The copyright holder makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * 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 + +#ifdef LINUX_XF86 +BOOLEAN SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + ScrnInfoPtr pScrn, DisplayModePtr mode, BOOLEAN IsCustom); +DisplayModePtr SiSBuildBuiltInModeList(ScrnInfoPtr pScrn); +#ifdef SISDUALHEAD /* TW: For dual head */ +BOOLEAN SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + ScrnInfoPtr pScrn, DisplayModePtr mode, BOOLEAN IsCustom); +BOOLEAN SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + ScrnInfoPtr pScrn, DisplayModePtr mode); +#endif /* dual head */ +#endif /* linux_xf86 */ + +#ifdef LINUXBIOS +BOOLEAN SiSInit(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +#endif + +#ifdef LINUX_XF86 +BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch); +#else +BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT ModeNo); +#endif + +#if defined(ALLOC_PRAGMA) +#pragma alloc_text(PAGE,SiSSetMode) +#pragma alloc_text(PAGE,SiSInit) +#endif + +static ULONG GetDRAMSize(SiS_Private *SiS_Pr, + PSIS_HW_DEVICE_INFO HwDeviceExtension); + +static void DelaySeconds(int seconds); +void SiS_DebugCode(SiS_Private *SiS_Pr, UCHAR code); + +#ifdef LINUX_XF86 +/* TW: Mode table for X driver */ +const UShort ModeIndex_320x480[] = {0x5a, 0x5b, 0x00, 0x00}; /* DSTN/FSTN */ +const UShort ModeIndex_512x384[] = {0x52, 0x58, 0x00, 0x5c}; +const UShort ModeIndex_640x400[] = {0x2f, 0x5d, 0x00, 0x5e}; +const UShort ModeIndex_640x480[] = {0x2e, 0x44, 0x00, 0x62}; +const UShort ModeIndex_720x480[] = {0x31, 0x33, 0x00, 0x35}; +const UShort ModeIndex_720x576[] = {0x32, 0x34, 0x00, 0x36}; +const UShort ModeIndex_800x480[] = {0x70, 0x7a, 0x00, 0x76}; +const UShort ModeIndex_800x600[] = {0x30, 0x47, 0x00, 0x63}; +const UShort ModeIndex_848x480[] = {0x39, 0x3b, 0x00, 0x3e}; +const UShort ModeIndex_856x480[] = {0x3f, 0x42, 0x00, 0x45}; +const UShort ModeIndex_1024x768[] = {0x38, 0x4a, 0x00, 0x64}; +const UShort ModeIndex_1024x576[] = {0x71, 0x74, 0x00, 0x77}; +const UShort ModeIndex_1024x600[] = {0x20, 0x21, 0x00, 0x22}; /* 300 series only */ +const UShort ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65}; +const UShort ModeIndex_300_1280x960[] = {0x6e, 0x6f, 0x00, 0x7b}; +const UShort ModeIndex_310_1280x960[] = {0x7c, 0x7d, 0x00, 0x7e}; +const UShort ModeIndex_1152x768[] = {0x23, 0x24, 0x00, 0x25}; /* 300 series only */ +const UShort ModeIndex_1152x864[] = {0x29, 0x2a, 0x00, 0x2b}; +const UShort ModeIndex_1280x768[] = {0x23, 0x24, 0x00, 0x25}; /* 310/325 series only */ +const UShort ModeIndex_1280x720[] = {0x79, 0x75, 0x00, 0x78}; +const UShort ModeIndex_1360x768[] = {0x48, 0x4b, 0x00, 0x4e}; +const UShort ModeIndex_1400x1050[] = {0x26, 0x27, 0x00, 0x28}; /* 310/325 series only */ +const UShort ModeIndex_1600x1200[] = {0x3c, 0x3d, 0x00, 0x66}; +const UShort ModeIndex_1920x1440[] = {0x68, 0x69, 0x00, 0x6b}; +const UShort ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00}; +const UShort ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e}; +#endif + +static void +DelaySeconds(int seconds) +{ + int i; +#ifdef WIN2000 + int j; +#endif + + for (i=0;i<seconds;i++) { +#ifdef TC + delay(1000); +#endif + +#ifdef WIN2000 + for (j=0;j<20000;j++) + VideoPortStallExecution(50); +#endif + +#ifdef WINCE_HEADER +#endif + +#ifdef LINUX_KERNEL +#endif + } +} + +void +SiS_DebugCode(SiS_Private *SiS_Pr, UCHAR code) +{ + OutPortByte(0x80, code); + DelaySeconds(0x3); +} + +#ifdef SIS300 +static void +InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + SiS_Pr->SiS_SModeIDTable = (SiS_StStruct *)SiS300_SModeIDTable; + SiS_Pr->SiS_VBModeIDTable = (SiS_VBModeStruct *)SiS300_VBModeIDTable; + SiS_Pr->SiS_StandTable = (SiS_StandTableStruct *)SiS300_StandTable; + SiS_Pr->SiS_EModeIDTable = (SiS_ExtStruct *)SiS300_EModeIDTable; + SiS_Pr->SiS_RefIndex = (SiS_Ext2Struct *)SiS300_RefIndex; + SiS_Pr->SiS_CRT1Table = (SiS_CRT1TableStruct *)SiS300_CRT1Table; + if(HwDeviceExtension->jChipType == SIS_300) { + SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS300_MCLKData_300; /* 300 */ + } else { + SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS300_MCLKData_630; /* 630 */ + } + SiS_Pr->SiS_ECLKData = (SiS_ECLKDataStruct *)SiS300_ECLKData; + SiS_Pr->SiS_VCLKData = (SiS_VCLKDataStruct *)SiS300_VCLKData; + SiS_Pr->SiS_VBVCLKData = (SiS_VBVCLKDataStruct *)SiS300_VCLKData; + SiS_Pr->SiS_ScreenOffset = SiS300_ScreenOffset; + SiS_Pr->SiS_StResInfo = (SiS_StResInfoStruct *)SiS300_StResInfo; + SiS_Pr->SiS_ModeResInfo = (SiS_ModeResInfoStruct *)SiS300_ModeResInfo; + + SiS_Pr->pSiS_OutputSelect = &SiS300_OutputSelect; + SiS_Pr->pSiS_SoftSetting = &SiS300_SoftSetting; + + SiS_Pr->SiS_SR15 = SiS300_SR15; + +#ifndef LINUX_XF86 + 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_NTSCPhase = SiS300_NTSCPhase; + SiS_Pr->SiS_PALPhase = SiS300_PALPhase; + SiS_Pr->SiS_NTSCPhase2 = SiS300_NTSCPhase2; + SiS_Pr->SiS_PALPhase2 = SiS300_PALPhase2; + SiS_Pr->SiS_PALMPhase = SiS300_PALMPhase; + SiS_Pr->SiS_PALNPhase = SiS300_PALNPhase; + SiS_Pr->SiS_PALMPhase2 = SiS300_PALMPhase2; + SiS_Pr->SiS_PALNPhase2 = SiS300_PALNPhase2; + + SiS_Pr->SiS_StLCD1024x768Data = (SiS_LCDDataStruct *)SiS300_StLCD1024x768Data; + SiS_Pr->SiS_ExtLCD1024x768Data = (SiS_LCDDataStruct *)SiS300_ExtLCD1024x768Data; + SiS_Pr->SiS_St2LCD1024x768Data = (SiS_LCDDataStruct *)SiS300_St2LCD1024x768Data; + SiS_Pr->SiS_StLCD1280x1024Data = (SiS_LCDDataStruct *)SiS300_StLCD1280x1024Data; + SiS_Pr->SiS_ExtLCD1280x1024Data = (SiS_LCDDataStruct *)SiS300_ExtLCD1280x1024Data; + SiS_Pr->SiS_St2LCD1280x1024Data = (SiS_LCDDataStruct *)SiS300_St2LCD1280x1024Data; + SiS_Pr->SiS_NoScaleData1024x768 = (SiS_LCDDataStruct *)SiS300_NoScaleData1024x768; + SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS300_NoScaleData1280x1024; + SiS_Pr->SiS_LCD1280x960Data = (SiS_LCDDataStruct *)SiS300_LCD1280x960Data; + SiS_Pr->SiS_ExtLCD1400x1050Data = (SiS_LCDDataStruct *)SiS300_ExtLCD1400x1050Data; + SiS_Pr->SiS_ExtLCD1600x1200Data = (SiS_LCDDataStruct *)SiS300_ExtLCD1600x1200Data; + SiS_Pr->SiS_StLCD1400x1050Data = (SiS_LCDDataStruct *)SiS300_StLCD1400x1050Data; + SiS_Pr->SiS_StLCD1600x1200Data = (SiS_LCDDataStruct *)SiS300_StLCD1600x1200Data; + SiS_Pr->SiS_NoScaleData1400x1050 = (SiS_LCDDataStruct *)SiS300_NoScaleData1400x1050; + SiS_Pr->SiS_NoScaleData1600x1200 = (SiS_LCDDataStruct *)SiS300_NoScaleData1600x1200; + + SiS_Pr->SiS_StPALData = (SiS_TVDataStruct *)SiS300_StPALData; + SiS_Pr->SiS_ExtPALData = (SiS_TVDataStruct *)SiS300_ExtPALData; + SiS_Pr->SiS_StNTSCData = (SiS_TVDataStruct *)SiS300_StNTSCData; + SiS_Pr->SiS_ExtNTSCData = (SiS_TVDataStruct *)SiS300_ExtNTSCData; +#ifdef oldHV + SiS_Pr->SiS_St1HiTVData = (SiS_TVDataStruct *)SiS300_St1HiTVData; + SiS_Pr->SiS_St2HiTVData = (SiS_TVDataStruct *)SiS300_St2HiTVData; + SiS_Pr->SiS_ExtHiTVData = (SiS_TVDataStruct *)SiS300_ExtHiTVData; +#endif + + SiS_Pr->SiS_NTSCTiming = SiS300_NTSCTiming; + SiS_Pr->SiS_PALTiming = SiS300_PALTiming; +#ifdef oldHV + SiS_Pr->SiS_HiTVSt1Timing = SiS300_HiTVSt1Timing; + SiS_Pr->SiS_HiTVSt2Timing = SiS300_HiTVSt2Timing; + SiS_Pr->SiS_HiTVTextTiming = SiS300_HiTVTextTiming; + SiS_Pr->SiS_HiTVGroup3Data = SiS300_HiTVGroup3Data; + SiS_Pr->SiS_HiTVGroup3Simu = SiS300_HiTVGroup3Simu; + SiS_Pr->SiS_HiTVGroup3Text = SiS300_HiTVGroup3Text; +#endif + + SiS_Pr->SiS_PanelDelayTbl = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTbl; + SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTblLVDS; + + SiS_Pr->SiS_LVDS800x600Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS800x600Data_1; + SiS_Pr->SiS_LVDS800x600Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS800x600Data_2; + SiS_Pr->SiS_LVDS1024x768Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1024x768Data_1; + SiS_Pr->SiS_LVDS1024x768Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1024x768Data_2; + SiS_Pr->SiS_LVDS1280x1024Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_1; + SiS_Pr->SiS_LVDS1280x1024Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_2; + SiS_Pr->SiS_LVDS1280x960Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_1; + SiS_Pr->SiS_LVDS1280x960Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_2; + SiS_Pr->SiS_LVDS1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1400x1050Data_1; + SiS_Pr->SiS_LVDS1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1400x1050Data_2; + SiS_Pr->SiS_LVDS1280x768Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x768Data_1; + SiS_Pr->SiS_LVDS1280x768Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x768Data_2; + SiS_Pr->SiS_LVDS1024x600Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1024x600Data_1; + SiS_Pr->SiS_LVDS1024x600Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1024x600Data_2; + SiS_Pr->SiS_LVDS1152x768Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1152x768Data_1; + SiS_Pr->SiS_LVDS1152x768Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1152x768Data_2; + SiS_Pr->SiS_LVDSXXXxXXXData_1 = (SiS_LVDSDataStruct *)SiS300_LVDSXXXxXXXData_1; + SiS_Pr->SiS_LVDS320x480Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS320x480Data_1; + SiS_Pr->SiS_LVDS640x480Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS640x480Data_1; + SiS_Pr->SiS_LCDA1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS300_LCDA1400x1050Data_1; + SiS_Pr->SiS_LCDA1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS300_LCDA1400x1050Data_2; + SiS_Pr->SiS_LCDA1600x1200Data_1 = (SiS_LVDSDataStruct *)SiS300_LCDA1600x1200Data_1; + SiS_Pr->SiS_LCDA1600x1200Data_2 = (SiS_LVDSDataStruct *)SiS300_LCDA1600x1200Data_2; + SiS_Pr->SiS_CHTVUNTSCData = (SiS_LVDSDataStruct *)SiS300_CHTVUNTSCData; + SiS_Pr->SiS_CHTVONTSCData = (SiS_LVDSDataStruct *)SiS300_CHTVONTSCData; + SiS_Pr->SiS_CHTVUPALData = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData; + SiS_Pr->SiS_CHTVOPALData = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData; + SiS_Pr->SiS_CHTVUPALMData = (SiS_LVDSDataStruct *)SiS300_CHTVUNTSCData; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVOPALMData = (SiS_LVDSDataStruct *)SiS300_CHTVONTSCData; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVUPALNData = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS300_CHTVSOPALData; + SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS300_PanelType00_1; + SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS300_PanelType01_1; + SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS300_PanelType02_1; + SiS_Pr->SiS_PanelType03_1 = (SiS_LVDSDesStruct *)SiS300_PanelType03_1; + SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1; + SiS_Pr->SiS_PanelType05_1 = (SiS_LVDSDesStruct *)SiS300_PanelType05_1; + SiS_Pr->SiS_PanelType06_1 = (SiS_LVDSDesStruct *)SiS300_PanelType06_1; + SiS_Pr->SiS_PanelType07_1 = (SiS_LVDSDesStruct *)SiS300_PanelType07_1; + SiS_Pr->SiS_PanelType08_1 = (SiS_LVDSDesStruct *)SiS300_PanelType08_1; + SiS_Pr->SiS_PanelType09_1 = (SiS_LVDSDesStruct *)SiS300_PanelType09_1; + SiS_Pr->SiS_PanelType0a_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0a_1; + SiS_Pr->SiS_PanelType0b_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0b_1; + SiS_Pr->SiS_PanelType0c_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0c_1; + SiS_Pr->SiS_PanelType0d_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0d_1; + SiS_Pr->SiS_PanelType0e_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0e_1; + SiS_Pr->SiS_PanelType0f_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0f_1; + SiS_Pr->SiS_PanelType00_2 = (SiS_LVDSDesStruct *)SiS300_PanelType00_2; + SiS_Pr->SiS_PanelType01_2 = (SiS_LVDSDesStruct *)SiS300_PanelType01_2; + SiS_Pr->SiS_PanelType02_2 = (SiS_LVDSDesStruct *)SiS300_PanelType02_2; + SiS_Pr->SiS_PanelType03_2 = (SiS_LVDSDesStruct *)SiS300_PanelType03_2; + SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2; + SiS_Pr->SiS_PanelType05_2 = (SiS_LVDSDesStruct *)SiS300_PanelType05_2; + SiS_Pr->SiS_PanelType06_2 = (SiS_LVDSDesStruct *)SiS300_PanelType06_2; + SiS_Pr->SiS_PanelType07_2 = (SiS_LVDSDesStruct *)SiS300_PanelType07_2; + SiS_Pr->SiS_PanelType08_2 = (SiS_LVDSDesStruct *)SiS300_PanelType08_2; + SiS_Pr->SiS_PanelType09_2 = (SiS_LVDSDesStruct *)SiS300_PanelType09_2; + SiS_Pr->SiS_PanelType0a_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0a_2; + SiS_Pr->SiS_PanelType0b_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0b_2; + SiS_Pr->SiS_PanelType0c_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0c_2; + SiS_Pr->SiS_PanelType0d_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0d_2; + SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0e_2; + SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0f_2; + SiS_Pr->SiS_CHTVUNTSCDesData = (SiS_LVDSDesStruct *)SiS300_CHTVUNTSCDesData; + SiS_Pr->SiS_CHTVONTSCDesData = (SiS_LVDSDesStruct *)SiS300_CHTVONTSCDesData; + SiS_Pr->SiS_CHTVUPALDesData = (SiS_LVDSDesStruct *)SiS300_CHTVUPALDesData; + SiS_Pr->SiS_CHTVOPALDesData = (SiS_LVDSDesStruct *)SiS300_CHTVOPALDesData; + SiS_Pr->SiS_LVDSCRT1800x600_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1; + SiS_Pr->SiS_LVDSCRT11024x768_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1; + SiS_Pr->SiS_LVDSCRT11280x1024_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1; + SiS_Pr->SiS_LVDSCRT11024x600_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_1; + SiS_Pr->SiS_LVDSCRT11152x768_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_1; + SiS_Pr->SiS_LVDSCRT1800x600_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1_H; + SiS_Pr->SiS_LVDSCRT11024x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1_H; + SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1_H; + SiS_Pr->SiS_LVDSCRT11024x600_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_1_H; + SiS_Pr->SiS_LVDSCRT11152x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_1_H; + SiS_Pr->SiS_LVDSCRT1800x600_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2; + SiS_Pr->SiS_LVDSCRT11024x768_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2; + SiS_Pr->SiS_LVDSCRT11280x1024_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2; + SiS_Pr->SiS_LVDSCRT11024x600_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_2; + SiS_Pr->SiS_LVDSCRT11152x768_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_2; + SiS_Pr->SiS_LVDSCRT1800x600_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2_H; + SiS_Pr->SiS_LVDSCRT11024x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2_H; + SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2_H; + SiS_Pr->SiS_LVDSCRT11024x600_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_2_H; + SiS_Pr->SiS_LVDSCRT11152x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_2_H; + SiS_Pr->SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UNTSC; + SiS_Pr->SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1ONTSC; + SiS_Pr->SiS_CHTVCRT1UPAL = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UPAL; + SiS_Pr->SiS_CHTVCRT1OPAL = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1OPAL; + SiS_Pr->SiS_CHTVCRT1SOPAL = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1SOPAL; + SiS_Pr->SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UNTSC; + SiS_Pr->SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_ONTSC; + SiS_Pr->SiS_CHTVReg_UPAL = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UPAL; + SiS_Pr->SiS_CHTVReg_OPAL = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_OPAL; + SiS_Pr->SiS_CHTVReg_UPALM = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UNTSC; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVReg_OPALM = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_ONTSC; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVReg_UPALN = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UPAL; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVReg_OPALN = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_OPAL; /* not supported on 300 series */ + SiS_Pr->SiS_CHTVReg_SOPAL = (SiS_CHTVRegDataStruct *)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; + + /* TW: New from 300/301LV BIOS */ + SiS_Pr->SiS_CRT2Part2_1024x768_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_1; + SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_1; + SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_1; + SiS_Pr->SiS_CRT2Part2_1600x1200_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_1; + SiS_Pr->SiS_CRT2Part2_1024x768_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_2; + SiS_Pr->SiS_CRT2Part2_1280x1024_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_2; + SiS_Pr->SiS_CRT2Part2_1400x1050_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_2; + SiS_Pr->SiS_CRT2Part2_1600x1200_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_2; + SiS_Pr->SiS_CRT2Part2_1024x768_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_3; + SiS_Pr->SiS_CRT2Part2_1280x1024_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_3; + SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_3; + SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_3; + + /* TW: LCDResInfo will on 300 series be translated to 310/325 series definitions */ + SiS_Pr->SiS_Panel320x480 = Panel_320x480; + SiS_Pr->SiS_Panel640x480 = Panel_640x480; + SiS_Pr->SiS_Panel800x600 = Panel_800x600; + SiS_Pr->SiS_Panel1024x768 = Panel_1024x768; + SiS_Pr->SiS_Panel1280x1024 = Panel_1280x1024; + SiS_Pr->SiS_Panel1280x960 = Panel_1280x960; + SiS_Pr->SiS_Panel1024x600 = Panel_1024x600; + SiS_Pr->SiS_Panel1152x768 = Panel_1152x768; + SiS_Pr->SiS_Panel1600x1200 = 16; /* TW: Something illegal */ + SiS_Pr->SiS_Panel1400x1050 = 16; /* TW: Something illegal */ + SiS_Pr->SiS_Panel1152x864 = 16; /* TW: Something illegal */ + SiS_Pr->SiS_Panel1280x768 = 16; /* TW: Something illegal */ + SiS_Pr->SiS_PanelMax = Panel_320x480; /* TW: highest value */ + SiS_Pr->SiS_PanelMinLVDS = Panel_800x600; /* TW: Lowest value LVDS */ + SiS_Pr->SiS_PanelMin301 = Panel_1024x768; /* TW: lowest value 301 */ +} +#endif + +#ifdef SIS315H +static void +InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + SiS_Pr->SiS_SModeIDTable = (SiS_StStruct *)SiS310_SModeIDTable; + SiS_Pr->SiS_StandTable = (SiS_StandTableStruct *)SiS310_StandTable; + SiS_Pr->SiS_EModeIDTable = (SiS_ExtStruct *)SiS310_EModeIDTable; + SiS_Pr->SiS_RefIndex = (SiS_Ext2Struct *)SiS310_RefIndex; + SiS_Pr->SiS_CRT1Table = (SiS_CRT1TableStruct *)SiS310_CRT1Table; + /* TW: MCLK is different */ + if(HwDeviceExtension->jChipType == SIS_330) { + SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_330; /* 330 */ + } else if(HwDeviceExtension->jChipType > SIS_315PRO) { + SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_650; /* 550, 650 */ + } else { + SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_315; /* 315 */ + } + SiS_Pr->SiS_MCLKData_1 = (SiS_MCLKDataStruct *)SiS310_MCLKData_1; + SiS_Pr->SiS_ECLKData = (SiS_ECLKDataStruct *)SiS310_ECLKData; + SiS_Pr->SiS_VCLKData = (SiS_VCLKDataStruct *)SiS310_VCLKData; + SiS_Pr->SiS_VBVCLKData = (SiS_VBVCLKDataStruct *)SiS310_VBVCLKData; + SiS_Pr->SiS_ScreenOffset = SiS310_ScreenOffset; + SiS_Pr->SiS_StResInfo = (SiS_StResInfoStruct *)SiS310_StResInfo; + SiS_Pr->SiS_ModeResInfo = (SiS_ModeResInfoStruct *)SiS310_ModeResInfo; + + SiS_Pr->pSiS_OutputSelect = &SiS310_OutputSelect; + SiS_Pr->pSiS_SoftSetting = &SiS310_SoftSetting; + + SiS_Pr->SiS_SR15 = SiS310_SR15; + +#ifndef LINUX_XF86 + 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_NTSCPhase = SiS310_NTSCPhase; + SiS_Pr->SiS_PALPhase = SiS310_PALPhase; + SiS_Pr->SiS_NTSCPhase2 = SiS310_NTSCPhase2; + SiS_Pr->SiS_PALPhase2 = SiS310_PALPhase2; + SiS_Pr->SiS_PALMPhase = SiS310_PALMPhase; + SiS_Pr->SiS_PALNPhase = SiS310_PALNPhase; + SiS_Pr->SiS_PALMPhase2 = SiS310_PALMPhase2; + SiS_Pr->SiS_PALNPhase2 = SiS310_PALNPhase2; + SiS_Pr->SiS_SpecialPhase = SiS310_SpecialPhase; + + SiS_Pr->SiS_StLCD1024x768Data = (SiS_LCDDataStruct *)SiS310_StLCD1024x768Data; + SiS_Pr->SiS_ExtLCD1024x768Data = (SiS_LCDDataStruct *)SiS310_ExtLCD1024x768Data; + SiS_Pr->SiS_St2LCD1024x768Data = (SiS_LCDDataStruct *)SiS310_St2LCD1024x768Data; + SiS_Pr->SiS_StLCD1280x1024Data = (SiS_LCDDataStruct *)SiS310_StLCD1280x1024Data; + SiS_Pr->SiS_ExtLCD1280x1024Data = (SiS_LCDDataStruct *)SiS310_ExtLCD1280x1024Data; + SiS_Pr->SiS_St2LCD1280x1024Data = (SiS_LCDDataStruct *)SiS310_St2LCD1280x1024Data; + SiS_Pr->SiS_NoScaleData1024x768 = (SiS_LCDDataStruct *)SiS310_NoScaleData1024x768; + SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS310_NoScaleData1280x1024; + SiS_Pr->SiS_LCD1280x960Data = (SiS_LCDDataStruct *)SiS310_LCD1280x960Data; + SiS_Pr->SiS_ExtLCD1400x1050Data = (SiS_LCDDataStruct *)SiS310_ExtLCD1400x1050Data; + SiS_Pr->SiS_ExtLCD1600x1200Data = (SiS_LCDDataStruct *)SiS310_ExtLCD1600x1200Data; + SiS_Pr->SiS_StLCD1400x1050Data = (SiS_LCDDataStruct *)SiS310_StLCD1400x1050Data; + SiS_Pr->SiS_StLCD1600x1200Data = (SiS_LCDDataStruct *)SiS310_StLCD1600x1200Data; + SiS_Pr->SiS_NoScaleData1400x1050 = (SiS_LCDDataStruct *)SiS310_NoScaleData1400x1050; + SiS_Pr->SiS_NoScaleData1600x1200 = (SiS_LCDDataStruct *)SiS310_NoScaleData1600x1200; + + SiS_Pr->SiS_StPALData = (SiS_TVDataStruct *)SiS310_StPALData; + SiS_Pr->SiS_ExtPALData = (SiS_TVDataStruct *)SiS310_ExtPALData; + SiS_Pr->SiS_StNTSCData = (SiS_TVDataStruct *)SiS310_StNTSCData; + SiS_Pr->SiS_ExtNTSCData = (SiS_TVDataStruct *)SiS310_ExtNTSCData; +#ifdef oldHV + SiS_Pr->SiS_St1HiTVData = (SiS_TVDataStruct *)SiS310_St1HiTVData; + SiS_Pr->SiS_St2HiTVData = (SiS_TVDataStruct *)SiS310_St2HiTVData; + SiS_Pr->SiS_ExtHiTVData = (SiS_TVDataStruct *)SiS310_ExtHiTVData; +#endif + + SiS_Pr->SiS_NTSCTiming = SiS310_NTSCTiming; + SiS_Pr->SiS_PALTiming = SiS310_PALTiming; +#ifdef oldHV + SiS_Pr->SiS_HiTVSt1Timing = SiS310_HiTVSt1Timing; + SiS_Pr->SiS_HiTVSt2Timing = SiS310_HiTVSt2Timing; + SiS_Pr->SiS_HiTVTextTiming = SiS310_HiTVTextTiming; + SiS_Pr->SiS_HiTVExtTiming = SiS310_HiTVExtTiming; + SiS_Pr->SiS_HiTVGroup3Data = SiS310_HiTVGroup3Data; + SiS_Pr->SiS_HiTVGroup3Simu = SiS310_HiTVGroup3Simu; + SiS_Pr->SiS_HiTVGroup3Text = SiS310_HiTVGroup3Text; +#endif + + SiS_Pr->SiS_PanelDelayTbl = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTbl; + SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTblLVDS; + + SiS_Pr->SiS_LVDS800x600Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS800x600Data_1; + SiS_Pr->SiS_LVDS800x600Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS800x600Data_2; + SiS_Pr->SiS_LVDS1024x768Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1024x768Data_1; + SiS_Pr->SiS_LVDS1024x768Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1024x768Data_2; + SiS_Pr->SiS_LVDS1280x1024Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x1024Data_1; + SiS_Pr->SiS_LVDS1280x1024Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x1024Data_2; + SiS_Pr->SiS_LVDS1280x960Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x960Data_1; + SiS_Pr->SiS_LVDS1280x960Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x960Data_2; + SiS_Pr->SiS_LVDS1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1400x1050Data_1; + SiS_Pr->SiS_LVDS1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1400x1050Data_2; + SiS_Pr->SiS_LVDS1280x768Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x768Data_1; + SiS_Pr->SiS_LVDS1280x768Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x768Data_2; + SiS_Pr->SiS_LVDS1024x600Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1024x600Data_1; + SiS_Pr->SiS_LVDS1024x600Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1024x600Data_2; + SiS_Pr->SiS_LVDS1152x768Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1152x768Data_1; + SiS_Pr->SiS_LVDS1152x768Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1152x768Data_2; + SiS_Pr->SiS_LVDSXXXxXXXData_1 = (SiS_LVDSDataStruct *)SiS310_LVDSXXXxXXXData_1; + SiS_Pr->SiS_LVDS320x480Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS320x480Data_1; + SiS_Pr->SiS_LVDS640x480Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS640x480Data_1; + SiS_Pr->SiS_LCDA1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS310_LCDA1400x1050Data_1; + SiS_Pr->SiS_LCDA1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS310_LCDA1400x1050Data_2; + SiS_Pr->SiS_LCDA1600x1200Data_1 = (SiS_LVDSDataStruct *)SiS310_LCDA1600x1200Data_1; + SiS_Pr->SiS_LCDA1600x1200Data_2 = (SiS_LVDSDataStruct *)SiS310_LCDA1600x1200Data_2; + SiS_Pr->SiS_CHTVUNTSCData = (SiS_LVDSDataStruct *)SiS310_CHTVUNTSCData; + SiS_Pr->SiS_CHTVONTSCData = (SiS_LVDSDataStruct *)SiS310_CHTVONTSCData; + SiS_Pr->SiS_CHTVUPALData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALData; + SiS_Pr->SiS_CHTVOPALData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALData; + SiS_Pr->SiS_CHTVUPALMData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALMData; + SiS_Pr->SiS_CHTVOPALMData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALMData; + SiS_Pr->SiS_CHTVUPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALNData; + SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALNData; + SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS310_CHTVSOPALData; + SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS310_PanelType00_1; + SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS310_PanelType01_1; + SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS310_PanelType02_1; + SiS_Pr->SiS_PanelType03_1 = (SiS_LVDSDesStruct *)SiS310_PanelType03_1; + SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS310_PanelType04_1; + SiS_Pr->SiS_PanelType05_1 = (SiS_LVDSDesStruct *)SiS310_PanelType05_1; + SiS_Pr->SiS_PanelType06_1 = (SiS_LVDSDesStruct *)SiS310_PanelType06_1; + SiS_Pr->SiS_PanelType07_1 = (SiS_LVDSDesStruct *)SiS310_PanelType07_1; + SiS_Pr->SiS_PanelType08_1 = (SiS_LVDSDesStruct *)SiS310_PanelType08_1; + SiS_Pr->SiS_PanelType09_1 = (SiS_LVDSDesStruct *)SiS310_PanelType09_1; + SiS_Pr->SiS_PanelType0a_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0a_1; + SiS_Pr->SiS_PanelType0b_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0b_1; + SiS_Pr->SiS_PanelType0c_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0c_1; + SiS_Pr->SiS_PanelType0d_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0d_1; + SiS_Pr->SiS_PanelType0e_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0e_1; + SiS_Pr->SiS_PanelType0f_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0f_1; + SiS_Pr->SiS_PanelType00_2 = (SiS_LVDSDesStruct *)SiS310_PanelType00_2; + SiS_Pr->SiS_PanelType01_2 = (SiS_LVDSDesStruct *)SiS310_PanelType01_2; + SiS_Pr->SiS_PanelType02_2 = (SiS_LVDSDesStruct *)SiS310_PanelType02_2; + SiS_Pr->SiS_PanelType03_2 = (SiS_LVDSDesStruct *)SiS310_PanelType03_2; + SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS310_PanelType04_2; + SiS_Pr->SiS_PanelType05_2 = (SiS_LVDSDesStruct *)SiS310_PanelType05_2; + SiS_Pr->SiS_PanelType06_2 = (SiS_LVDSDesStruct *)SiS310_PanelType06_2; + SiS_Pr->SiS_PanelType07_2 = (SiS_LVDSDesStruct *)SiS310_PanelType07_2; + SiS_Pr->SiS_PanelType08_2 = (SiS_LVDSDesStruct *)SiS310_PanelType08_2; + SiS_Pr->SiS_PanelType09_2 = (SiS_LVDSDesStruct *)SiS310_PanelType09_2; + SiS_Pr->SiS_PanelType0a_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0a_2; + SiS_Pr->SiS_PanelType0b_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0b_2; + SiS_Pr->SiS_PanelType0c_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0c_2; + SiS_Pr->SiS_PanelType0d_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0d_2; + SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0e_2; + SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0f_2; + + SiS_Pr->LVDS1024x768Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1076_1; + SiS_Pr->LVDS1280x1024Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1210_1; + SiS_Pr->LVDS1400x1050Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1296_1 ; + SiS_Pr->LVDS1600x1200Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1600_1 ; + SiS_Pr->LVDS1024x768Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1076_2; + SiS_Pr->LVDS1280x1024Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1210_2; + SiS_Pr->LVDS1400x1050Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1296_2; + SiS_Pr->LVDS1600x1200Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1600_2 ; + + /* TW: New from 650/301LV BIOS */ + SiS_Pr->SiS_CRT2Part2_1024x768_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_1; + SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_1; + SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_1; + SiS_Pr->SiS_CRT2Part2_1600x1200_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_1; + SiS_Pr->SiS_CRT2Part2_1024x768_2 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_2; + SiS_Pr->SiS_CRT2Part2_1280x1024_2 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_2; + SiS_Pr->SiS_CRT2Part2_1400x1050_2 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_2; + SiS_Pr->SiS_CRT2Part2_1600x1200_2 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_2; + SiS_Pr->SiS_CRT2Part2_1024x768_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_3; + SiS_Pr->SiS_CRT2Part2_1280x1024_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_3; + SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_3; + SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_3; + + SiS_Pr->SiS_CHTVUNTSCDesData = (SiS_LVDSDesStruct *)SiS310_CHTVUNTSCDesData; + SiS_Pr->SiS_CHTVONTSCDesData = (SiS_LVDSDesStruct *)SiS310_CHTVONTSCDesData; + SiS_Pr->SiS_CHTVUPALDesData = (SiS_LVDSDesStruct *)SiS310_CHTVUPALDesData; + SiS_Pr->SiS_CHTVOPALDesData = (SiS_LVDSDesStruct *)SiS310_CHTVOPALDesData; + + SiS_Pr->SiS_LVDSCRT1800x600_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1; + SiS_Pr->SiS_LVDSCRT11024x768_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1; + SiS_Pr->SiS_LVDSCRT11280x1024_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1; + SiS_Pr->SiS_LVDSCRT11400x1050_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1; + SiS_Pr->SiS_LVDSCRT11280x768_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x768_1; + SiS_Pr->SiS_LVDSCRT11024x600_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_1; + SiS_Pr->SiS_LVDSCRT11152x768_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_1; + SiS_Pr->SiS_LVDSCRT11600x1200_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1; + SiS_Pr->SiS_LVDSCRT1800x600_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1_H; + SiS_Pr->SiS_LVDSCRT11024x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1_H; + SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1_H; + SiS_Pr->SiS_LVDSCRT11400x1050_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1_H; + SiS_Pr->SiS_LVDSCRT11280x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x768_1_H; + SiS_Pr->SiS_LVDSCRT11024x600_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_1_H; + SiS_Pr->SiS_LVDSCRT11152x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_1_H; + SiS_Pr->SiS_LVDSCRT11600x1200_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1_H; + SiS_Pr->SiS_LVDSCRT1800x600_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2; + SiS_Pr->SiS_LVDSCRT11024x768_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2; + SiS_Pr->SiS_LVDSCRT11280x1024_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2; + SiS_Pr->SiS_LVDSCRT11400x1050_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2; + SiS_Pr->SiS_LVDSCRT11280x768_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x768_2; + SiS_Pr->SiS_LVDSCRT11024x600_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_2; + SiS_Pr->SiS_LVDSCRT11152x768_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_2; + SiS_Pr->SiS_LVDSCRT11600x1200_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2; + SiS_Pr->SiS_LVDSCRT1800x600_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2_H; + SiS_Pr->SiS_LVDSCRT11024x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2_H; + SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2_H; + SiS_Pr->SiS_LVDSCRT11400x1050_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2_H; + SiS_Pr->SiS_LVDSCRT11280x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x768_2_H; + SiS_Pr->SiS_LVDSCRT11024x600_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_2_H; + SiS_Pr->SiS_LVDSCRT11152x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_2_H; + SiS_Pr->SiS_LVDSCRT11600x1200_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2_H; + SiS_Pr->SiS_LVDSCRT1XXXxXXX_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1XXXxXXX_1; + SiS_Pr->SiS_LVDSCRT1320x480_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1320x480_1; + SiS_Pr->SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UNTSC; + SiS_Pr->SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1ONTSC; + SiS_Pr->SiS_CHTVCRT1UPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UPAL; + SiS_Pr->SiS_CHTVCRT1OPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL; + SiS_Pr->SiS_CHTVCRT1SOPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1SOPAL; + SiS_Pr->SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UNTSC; + SiS_Pr->SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_ONTSC; + SiS_Pr->SiS_CHTVReg_UPAL = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPAL; + SiS_Pr->SiS_CHTVReg_OPAL = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPAL; + SiS_Pr->SiS_CHTVReg_UPALM = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPALM; + SiS_Pr->SiS_CHTVReg_OPALM = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPALM; + SiS_Pr->SiS_CHTVReg_UPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPALN; + SiS_Pr->SiS_CHTVReg_OPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPALN; + SiS_Pr->SiS_CHTVReg_SOPAL = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_SOPAL; + SiS_Pr->SiS_LCDACRT1800x600_1 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT1800x600_1; + SiS_Pr->SiS_LCDACRT11024x768_1 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_1; + SiS_Pr->SiS_LCDACRT11280x1024_1 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_1; + SiS_Pr->SiS_LCDACRT11400x1050_1 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_1; + SiS_Pr->SiS_LCDACRT11600x1200_1 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_1; + SiS_Pr->SiS_LCDACRT1800x600_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT1800x600_1_H; + SiS_Pr->SiS_LCDACRT11024x768_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_1_H; + SiS_Pr->SiS_LCDACRT11280x1024_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_1_H; + SiS_Pr->SiS_LCDACRT11400x1050_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_1_H; + SiS_Pr->SiS_LCDACRT11600x1200_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_1_H; + SiS_Pr->SiS_LCDACRT1800x600_2 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT1800x600_2; + SiS_Pr->SiS_LCDACRT11024x768_2 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_2; + SiS_Pr->SiS_LCDACRT11280x1024_2 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_2; + SiS_Pr->SiS_LCDACRT11400x1050_2 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_2; + SiS_Pr->SiS_LCDACRT11600x1200_2 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_2; + SiS_Pr->SiS_LCDACRT1800x600_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT1800x600_2_H; + SiS_Pr->SiS_LCDACRT11024x768_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_2_H; + SiS_Pr->SiS_LCDACRT11280x1024_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_2_H; + SiS_Pr->SiS_LCDACRT11400x1050_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_2_H; + SiS_Pr->SiS_LCDACRT11600x1200_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_2_H; + 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_CHTVVCLKSOPAL; + + SiS_Pr->SiS_Panel320x480 = Panel_320x480; + SiS_Pr->SiS_Panel640x480 = Panel_640x480; + SiS_Pr->SiS_Panel800x600 = Panel_800x600; + SiS_Pr->SiS_Panel1024x768 = Panel_1024x768; + SiS_Pr->SiS_Panel1280x1024 = Panel_1280x1024; + SiS_Pr->SiS_Panel1280x960 = Panel_1280x960; + SiS_Pr->SiS_Panel1600x1200 = Panel_1600x1200; + SiS_Pr->SiS_Panel1400x1050 = Panel_1400x1050; + SiS_Pr->SiS_Panel1152x768 = Panel_1152x768; + SiS_Pr->SiS_Panel1152x864 = Panel_1152x864; + SiS_Pr->SiS_Panel1280x768 = Panel_1280x768; + SiS_Pr->SiS_Panel1024x600 = Panel_1024x600; + SiS_Pr->SiS_PanelMax = Panel_320x480; /* TW: highest value */ + SiS_Pr->SiS_PanelMinLVDS = Panel_800x600; /* TW: lowest value LVDS/LCDA */ + SiS_Pr->SiS_PanelMin301 = Panel_1024x768; /* TW: lowest value 301 */ +} +#endif + +#ifdef LINUXBIOS +/* -------------- SiSInit -----------------*/ +/* TW: I degraded this for LINUXBIOS only, because we + * don't need this otherwise. Under normal + * circumstances, the video BIOS has initialized + * the adapter for us. BTW, this code is incomplete + * and very possibly not functioning on newer chipsets. + */ +BOOLEAN +SiSInit(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase; + ULONG FBAddr = (ULONG)HwDeviceExtension->pjVideoMemoryAddress; + USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; + UCHAR i, temp=0; + UCHAR SR11; +#ifdef LINUX_KERNEL + UCHAR temp1; + ULONG base; +#endif + UCHAR SR13=0, SR14=0, SR16=0 + UCHAR SR17=0, SR19=0, SR1A=0; +#ifdef SIS300 + UCHAR SR18=0, SR12=0; +#endif +#ifdef SIS315H + UCHAR CR37=0, CR38=0, CR79=0, + UCHAR CR7A=0, CR7B=0, CR7C=0; + UCHAR SR1B=0, SR15=0; + PSIS_DSReg pSR; + ULONG Temp; +#endif + UCHAR VBIOSVersion[5]; + + if(FBAddr==0) return (FALSE); + if(BaseAddr==0) return (FALSE); + + SiS_SetReg3((USHORT)(BaseAddr+0x12), 0x67); /* Misc */ + +#ifdef SIS315H + if(HwDeviceExtension->jChipType > SIS_315PRO) { + if(!HwDeviceExtension->bIntegratedMMEnabled) + return (FALSE); + } +#endif + + SiS_MemoryCopy(VBIOSVersion,HwDeviceExtension->szVBIOSVer,4); + VBIOSVersion[4]= 0x00; + + SiSDetermineROMUsage(SiS_Pr, HwDeviceExtension, ROMAddr); + + /* TW: Init pointers */ +#ifdef SIS315H + if((HwDeviceExtension->jChipType == SIS_315H) || + (HwDeviceExtension->jChipType == SIS_315) || + (HwDeviceExtension->jChipType == SIS_315PRO) || + (HwDeviceExtension->jChipType == SIS_550) || + (HwDeviceExtension->jChipType == SIS_650) || + (HwDeviceExtension->jChipType == SIS_740) || + (HwDeviceExtension->jChipType == SIS_330)) + InitTo310Pointer(SiS_Pr, HwDeviceExtension); +#endif + +#ifdef SIS300 + if((HwDeviceExtension->jChipType == SIS_540) || + (HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730) || + (HwDeviceExtension->jChipType == SIS_300)) + InitTo300Pointer(SiS_Pr, HwDeviceExtension); +#endif + + /* TW: Set SiS Register definitions */ + SiSRegInit(SiS_Pr, BaseAddr); + + /* TW: Determine LVDS/CH70xx/TRUMPION */ + SiS_Set_LVDS_TRUMPION(SiS_Pr, HwDeviceExtension); + + /* TW: Unlock registers */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86); + +#ifdef LINUX_KERNEL + +#ifdef SIS300 /* Set SR14 */ + if((HwDeviceExtension->jChipType==SIS_540) || + (HwDeviceExtension->jChipType==SIS_630) || + (HwDeviceExtension->jChipType==SIS_730)) { + base=0x80000060; + OutPortLong(base,0xcf8); + temp1 = InPortLong(0xcfc); + temp1 >>= (16+8+4); + temp1 &= 0x07; + temp1++; + temp1 = 1 << temp1; + SR14 = temp1 - 1; + base = 0x80000064; + OutPortLong(base,0xcf8); + temp1 = InPortLong(0xcfc); + temp1 &= 0x00000020; + if(temp1) SR14 |= 0x80; + else SR14 |= 0x40; + } +#endif + +#ifdef SIS315H /* Set SR14 */ + if(HwDeviceExtension->jChipType == SIS_550) { + base = 0x80000060; + OutPortLong(base,0xcf8); + temp1 = InPortLong(0xcfc); + temp1 >>= (16+8+4); + temp1 &= 0x07; + temp1++; + temp1 = 1 << temp1; + SR14 = temp1 - 1; + base = 0x80000064; + OutPortLong(base,0xcf8); + temp1 = InPortLong(0xcfc); + temp1 &= 0x00000020; + if(temp1) SR14 |= 0x80; + else SR14 |= 0x40; + } + + if((HwDeviceExtension->jChipType == SIS_740) || /* Set SR14 */ + (HwDeviceExtension->jChipType == SIS_650)) { + base = 0x80000064; + OutPortLong(base,0xcf8); + temp1=InPortLong(0xcfc); + temp1 >>= 4; + temp1 &= 0x07; + if(temp1 > 2) { + temp = temp1; + switch(temp) { + case 3: temp1 = 0x07; break; + case 4: temp1 = 0x0F; break; + case 5: temp1 = 0x1F; break; + case 6: temp1 = 0x05; break; + case 7: temp1 = 0x17; break; + case 8: break; + case 9: break; + } + } + SR14 = temp1; + base = 0x8000007C; + OutPortLong(base,0xcf8); + temp1 = InPortLong(0xcfc); + temp1 &= 0x00000020; + if(temp1) SR14 |= 0x80; + } +#endif + +#endif /* Linux kernel */ + +#ifdef SIS300 + if((HwDeviceExtension->jChipType == SIS_540)|| + (HwDeviceExtension->jChipType == SIS_630)|| + (HwDeviceExtension->jChipType == SIS_730)) { + SR12 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x12); + SR13 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13); + SR14 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); + SR16 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); + SR17 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17); + SR18 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x18); + SR19 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x19); + SR1A = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1A); + } else if(HwDeviceExtension->jChipType == SIS_300){ + SR13 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13); + SR14 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); + } +#endif +#ifdef SIS315H + if((HwDeviceExtension->jChipType == SIS_550) || + (HwDeviceExtension->jChipType == SIS_740) || + (HwDeviceExtension->jChipType == SIS_650)) { + SR19 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x19); + SR19 = (SR19)||0x01; /* TW: ??? || ??? */ + if(SR19==0x00) { + SR13 = 0x22; + SR14 = 0x00; + SR15 = 0x01; + SR16 = 0x00; + SR17 = 0x00; + SR1A = 0x00; + SR1B = 0x00; + CR37 = 0x00; + CR38 = 0x00; + CR79 = 0x00; + CR7A = 0x00; + CR7B = 0x00; + CR7C = 0x00; + } else { + SR13 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13); + SR14 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); + SR15 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15); + SR16 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); + SR17 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17); + SR1A = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1A); + SR1B = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1B); + CR37 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37); /* TW: Was 0x02 - why? */ + CR38 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + CR79 = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x79); + CR7A = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x7A); + CR7B = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x7B); + CR7C = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x7C); + } + } +#endif + + /* Reset extended registers */ + + for(i=0x06; i< 0x20; i++) SiS_SetReg1(SiS_Pr->SiS_P3c4,i,0); + for(i=0x21; i<=0x27; i++) SiS_SetReg1(SiS_Pr->SiS_P3c4,i,0); + for(i=0x31; i<=0x3D; i++) SiS_SetReg1(SiS_Pr->SiS_P3c4,i,0); + +#ifdef SIS300 + if((HwDeviceExtension->jChipType == SIS_540) || + (HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730) || + (HwDeviceExtension->jChipType == SIS_300)) { + for(i=0x38; i<=0x3F; i++) SiS_SetReg1(SiS_Pr->SiS_P3d4,i,0); + } +#endif + +#ifdef SIS315H + if((HwDeviceExtension->jChipType == SIS_315H) || + (HwDeviceExtension->jChipType == SIS_315) || + (HwDeviceExtension->jChipType == SIS_315PRO) || + (HwDeviceExtension->jChipType == SIS_550) || + (HwDeviceExtension->jChipType == SIS_650) || + (HwDeviceExtension->jChipType == SIS_740) || + (HwDeviceExtension->jChipType == SIS_330)) { + for(i=0x12; i<=0x1B; i++) SiS_SetReg1(SiS_Pr->SiS_P3c4,i,0); + for(i=0x79; i<=0x7C; i++) SiS_SetReg1(SiS_Pr->SiS_P3d4,i,0); + } +#endif + + /* Restore Extended Registers */ + +#ifdef SIS300 + if((HwDeviceExtension->jChipType == SIS_540) || + (HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730)) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x12,SR12); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,SR13); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,SR14); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,SR16); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x17,SR17); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x18,SR18); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x19,SR19); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1A,SR1A); + } +#endif + +#ifdef SIS315H + if((HwDeviceExtension->jChipType == SIS_550) || + (HwDeviceExtension->jChipType == SIS_740) || + (HwDeviceExtension->jChipType == SIS_650)) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,SR13); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,SR14); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x15,SR15); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,SR16); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x17,SR17); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x19,SR19); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1A,SR1A); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1B,SR1B); + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x37,CR37); + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x38,CR38); + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x79,CR79); + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x7A,CR7A); + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x7B,CR7B); + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x7C,CR7C); + } +#endif + +#ifdef SIS300 + if((HwDeviceExtension->jChipType==SIS_540) || + (HwDeviceExtension->jChipType==SIS_630) || + (HwDeviceExtension->jChipType==SIS_730)) { + temp = (UCHAR)SR1A & 0x03; + } else if(HwDeviceExtension->jChipType == SIS_300) { + /* TW: Nothing */ + } +#endif +#ifdef SIS315H + if((HwDeviceExtension->jChipType == SIS_315H) || + (HwDeviceExtension->jChipType == SIS_315) || + (HwDeviceExtension->jChipType == SIS_315PRO) || + (HwDeviceExtension->jChipType == SIS_330) ) { + if((*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) == 0) { + temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3A) & 0x03; + } + } + if((HwDeviceExtension->jChipType == SIS_550) || + (HwDeviceExtension->jChipType == SIS_740) || + (HwDeviceExtension->jChipType == SIS_650)) { + if((*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) == 0) { + temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x07; + } + } +#endif + + SiS_Pr->SiS_RAMType = temp; + SiS_SetMemoryClock(SiS_Pr, ROMAddr, HwDeviceExtension); + + /* Set default register contents */ + + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x07,*SiS_Pr->pSiS_SR07); /* DAC speed */ + + if((HwDeviceExtension->jChipType != SIS_540) && + (HwDeviceExtension->jChipType != SIS_630) && + (HwDeviceExtension->jChipType != SIS_730)){ + for(i=0x15;i<0x1C;i++) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,i,SiS_Pr->SiS_SR15[i-0x15][SiS_Pr->SiS_RAMType]); + } + } + +#ifdef SIS315H + if((HwDeviceExtension->jChipType == SIS_315H) || + (HwDeviceExtension->jChipType == SIS_315) || + (HwDeviceExtension->jChipType == SIS_315PRO) || + (HwDeviceExtension->jChipType == SIS_330)) { + for(i=0x40;i<=0x44;i++) { + SiS_SetReg1(SiS_Pr->SiS_P3d4,i,SiS_Pr->SiS_CR40[i-0x40][SiS_Pr->SiS_RAMType]); + } + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x48,0x23); + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x49,SiS_Pr->SiS_CR49[0]); + /* SiS_SetReg1(SiS_Pr->SiS_P3c4,0x25,SiS_Pr->SiS_SR25[0]); */ + } +#endif + + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1F,*SiS_Pr->pSiS_SR1F); /* DAC pedestal */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x20,0xA0); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x23,*SiS_Pr->pSiS_SR23); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x24,*SiS_Pr->pSiS_SR24); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x25,SiS_Pr->SiS_SR25[0]); + +#ifdef SIS300 + if(HwDeviceExtension->jChipType == SIS_300) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x21,0x84); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x22,0x00); + } +#endif + + SR11 = 0x0F; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x11,SR11); /* Power Management & DDC port */ + + SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x00,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x02,*SiS_Pr->pSiS_CRT2Data_1_2); + +#ifdef SIS315H + if((HwDeviceExtension->jChipType == SIS_315H) || + (HwDeviceExtension->jChipType == SIS_315) || + (HwDeviceExtension->jChipType == SIS_315PRO) || + (HwDeviceExtension->jChipType == SIS_550) || + (HwDeviceExtension->jChipType == SIS_650) || + (HwDeviceExtension->jChipType == SIS_740) || + (HwDeviceExtension->jChipType == SIS_330)) + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2E,0x08); /* use VB */ +#endif + + temp = *SiS_Pr->pSiS_SR32; + if(SiS_BridgeIsOn(SiS_Pr, BaseAddr)) { + temp &= 0xEF; + } + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,temp); + +#ifdef SIS315H + if((HwDeviceExtension->jChipType == SIS_315H) || + (HwDeviceExtension->jChipType == SIS_315) || + (HwDeviceExtension->jChipType == SIS_315PRO) || + (HwDeviceExtension->jChipType == SIS_330)) { + HwDeviceExtension->pQueryVGAConfigSpace(HwDeviceExtension,0x50,0,&Temp); + Temp >>= 20; + Temp &= 0xF; + if (Temp != 1) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x25,SiS_Pr->SiS_SR25[1]); + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x49,SiS_Pr->SiS_CR49[1]); + } + + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x27,0x1F); + + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,*SiS_Pr->pSiS_SR31); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,*SiS_Pr->pSiS_SR32); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x33,*SiS_Pr->pSiS_SR33); + } +#endif + + if (SiS_BridgeIsOn(SiS_Pr, BaseAddr) == 0) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x00,0x1C); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0D,*SiS_Pr->pSiS_CRT2Data_4_D); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0E,*SiS_Pr->pSiS_CRT2Data_4_E); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x10,*SiS_Pr->pSiS_CRT2Data_4_10); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0F,0x3F); + } + SiS_LockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr); + } + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x83,0x00); + +#ifdef SIS315H + if((HwDeviceExtension->jChipType == SIS_315H) || + (HwDeviceExtension->jChipType == SIS_315) || + (HwDeviceExtension->jChipType == SIS_315PRO) || + (HwDeviceExtension->jChipType == SIS_330)) { + if(HwDeviceExtension->bSkipDramSizing==TRUE) { + SiS_SetDRAMModeRegister(SiS_Pr, ROMAddr,HwDeviceExtension); + pSR = HwDeviceExtension->pSR; + if(pSR != NULL) { + while(pSR->jIdx != 0xFF) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,pSR->jIdx,pSR->jVal); + pSR++; + } + } + } else SiS_SetDRAMSize_310(SiS_Pr, HwDeviceExtension); + } +#endif + +#ifdef SIS315H + if(HwDeviceExtension->jChipType == SIS_550) { + /* SetDRAMConfig begin */ +/* SiS_SetReg1(SiS_Pr->SiS_P3c4,0x12,SR12); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,SR13); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,SR14); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,SR16); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x17,SR17); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x18,SR18); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x19,SR19); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1A,SR1A); */ + /* SetDRAMConfig end */ + } +#endif + +#ifdef SIS300 + if(HwDeviceExtension->jChipType == SIS_300) { + if (HwDeviceExtension->bSkipDramSizing == TRUE) { +/* SiS_SetDRAMModeRegister(ROMAddr,HwDeviceExtension); + temp = (HwDeviceExtension->pSR)->jVal; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,temp); + temp = (HwDeviceExtension->pSR)->jVal; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,temp); */ + } else { +#ifdef TC + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,SR13); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,SR14); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x15,0xFF,0x04); +#else + SiS_SetDRAMSize_300(SiS_Pr, HwDeviceExtension); + SiS_SetDRAMSize_300(SiS_Pr, HwDeviceExtension); +#endif + } + } + if((HwDeviceExtension->jChipType==SIS_540)|| + (HwDeviceExtension->jChipType==SIS_630)|| + (HwDeviceExtension->jChipType==SIS_730)) { +#if 0 + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x12,SR12); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,SR13); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,SR14); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,SR16); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x17,SR17); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x18,SR18); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x19,SR19); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1A,SR1A); +#endif + } +/* SetDRAMSize end */ +#endif /* SIS300 */ + + /* Set default Ext2Regs */ +#if 0 + AGP=1; + temp=(UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3A); + temp &= 0x30; + if(temp == 0x30) AGP=0; + if(AGP == 0) *SiS_Pr->pSiS_SR21 &= 0xEF; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x21,*SiS_Pr->pSiS_SR21); + if(AGP == 1) *SiS_Pr->pSiS_SR22 &= 0x20; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x22,*SiS_Pr->pSiS_SR22); +#endif + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x21,*SiS_Pr->pSiS_SR21); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x22,*SiS_Pr->pSiS_SR22); + +#if 0 + SiS_SetReg3(SiS_Pr->SiS_P3c6,0xff); + SiS_ClearDAC(SiS_Pr, SiS_Pr->SiS_P3c8); +#endif + +#ifdef LINUXBIOS /* TW: This is not needed for our purposes */ + SiS_DetectMonitor(SiS_Pr, HwDeviceExtension,BaseAddr); /* Sense CRT1 */ + SiS_GetSenseStatus(SiS_Pr, HwDeviceExtension,ROMAddr); /* Sense CRT2 */ +#endif + + return(TRUE); +} + +void +SiS_Set_LVDS_TRUMPION(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT temp = 0; + +#ifdef SiS300 + if((HwDeviceExtension->jChipType == SIS_540) || + (HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730)) { + /* TW: Read POWER_ON_TRAP and copy to CR37 */ + temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1A); + temp = (temp & 0xE0) >> 4; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0xF1,temp); + } +#endif +#ifdef SIS315H + if((HwDeviceExtension->jChipType == SIS_650) || + (HwDeviceExtension->jChipType == SIS_740) || + (HwDeviceExtension->jChipType == SIS_330)) { +#if 0 /* TW: This is not required */ + /* TW: Read POWER_ON_TRAP and copy to CR37 */ + temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1A); + temp = (temp & 0xE0) >> 4; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0xF1,temp); +#endif + } +#endif + + SiSSetLVDSetc(SiS_Pr, HwDeviceExtension, 0); +} + +/* =============== SiS 300 dram sizing begin =============== */ +#ifdef SIS300 +void +SiS_SetDRAMSize_300(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + ULONG FBAddr = (ULONG)HwDeviceExtension->pjVideoMemoryAddress; + USHORT SR13, SR14=0, buswidth, Done; + SHORT i, j, k; + USHORT data, TotalCapacity, PhysicalAdrOtherPage=0; + ULONG Addr; + UCHAR temp; + int PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount; + int RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank; + int PageCapacity, PhysicalAdrHigh, PhysicalAdrHalfPage; + + SiSSetMode(SiS_Pr, HwDeviceExtension, 0x2e); + + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20); /* Turn OFF Display */ + + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,0x00); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,0xBF); + + buswidth = SiS_ChkBUSWidth_300(SiS_Pr, FBAddr); + + MB2Bank = 16; + Done = 0; + for(i=6; i>=0; i--) { + if(Done == 1) break; + PseudoRankCapacity = 1 << i; + for(j=4; j>=1; j--) { + if(Done == 1) break; + PseudoTotalCapacity = PseudoRankCapacity * j; + PseudoAdrPinCount = 15 - j; + if(PseudoTotalCapacity <= 64) { + for(k=0; k<=16; k++) { + if(Done == 1) 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 */ + /*Test*/ + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x15,0xFB); + SiS_SetRegOR(SiS_Pr->SiS_P3c4,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; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,SR13); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,SR14); + + Addr = FBAddr + (BankNumHigh) * 64 * 1024 + PhysicalAdrHigh; + *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHigh; + Addr = FBAddr + (BankNumMid) * 64 * 1024 + PhysicalAdrHigh; + *((USHORT *)(Addr)) = (USHORT)BankNumMid; + Addr = FBAddr + (BankNumHigh) * 64 * 1024 + PhysicalAdrHalfPage; + *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHalfPage; + Addr = FBAddr + (BankNumHigh) * 64 * 1024 + PhysicalAdrOtherPage; + *((USHORT *)(Addr)) = PhysicalAdrOtherPage; + + /* Read data */ + Addr = FBAddr + (BankNumHigh) * 64 * 1024 + PhysicalAdrHigh; + data = *((USHORT *)(Addr)); + if(data == PhysicalAdrHigh) Done = 1; + } /* if struct */ + } /* for loop (k) */ + } /* if struct */ + } /* for loop (j) */ + } /* for loop (i) */ +} + +USHORT +SiS_ChkBUSWidth_300(SiS_Private *SiS_Pr, ULONG FBAddress) +{ + PULONG pVideoMemory; + + pVideoMemory = (PULONG)FBAddress; + + pVideoMemory[0] = 0x01234567L; + pVideoMemory[1] = 0x456789ABL; + pVideoMemory[2] = 0x89ABCDEFL; + pVideoMemory[3] = 0xCDEF0123L; + if (pVideoMemory[3]==0xCDEF0123L) { /* Channel A 128bit */ + return(4); + } + if (pVideoMemory[1]==0x456789ABL) { /* Channel B 64bit */ + return(2); + } + return(1); +} +#endif +/* =============== SiS 300 dram sizing end =============== */ + +/* ============ SiS 310/325 dram sizing begin ============== */ +#ifdef SIS315H + +/* TW: Moved Get310DRAMType further down */ + +void +SiS_Delay15us(SiS_Private *SiS_Pr, ULONG ulMicrsoSec) +{ +} + +void +SiS_SDR_MRS(SiS_Private *SiS_Pr, ) +{ + USHORT data; + + data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); + data &= 0x3F; /* SR16 D7=0, D6=0 */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,data); /* enable mode register set(MRS) low */ + SiS_Delay15us(SiS_Pr, 0x100); + data |= 0x80; /* SR16 D7=1, D6=0 */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,data); /* enable mode register set(MRS) high */ + SiS_Delay15us(SiS_Pr, 0x100); +} + +void +SiS_DDR_MRS(SiS_Private *SiS_Pr) +{ + USHORT data; + + /* SR16 <- 1F,DF,2F,AF */ + + /* enable DLL of DDR SD/SGRAM , SR16 D4=1 */ + data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); + data &= 0x0F; + data |= 0x10; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,data); + + if (!(SiS_Pr->SiS_SR15[1][SiS_Pr->SiS_RAMType] & 0x10)) + data &= 0x0F; + + /* SR16 D7=1,D6=1 */ + data |= 0xC0; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,data); + + /* SR16 D7=1,D6=0,D5=1,D4=0 */ + data &= 0x0F; + data |= 0x20; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,data); + if (!(SiS_Pr->SiS_SR15[1][SiS_Pr->SiS_RAMType] & 0x10)) + data &= 0x0F; + + /* SR16 D7=1 */ + data |= 0x80; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,data); +} + +void +SiS_SetDRAMModeRegister(SiS_Private *SiS_Pr, UCHAR *ROMAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + if (SiS_Get310DRAMType(ROMAddr,HwDeviceExtension) < 2) + SiS_SDR_MRS(SiS_Pr); + else + /* SR16 <- 0F,CF,0F,8F */ + SiS_DDR_MRS(SiS_Pr); +} + +void +SiS_DisableRefresh(SiS_Private *SiS_Pr) +{ + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x17,0xF8); + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x19,0x03); +} + +void +SiS_EnableRefresh(SiS_Private *SiS_Pr, UCHAR *ROMAddr) +{ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x17,SiS_Pr->SiS_SR15[2][SiS_Pr->SiS_RAMType]); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x19,SiS_Pr->SiS_SR15[4][SiS_Pr->SiS_RAMType]); +} + +void +SiS_DisableChannelInterleaving(SiS_Private *SiS_Pr, int index, + USHORT SiS_DDRDRAM_TYPE[][5]) +{ + USHORT data; + + data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15); + data &= 0x1F; + switch (SiS_DDRDRAM_TYPE[index][3]) + { + case 64: data |= 0; break; + case 32: data |= 0x20; break; + case 16: data |= 0x40; break; + case 4: data |= 0x60; break; + } + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x15,data); +} + +void +SiS_SetDRAMSizingType(SiS_Private *SiS_Pr, int index, USHORT DRAMTYPE_TABLE[][5]) +{ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,DRAMTYPE_TABLE[index][4]); + /* should delay 50 ns */ +} + +void +SiS_CheckBusWidth_310(SiS_Private *SiS_Pr, UCHAR *ROMAddress,ULONG FBAddress, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT data, temp; + PULONG volatile pVideoMemory; + + pVideoMemory = (PULONG)FBAddress; + + if(HwDeviceExtension->jChipType == SIS_330) temp = 1; + else temp = 2; + + if(SiS_Get310DRAMType(ROMAddress,HwDeviceExtension) < temp) { + + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,0x00); + if(HwDeviceExtension->jChipType != SIS_330) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,0x12); + } else { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,0x02); + } + /* should delay */ + SiS_SDR_MRS(SiS_Pr); + + SiS_Pr->SiS_ChannelAB = 0; + SiS_Pr->SiS_DataBusWidth = 128; + pVideoMemory[0] = 0x01234567L; + pVideoMemory[1] = 0x456789ABL; + pVideoMemory[2] = 0x89ABCDEFL; + pVideoMemory[3] = 0xCDEF0123L; + pVideoMemory[4] = 0x55555555L; + pVideoMemory[5] = 0x55555555L; + pVideoMemory[6] = 0xFFFFFFFFL; + pVideoMemory[7] = 0xFFFFFFFFL; + if((pVideoMemory[3] != 0xCDEF0123L) || (pVideoMemory[2] != 0x89ABCDEFL)) { + /* Channel A 64Bit */ + SiS_Pr->SiS_DataBusWidth = 64; + SiS_Pr->SiS_ChannelAB = 0; + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x14, 0xFD); + } + if((pVideoMemory[1] != 0x456789ABL) || (pVideoMemory[0] != 0x01234567L)) { + /* Channel B 64Bit */ + SiS_Pr->SiS_DataBusWidth = 64; + SiS_Pr->SiS_ChannelAB = 1; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x14,0xfd,0x01); + } + return; + + } else { + + /* DDR Dual channel */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x13,0x00); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,0x02); /* Channel A, 64bit */ + /* should delay */ + SiS_DDR_MRS(SiS_Pr); + + SiS_Pr->SiS_ChannelAB = 0; + SiS_Pr->SiS_DataBusWidth = 64; + pVideoMemory[0] = 0x01234567L; + pVideoMemory[1] = 0x456789ABL; + pVideoMemory[2] = 0x89ABCDEFL; + pVideoMemory[3] = 0xCDEF0123L; + pVideoMemory[4] = 0x55555555L; + pVideoMemory[5] = 0x55555555L; + pVideoMemory[6] = 0xAAAAAAAAL; + pVideoMemory[7] = 0xAAAAAAAAL; + + if (pVideoMemory[1] == 0x456789ABL) { + if (pVideoMemory[0] == 0x01234567L) { + /* Channel A 64bit */ + return; + } + } else { + if (pVideoMemory[0] == 0x01234567L) { + /* Channel A 32bit */ + SiS_Pr->SiS_DataBusWidth = 32; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,0x00); + return; + } + } + + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,0x03); /* Channel B, 64bit */ + SiS_DDR_MRS(SiS_Pr); + + SiS_Pr->SiS_ChannelAB = 1; + SiS_Pr->SiS_DataBusWidth = 64; + pVideoMemory[0] = 0x01234567L; + pVideoMemory[1] = 0x456789ABL; + pVideoMemory[2] = 0x89ABCDEFL; + pVideoMemory[3] = 0xCDEF0123L; + pVideoMemory[4] = 0x55555555L; + pVideoMemory[5] = 0x55555555L; + pVideoMemory[6] = 0xAAAAAAAAL; + pVideoMemory[7] = 0xAAAAAAAAL; + if(pVideoMemory[1] == 0x456789ABL) { + /* Channel B 64 */ + if(pVideoMemory[0] == 0x01234567L) { + /* Channel B 64bit */ + return; + } else { + /* error */ + } + } else { + if(pVideoMemory[0] == 0x01234567L) { + /* Channel B 32 */ + SiS_Pr->SiS_DataBusWidth = 32; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,0x01); + } else { + /* error */ + } + } + } +} + +int +SiS_SetRank(SiS_Private *SiS_Pr, int index,UCHAR RankNo,USHORT DRAMTYPE_TABLE[][5]) +{ + USHORT data; + int RankSize; + + if ((RankNo==2)&&(DRAMTYPE_TABLE[index][0]==2)) + return 0; + + RankSize = DRAMTYPE_TABLE[index][3]/2 * SiS_Pr->SiS_DataBusWidth / 32; + + if (RankNo * RankSize <= 128) { + data = 0; + while((RankSize >>= 1) > 0) { + data += 0x10; + } + data |= (RankNo - 1) << 2; + data |= (SiS_Pr->SiS_DataBusWidth / 64) & 2; + data |= SiS_Pr->SiS_ChannelAB; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,data); + /* should delay */ + SiS_SDR_MRS(SiS_Pr); + return 1; + } else + return 0; +} + +int +SiS_SetDDRChannel(SiS_Private *SiS_Pr, int index,UCHAR ChannelNo, + USHORT DRAMTYPE_TABLE[][5]) +{ + USHORT data; + int RankSize; + + RankSize = DRAMTYPE_TABLE[index][3]/2 * SiS_Pr->SiS_DataBusWidth / 32; + /* RankSize = DRAMTYPE_TABLE[index][3]; */ + if (ChannelNo * RankSize <= 128) { + data = 0; + while((RankSize >>= 1) > 0) { + data += 0x10; + } + if(ChannelNo == 2) data |= 0x0C; + data |= (SiS_Pr->SiS_DataBusWidth / 32) & 2; + data |= SiS_Pr->SiS_ChannelAB; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,data); + /* should delay */ + SiS_DDR_MRS(SiS_Pr); + return 1; + } else + return 0; +} + +int +SiS_CheckColumn(SiS_Private *SiS_Pr, int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress) +{ + int i; + ULONG Increment,Position; + + /*Increment = 1<<(DRAMTYPE_TABLE[index][2] + SiS_Pr->SiS_DataBusWidth / 64 + 1); */ + Increment = 1 << (10 + SiS_Pr->SiS_DataBusWidth / 64); + + for (i=0,Position=0;i<2;i++) { + *((PULONG)(FBAddress + Position)) = Position; + Position += Increment; + } + + for (i=0,Position=0;i<2;i++) { +/* if (FBAddress[Position]!=Position) */ + if((*(PULONG)(FBAddress + Position)) != Position) + return 0; + Position += Increment; + } + return 1; +} + +int +SiS_CheckBanks(SiS_Private *SiS_Pr, int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress) +{ + int i; + ULONG Increment,Position; + Increment = 1 << (DRAMTYPE_TABLE[index][2] + SiS_Pr->SiS_DataBusWidth / 64 + 2); + + for (i=0,Position=0;i<4;i++) { +/* FBAddress[Position]=Position; */ + *((PULONG)(FBAddress + Position)) = Position; + Position += Increment; + } + + for (i=0,Position=0;i<4;i++) { +/* if (FBAddress[Position]!=Position) */ + if((*(PULONG)(FBAddress + Position)) != Position) + return 0; + Position += Increment; + } + return 1; +} + +int +SiS_CheckRank(SiS_Private *SiS_Pr, int RankNo,int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress) +{ + int i; + ULONG Increment,Position; + Increment = 1<<(DRAMTYPE_TABLE[index][2] + DRAMTYPE_TABLE[index][1] + + DRAMTYPE_TABLE[index][0] + SiS_Pr->SiS_DataBusWidth / 64 + RankNo); + + for (i=0,Position=0;i<2;i++) { +/* FBAddress[Position]=Position; */ + *((PULONG)(FBAddress+Position))=Position; + /* *((PULONG)(FBAddress))=Position; */ + Position += Increment; + } + + for (i=0,Position=0;i<2;i++) { +/* if (FBAddress[Position]!=Position) */ + if ( (*(PULONG) (FBAddress + Position)) !=Position) + /*if ( (*(PULONG) (FBAddress )) !=Position) */ + return 0; + Position += Increment; + } + return 1; +} + +int +SiS_CheckDDRRank(SiS_Private *SiS_Pr, int RankNo,int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress) +{ + ULONG Increment,Position; + USHORT data; + + Increment = 1<<(DRAMTYPE_TABLE[index][2] + DRAMTYPE_TABLE[index][1] + + DRAMTYPE_TABLE[index][0] + SiS_Pr->SiS_DataBusWidth / 64 + RankNo); + + Increment += Increment/2; + + Position =0; + *((PULONG)(FBAddress+Position + 0)) = 0x01234567; + *((PULONG)(FBAddress+Position + 1)) = 0x456789AB; + *((PULONG)(FBAddress+Position + 2)) = 0x55555555; + *((PULONG)(FBAddress+Position + 3)) = 0x55555555; + *((PULONG)(FBAddress+Position + 4)) = 0xAAAAAAAA; + *((PULONG)(FBAddress+Position + 5)) = 0xAAAAAAAA; + + if ( (*(PULONG) (FBAddress + 1)) == 0x456789AB) + return 1; + + if ( (*(PULONG) (FBAddress + 0)) == 0x01234567) + return 0; + + data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); + data &= 0xF3; + data |= 0x08; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x14,data); + data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15); + data += 0x20; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x15,data); + + return 1; +} + +int +SiS_CheckRanks(SiS_Private *SiS_Pr, int RankNo,int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress) +{ + int r; + + for (r=RankNo;r>=1;r--) { + if (!SiS_CheckRank(SiS_Pr, r, index, DRAMTYPE_TABLE, FBAddress)) + return 0; + } + if (!SiS_CheckBanks(SiS_Pr, index, DRAMTYPE_TABLE, FBAddress)) + return 0; + + if (!SiS_CheckColumn(SiS_Pr, index, DRAMTYPE_TABLE, FBAddress)) + return 0; + + return 1; +} + +int +SiS_CheckDDRRanks(SiS_Private *SiS_Pr, int RankNo,int index,USHORT DRAMTYPE_TABLE[][5], + ULONG FBAddress) +{ + int r; + + for (r=RankNo;r>=1;r--) { + if (!SiS_CheckDDRRank(SiS_Pr, r,index,DRAMTYPE_TABLE,FBAddress)) + return 0; + } + if (!SiS_CheckBanks(SiS_Pr, index,DRAMTYPE_TABLE,FBAddress)) + return 0; + + if (!SiS_CheckColumn(SiS_Pr, index,DRAMTYPE_TABLE,FBAddress)) + return 0; + + return 1; +} + +int +SiS_SDRSizing(SiS_Private *SiS_Pr, ULONG FBAddress) +{ + int i; + UCHAR j; + + for (i=0;i<13;i++) { + SiS_SetDRAMSizingType(SiS_Pr, i, SiS_SDRDRAM_TYPE); + for (j=2;j>0;j--) { + if (!SiS_SetRank(SiS_Pr, i,(UCHAR) j, SiS_SDRDRAM_TYPE)) + continue; + else { + if (SiS_CheckRanks(SiS_Pr, j,i,SiS_SDRDRAM_TYPE, FBAddress)) + return 1; + } + } + } + return 0; +} + +int +SiS_DDRSizing(SiS_Private *SiS_Pr, ULONG FBAddress) +{ + + int i; + UCHAR j; + + for (i=0; i<4; i++){ + SiS_SetDRAMSizingType(SiS_Pr, i, SiS_DDRDRAM_TYPE); + SiS_DisableChannelInterleaving(SiS_Pr, i, SiS_DDRDRAM_TYPE); + for (j=2; j>0; j--) { + SiS_SetDDRChannel(SiS_Pr, i, j, SiS_DDRDRAM_TYPE); + if (!SiS_SetRank(SiS_Pr, i, (UCHAR) j, SiS_DDRDRAM_TYPE)) + continue; + else { + if (SiS_CheckDDRRanks(SiS_Pr, j, i, SiS_DDRDRAM_TYPE, FBAddress)) + return 1; + } + } + } + return 0; +} + +/* + check if read cache pointer is correct +*/ +void +SiS_VerifyMclk(SiS_Private *SiS_Pr, ULONG FBAddr) +{ + PUCHAR pVideoMemory = (PUCHAR) FBAddr; + UCHAR i, j; + USHORT Temp,SR21; + + pVideoMemory[0] = 0xaa; /* alan */ + pVideoMemory[16] = 0x55; /* note: PCI read cache is off */ + + if((pVideoMemory[0] != 0xaa) || (pVideoMemory[16] != 0x55)) { + for (i=0,j=16; i<2; i++,j+=16) { + SR21 = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x21); + Temp = SR21 & 0xFB; /* disable PCI post write buffer empty gating */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x21,Temp); + + Temp = SiS_GetReg1(SiS_Pr->SiS_P3c4, 0x3C); + Temp |= 0x01; /* MCLK reset */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x3C,Temp); + Temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3C); + Temp &= 0xFE; /* MCLK normal operation */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x3C,Temp); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x21,SR21); + + pVideoMemory[16+j] = j; + if(pVideoMemory[16+j] == j) { + pVideoMemory[j] = j; + break; + } + } + } +} + +/* TW: Is this a 315E? */ +int +Is315E(SiS_Private *SiS_Pr) +{ + USHORT data; + + data = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5F); + if(data & 0x10) return 1; + else return 0; +} + +/* TW: For 315 only */ +void +SiS_SetDRAMSize_310(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase; + ULONG FBAddr = (ULONG)HwDeviceExtension->pjVideoMemoryAddress; + USHORT data; + +#ifdef SIS301 /* TW: SIS301 ??? */ + /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x30,0x40); */ +#endif +#ifdef SIS302 /* TW: SIS302 ??? */ + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x30,0x4D); /* alan,should change value */ + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x31,0xc0); /* alan,should change value */ + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x34,0x3F); /* alan,should change value */ +#endif + + SiSSetMode(SiS_Pr, HwDeviceExtension, 0x2e); + + data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x21); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x21,0xDF); /* disable read cache */ + + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20); /* Turn OFF Display */ + + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x16,0x0F); /* assume lowest speed DRAM */ + + SiS_SetDRAMModeRegister(SiS_Pr, ROMAddr, HwDeviceExtension); + SiS_DisableRefresh(SiS_Pr); + SiS_CheckBusWidth_310(SiS_Pr, ROMAddr, FBAddr, HwDeviceExtension); + + SiS_VerifyMclk(SiS_Pr, FBAddr); + + if(HwDeviceExtension->jChipType == SIS_330) temp = 1; + else temp = 2; + + if(SiS_Get310DRAMType(SiS_Pr, ROMAddr, HwDeviceExtension) < temp) + SiS_SDRSizing(SiS_Pr, FBAddr); + else + SiS_DDRSizing(SiS_Pr, FBAddr); + + if(HwDeviceExtension->jChipType != SIS_330) { + if(Is315E(SiS_Pr)) { + data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); + if((data & 0x0C) == 0x0C) { /* dual channel */ + if((data & 0xF0) > 0x40) + data = (data & 0x0F) | 0x40; + } else { /* single channel */ + if((data & 0xF0) > 0x50) + data = (data & 0x0F) | 0x50; + } + } + } + + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x16,SiS_Pr->SiS_SR15[1][SiS_Pr->SiS_RAMType]); /* restore SR16 */ + + SiS_EnableRefresh(SiS_Pr, ROMAddr); + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x21,0x20); /* enable read cache */ +} +#endif + +void +SiS_SetMemoryClock(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x28,SiS_Pr->SiS_MCLKData_0[SiS_Pr->SiS_RAMType].SR28); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x29,SiS_Pr->SiS_MCLKData_0[SiS_Pr->SiS_RAMType].SR29); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2A,SiS_Pr->SiS_MCLKData_0[SiS_Pr->SiS_RAMType].SR2A); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2E,SiS_Pr->SiS_ECLKData[SiS_Pr->SiS_RAMType].SR2E); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2F,SiS_Pr->SiS_ECLKData[SiS_Pr->SiS_RAMType].SR2F); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x30,SiS_Pr->SiS_ECLKData[SiS_Pr->SiS_RAMType].SR30); + +#ifdef SIS315H + if (Is315E(SiS_Pr)) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x28,0x3B); /* 143 */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x29,0x22); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2E,0x3B); /* 143 */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2F,0x22); + } +#endif +} + +#endif /* ifdef LINUXBIOS */ + +#ifdef SIS315H +UCHAR +SiS_Get310DRAMType(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + UCHAR data, temp; + + if(*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) { + data = *SiS_Pr->pSiS_SoftSetting & 0x03; + } else { + if((HwDeviceExtension->jChipType > SIS_315PRO) && + (HwDeviceExtension->jChipType < SIS_330)) { + data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x07; + } else { /* TW: 315, 330 */ + data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3a) & 0x03; + if(HwDeviceExtension->jChipType == SIS_330) { + if(data > 1) { + temp = SiS_GetReg1(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; +} +#endif + +/* SiSInit END */ + +/* ----------------------------------------- */ + +void SiSRegInit(SiS_Private *SiS_Pr, USHORT 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_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) */ +} + +void +SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ +/* #ifdef LINUX_XF86 */ + if ((HwDeviceExtension->jChipType == SIS_540)|| + (HwDeviceExtension->jChipType == SIS_630)|| + (HwDeviceExtension->jChipType == SIS_730)|| + (HwDeviceExtension->jChipType == SIS_300)) { + /* TW: Set - PCI LINEAR ADDRESSING ENABLE (0x80) + - PCI IO ENABLE (0x20) + - MMIO ENABLE (0x1) + */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x20,0xa1); + /* TW: Enable 2D (0x42) & 3D accelerator (0x18) */ + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0xFF,0x5A); + } + if((HwDeviceExtension->jChipType == SIS_315H)|| + (HwDeviceExtension->jChipType == SIS_315) || + (HwDeviceExtension->jChipType == SIS_315PRO)|| + (HwDeviceExtension->jChipType == SIS_550) || + (HwDeviceExtension->jChipType == SIS_650) || + (HwDeviceExtension->jChipType == SIS_740) || + (HwDeviceExtension->jChipType == SIS_330)) { + /* TW: This seems to be done the same way on these chipsets */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x20,0xa1); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0xFF,0x5A); + } +/* #endif */ +} + +void +SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo) +{ + ULONG 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_HiVision = 0; + SiS_Pr->SiS_IF_DEF_DSTN = 0; + SiS_Pr->SiS_IF_DEF_FSTN = 0; + + SiS_Pr->SiS_ChrontelInit = 0; + + if((ModeNo == 0x5a) || (ModeNo == 0x5b)) { + SiS_Pr->SiS_IF_DEF_DSTN = 1; /* for 550 dstn */ + SiS_Pr->SiS_IF_DEF_FSTN = 1; /* for fstn */ + } + +#ifdef SIS300 + if((HwDeviceExtension->jChipType == SIS_540) || + (HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730)) + { + /* TW: Check for SiS30x first */ + temp = SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x00); + if((temp == 1) || (temp == 2)) return; + temp = SiS_GetReg1(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)) { + /* TW: Save power status (and error check) - UNUSED */ + SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e); + SiS_Pr->SiS_IF_DEF_CH70xx = 1; + } + } +#endif +#ifdef SIS315H + if((HwDeviceExtension->jChipType == SIS_550) || + (HwDeviceExtension->jChipType == SIS_650) || + (HwDeviceExtension->jChipType == SIS_740) || + (HwDeviceExtension->jChipType == SIS_330)) + { + /* TW: CR37 is different on 310/325 series */ + if(SiS_Pr->SiS_IF_DEF_FSTN) /* fstn: set CR37=0x04 */ + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x37,0x04); /* (fake LVDS bridge) */ + + temp=SiS_GetReg1(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; + } + + /* HiVision (HDTV) is done differently now. */ + /* SiS_Pr->SiS_IF_DEF_HiVision = 1; */ + } +#endif +} + +void +SiSInitPtr(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ +#ifdef SIS315H + if((HwDeviceExtension->jChipType == SIS_315H) || + (HwDeviceExtension->jChipType == SIS_315) || + (HwDeviceExtension->jChipType == SIS_315PRO) || + (HwDeviceExtension->jChipType == SIS_550) || + (HwDeviceExtension->jChipType == SIS_650) || + (HwDeviceExtension->jChipType == SIS_740) || + (HwDeviceExtension->jChipType == SIS_330)) + InitTo310Pointer(SiS_Pr, HwDeviceExtension); +#endif + +#ifdef SIS300 + if ((HwDeviceExtension->jChipType == SIS_540) || + (HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730) || + (HwDeviceExtension->jChipType == SIS_300)) + InitTo300Pointer(SiS_Pr, HwDeviceExtension); +#endif +} + +void +SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, UCHAR *ROMAddr) +{ + if((ROMAddr) && (HwDeviceExtension->UseROM)) { + if((ROMAddr[0x00] != 0x55) || (ROMAddr[0x01] != 0xAA)) { + SiS_Pr->SiS_UseROM = FALSE; + } else if(HwDeviceExtension->jChipType == SIS_300) { + /* TW: 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 SiS_Pr->SiS_UseROM = FALSE; + } else if(HwDeviceExtension->jChipType < SIS_315H) { + /* TW: Rest of 300 series: We don't use the ROM image if + * the BIOS version < 2.0.0 as such old BIOSes don't + * have the needed data at the expected locations. + */ + if(ROMAddr[0x06] < '2') SiS_Pr->SiS_UseROM = FALSE; + else SiS_Pr->SiS_UseROM = TRUE; + } else { + /* TW: 310/325/330 series stick to the standard */ + SiS_Pr->SiS_UseROM = TRUE; + } + } else SiS_Pr->SiS_UseROM = FALSE; + +} + +/* + ========================================= + ======== SiS SetMode Functions ========== + ========================================= +*/ +#ifdef LINUX_XF86 +/* TW: This is used for non-Dual-Head mode from X */ +BOOLEAN +SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, 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, SiS_Pr->CVDisplay); + + return(SiSSetMode(SiS_Pr, HwDeviceExtension, pScrn, ModeNo, TRUE)); + + } + + ModeNo = SiS_CalcModeIndex(pScrn, mode); + if(!ModeNo) return FALSE; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting mode 0x%x\n", ModeNo); + + return(SiSSetMode(SiS_Pr, HwDeviceExtension, pScrn, ModeNo, TRUE)); +} + +#ifdef SISDUALHEAD +/* TW: Set CRT1 mode (used for dual head) */ +BOOLEAN +SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, ScrnInfoPtr pScrn, + DisplayModePtr mode, BOOLEAN IsCustom) +{ + ULONG temp; + USHORT ModeIdIndex; + UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase; + USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; + SISPtr pSiS = SISPTR(pScrn); + SISEntPtr pSiSEnt = pSiS->entityPrivate; + unsigned char backupreg=0; + BOOLEAN backupcustom; + + 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 in CRT1\n", + SiS_Pr->CHDisplay, SiS_Pr->CVDisplay); + ModeNo = 0xfe; + + } else { + + ModeNo = SiS_CalcModeIndex(pScrn, mode); + if(!ModeNo) return FALSE; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Setting mode 0x%x on CRT1\n", ModeNo); + } + + SiSInitPtr(SiS_Pr, HwDeviceExtension); + + SiSRegInit(SiS_Pr, BaseAddr); + + SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff); + + SiSInitPCIetc(SiS_Pr, HwDeviceExtension); + + SiSSetLVDSetc(SiS_Pr, HwDeviceExtension, ModeNo); + + SiSDetermineROMUsage(SiS_Pr, HwDeviceExtension, ROMAddr); + + /* TW: We don't clear the buffer under X */ + SiS_Pr->SiS_flag_clearbuffer = 0; + + /* 1.Openkey */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86); + + SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr); + + if(!SiS_Pr->UseCustomMode) { + /* 2.Get ModeID Table */ + temp = SiS_SearchModeID(SiS_Pr, ROMAddr,&ModeNo,&ModeIdIndex); + if(temp == 0) return(0); + } else { + ModeIdIndex = 0; + } + + /* TW: Determine VBType (301,301B,301LV,302B,302LV) */ + SiS_GetVBType(SiS_Pr, BaseAddr,HwDeviceExtension); + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwDeviceExtension->jChipType >= SIS_315H) { + backupreg = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + } else { + backupreg = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x35); + } + } + + SiS_SetHiVision(SiS_Pr, BaseAddr,HwDeviceExtension); + + /* TW: Get VB information (connectors, connected devices) */ + /* (We don't care if the current mode is a CRT2 mode) */ + SiS_GetVBInfo(SiS_Pr, BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,0); + SiS_GetLCDResInfo(SiS_Pr, ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); + + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08) { + /* TW: I am not sure the flag's name is correct */ + if(ModeNo != 0x10) SiS_Pr->SiS_SetFlag |= CRT2IsVGA; + } + + /* TW: New from 650/LV 1.10.6x */ + if(IS_SIS650740) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f); + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7); + } + } + } + + /* TW: Set mode on CRT1 */ + SiS_SetCRT1Group(SiS_Pr, ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex,BaseAddr); + + pSiSEnt->CRT1ModeNo = ModeNo; + pSiSEnt->CRT1DMode = mode; + + /* TW: SetPitch: Adapt to virtual size & position */ + SiS_SetPitchCRT1(SiS_Pr, pScrn, BaseAddr); + + /* We have to reset CRT2 if changing mode on CRT1 */ + if(pSiSEnt->CRT2ModeNo != -1) { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "(Re-)Setting mode 0x%x on CRT2\n", + pSiSEnt->CRT2ModeNo); + backupcustom = SiS_Pr->UseCustomMode; + if(SiS_Pr->UseCustomMode) { + SiS_Pr->CRT1UsesCustomMode = TRUE; + } else { + SiS_Pr->CRT1UsesCustomMode = FALSE; + } + SiSBIOSSetModeCRT2(SiS_Pr, HwDeviceExtension, pSiSEnt->pScrn_1, + pSiSEnt->CRT2DMode); + SiS_Pr->UseCustomMode = backupcustom; + SiS_Pr->CRT1UsesCustomMode = FALSE; + } + + if(IS_SIS650740) { /* TW: *** For 650 only! *** */ + SiS_HandleCRT1(SiS_Pr); + } + + SiS_DisplayOn(SiS_Pr); + SiS_SetReg3(SiS_Pr->SiS_P3c6,0xFF); + + /* TW: New from 650/LV 1.10.6x and 1.10.7w, 630/301B 2.06.50 */ + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x38,backupreg); + } else if((HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730)) { + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x35,backupreg); + } + } + + /* Backup/Set ModeNo in BIOS scratch area */ + SiS_GetSetModeID(pScrn,ModeNo); + + return TRUE; +} + +/* TW: Set CRT2 mode (used for dual head) */ +BOOLEAN +SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, ScrnInfoPtr pScrn, + DisplayModePtr mode) +{ + ULONG temp; + USHORT ModeIdIndex; + UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase; + USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; + UShort ModeNo = 0; + SISPtr pSiS = SISPTR(pScrn); + SISEntPtr pSiSEnt = pSiS->entityPrivate; + unsigned char tempr1, tempr2, backupreg=0; + + SiS_Pr->UseCustomMode = FALSE; + + ModeNo = SiS_CalcModeIndex(pScrn, mode); + if(!ModeNo) return FALSE; + + SiSInitPtr(SiS_Pr, HwDeviceExtension); + + SiSRegInit(SiS_Pr, BaseAddr); + + SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff); + + SiSInitPCIetc(SiS_Pr, HwDeviceExtension); + + SiSSetLVDSetc(SiS_Pr, HwDeviceExtension, ModeNo); + + SiSDetermineROMUsage(SiS_Pr, HwDeviceExtension, ROMAddr); + + /* TW: We don't clear the buffer under X */ + SiS_Pr->SiS_flag_clearbuffer=0; + + /* TW: Save ModeNo so we can set it from within SetMode for CRT1 */ + pSiSEnt->CRT2ModeNo = ModeNo; + pSiSEnt->CRT2DMode = mode; + + /* TW: 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; + } + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Setting mode 0x%x on CRT2\n", ModeNo); + + /* 1.Openkey */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86); + + SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr); + + /* 2.Get ModeID */ + temp = SiS_SearchModeID(SiS_Pr, ROMAddr,&ModeNo,&ModeIdIndex); + if(temp == 0) return(0); + + /* TW: Determine VBType (301,301B,301LV,302B,302LV) */ + SiS_GetVBType(SiS_Pr, BaseAddr,HwDeviceExtension); + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_UnLockCRT2(SiS_Pr,HwDeviceExtension,BaseAddr); + if(HwDeviceExtension->jChipType < SIS_330) { + if(ROMAddr && SiS_Pr->SiS_UseROM) { + temp = ROMAddr[VB310Data_1_2_Offset]; + temp |= 0x40; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x02,temp); + } + } + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10); + + SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x02,0x0c); + + backupreg = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + } else { + backupreg = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x35); + } + } + + /* TW: Get VB information (connectors, connected devices) */ + SiS_SetHiVision(SiS_Pr, BaseAddr,HwDeviceExtension); + SiS_GetVBInfo(SiS_Pr, BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,1); + SiS_GetLCDResInfo(SiS_Pr, ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); + + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08) { + /* TW: I am not sure the flag's name is correct */ + if(ModeNo != 0x10) SiS_Pr->SiS_SetFlag |= CRT2IsVGA; + } + } + + /* Set mode on CRT2 */ + switch (HwDeviceExtension->ujVBChipID) { + case VB_CHIP_301: + case VB_CHIP_301B: + case VB_CHIP_301LV: + case VB_CHIP_301LVX: + case VB_CHIP_302: + case VB_CHIP_302B: + case VB_CHIP_302LV: + case VB_CHIP_302LVX: + SiS_SetCRT2Group301(SiS_Pr, BaseAddr,ROMAddr,ModeNo,HwDeviceExtension); + break; + case VB_CHIP_303: + break; + case VB_CHIP_UNKNOWN: + if (SiS_Pr->SiS_IF_DEF_LVDS == 1 || + SiS_Pr->SiS_IF_DEF_CH70xx != 0 || + SiS_Pr->SiS_IF_DEF_TRUMPION != 0) { + SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension); + } + break; + } + + SiS_DisplayOn(SiS_Pr); + SiS_SetReg3(SiS_Pr->SiS_P3c6,0xFF); + + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(!(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr))) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb); + } + } + } + + /* TW: New from 650/LV 1.10.6x and 1.10.7w, 630 2.06.50 */ + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01); + } else { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE); + } + + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x38,backupreg); + + tempr1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + tempr2 = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x00); + if(tempr1 & SetCRT2ToAVIDEO) tempr2 &= 0xF7; + if(tempr1 & SetCRT2ToSVIDEO) tempr2 &= 0xFB; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x00,tempr2); + + if(tempr1 & SetCRT2ToLCD) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc); + } + } else if((HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730)) { + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x35,backupreg); + } + } + + /* TW: SetPitch: Adapt to virtual size & position */ + SiS_SetPitchCRT2(SiS_Pr, pScrn, BaseAddr); + + return TRUE; +} +#endif /* Dualhead */ +#endif /* Linux_XF86 */ + +#ifdef LINUX_XF86 +/* TW: We need pScrn for setting the pitch correctly */ +BOOLEAN +SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch) +#else +BOOLEAN +SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo) +#endif +{ + ULONG temp; + USHORT ModeIdIndex,KeepLockReg; + UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase; + USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; + unsigned char backupreg=0, tempr1, tempr2; + +#ifndef LINUX_XF86 + SiS_Pr->UseCustomMode = FALSE; + SiS_Pr->CRT1UsesCustomMode = FALSE; +#endif + + if(SiS_Pr->UseCustomMode) { + ModeNo = 0xfe; + } + + SiSInitPtr(SiS_Pr, HwDeviceExtension); + + SiSRegInit(SiS_Pr, BaseAddr); + +#ifdef LINUX_XF86 + if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff); + else +#endif + SiS_Pr->SiS_VGAINFO = 0x11; + + SiSInitPCIetc(SiS_Pr, HwDeviceExtension); + + SiSSetLVDSetc(SiS_Pr, HwDeviceExtension, ModeNo); + + SiSDetermineROMUsage(SiS_Pr, HwDeviceExtension, ROMAddr); + + if(!SiS_Pr->UseCustomMode) { + /* TW: Shift the clear-buffer-bit away */ + ModeNo = ((ModeNo & 0x80) << 8) | (ModeNo & 0x7f); + } + +#ifdef LINUX_XF86 + /* TW: We never clear the buffer in X */ + ModeNo |= 0x8000; +#endif + + if(ModeNo & 0x8000) { + ModeNo &= 0x7fff; + SiS_Pr->SiS_flag_clearbuffer = 0; + } else { + SiS_Pr->SiS_flag_clearbuffer = 1; + } + + /* 1.Openkey */ + KeepLockReg = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x05); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86); + + SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr); + + if(!SiS_Pr->UseCustomMode) { + + /* 2.Get ModeID Table */ + temp = SiS_SearchModeID(SiS_Pr,ROMAddr,&ModeNo,&ModeIdIndex); + if(temp == 0) return(0); + + } else { + + ModeIdIndex = 0; + + } + + /* TW: Determine VBType (301,301B,301LV,302B,302LV) */ + SiS_GetVBType(SiS_Pr,BaseAddr,HwDeviceExtension); + + /* TW: Init/restore some VB registers */ + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_UnLockCRT2(SiS_Pr,HwDeviceExtension,BaseAddr); + if(HwDeviceExtension->jChipType < SIS_330) { + if(ROMAddr && SiS_Pr->SiS_UseROM) { + temp = ROMAddr[VB310Data_1_2_Offset]; + temp |= 0x40; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x02,temp); + } + } + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10); + + SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x02,0x0c); + + backupreg = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + } else { + backupreg = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x35); + } + } + + /* TW: Get VB information (connectors, connected devices) */ + SiS_SetHiVision(SiS_Pr,BaseAddr,HwDeviceExtension); + SiS_GetVBInfo(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,1); + SiS_GetLCDResInfo(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); + + /* 3. Check memory size */ + temp = SiS_CheckMemorySize(SiS_Pr,ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex); + if(!temp) return(0); + + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08) { + /* TW: I am not sure the flag's name is correct */ + if(ModeNo != 0x10) SiS_Pr->SiS_SetFlag |= CRT2IsVGA; + } + + /* TW: New from 650/LV 1.10.6x */ + if(IS_SIS650740) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f); + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7); + } + } + } + + /* TW: Set mode on CRT1 */ + if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) { + SiS_SetCRT1Group(SiS_Pr,ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex,BaseAddr); + } else { + if(!(SiS_Pr->SiS_VBInfo & SwitchToCRT2)) { + SiS_SetCRT1Group(SiS_Pr,ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex,BaseAddr); + } + } + + /* TW: Set mode on CRT2 */ + if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2 | SetCRT2ToLCDA)) { + switch (HwDeviceExtension->ujVBChipID) { + case VB_CHIP_301: + case VB_CHIP_301B: + case VB_CHIP_301LV: + case VB_CHIP_301LVX: + case VB_CHIP_302: + case VB_CHIP_302B: + case VB_CHIP_302LV: + case VB_CHIP_302LVX: + SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension); + break; + case VB_CHIP_303: + break; + case VB_CHIP_UNKNOWN: + if(SiS_Pr->SiS_IF_DEF_LVDS == 1 || + SiS_Pr->SiS_IF_DEF_CH70xx != 0 || + SiS_Pr->SiS_IF_DEF_TRUMPION != 0) + SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension); + break; + } + } + + if(IS_SIS650740) { /* TW: For 650 only! */ + SiS_HandleCRT1(SiS_Pr); + } + + SiS_DisplayOn(SiS_Pr); + SiS_SetReg3(SiS_Pr->SiS_P3c6,0xFF); + + if(HwDeviceExtension->jChipType >= SIS_315H) { +#if 0 + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + SiS_Handle301B_1400x1050(SiS_Pr, ModeNo); + } + } +#endif + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(!(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr))) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb); + } + } + } + + /* TW: New from 650/LV 1.10.6x and 1.10.7w */ + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01); + } else { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE); + } + + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x38,backupreg); + + tempr1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + tempr2 = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x00); + if(tempr1 & SetCRT2ToAVIDEO) tempr2 &= 0xF7; + if(tempr1 & SetCRT2ToSVIDEO) tempr2 &= 0xFB; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x00,tempr2); + + if((IS_SIS650740) && (SiS_GetReg1(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(tempr1 & SetCRT2ToLCD) { +/* if(ModeNo <= 0x13) { - not in 1.10.8r */ + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc); +/* } */ + } + } else if((HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730)) { + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x35,backupreg); + } + } + +#ifdef LINUX_XF86 + if(pScrn) { + /* TW: SetPitch: Adapt to virtual size & position */ + if((ModeNo > 0x13) && (dosetpitch)) { + SiS_SetPitch(SiS_Pr, pScrn, BaseAddr); + } + + /* Backup/Set ModeNo in BIOS scratch area */ + SiS_GetSetModeID(pScrn, ModeNo); + } +#endif + +#ifndef LINUX_XF86 /* TW: We never lock registers in XF86 */ + if(KeepLockReg == 0xA1) SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86); + else SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x00); +#endif + + return TRUE; +} + +void +SiS_SetEnableDstn(SiS_Private *SiS_Pr) /* TW: Called from sis_main.c */ +{ + /* For 550 dstn */ + SiS_Pr->SiS_IF_DEF_DSTN = 1; +} + +void +SiS_HandleCRT1(SiS_Private *SiS_Pr) +{ + /* TW: Do this on 650 only! */ + + /* TW: No, we don't do this at all. There is a new + * CRT1-is-connected-at-boot-time logic in the 650, which + * confuses our own. So just clear the bit and skip the rest. + */ + + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x63,0xbf); + +#if 0 + if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15) & 0x01)) + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x63,0x40); + } +#endif +} + +#if 0 +void +SiS_Handle301B_1400x1050(SiS_Private *SiS_Pr, USHORT ModeNo) +{ + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) { + if(ModeNo <= 0x13) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & (SetNotSimuMode >> 8)) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xFC); + } + } + } +} +#endif + +void +SiS_SetCRT1Group(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT ModeNo,USHORT ModeIdIndex,USHORT BaseAddr) +{ + USHORT StandTableIndex,RefreshRateTableIndex; + + SiS_Pr->SiS_CRT1Mode = ModeNo; + StandTableIndex = SiS_GetModePtr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex); + if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) { + if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2)) { + SiS_DisableBridge(SiS_Pr,HwDeviceExtension,BaseAddr); + } + } + + SiS_SetSeqRegs(SiS_Pr,ROMAddr,StandTableIndex); + SiS_SetMiscRegs(SiS_Pr,ROMAddr,StandTableIndex); + SiS_SetCRTCRegs(SiS_Pr,ROMAddr,HwDeviceExtension,StandTableIndex); + SiS_SetATTRegs(SiS_Pr,ROMAddr,StandTableIndex,HwDeviceExtension); + SiS_SetGRCRegs(SiS_Pr,ROMAddr,StandTableIndex); + SiS_ClearExt1Regs(SiS_Pr,HwDeviceExtension); + SiS_ResetCRT1VCLK(SiS_Pr,ROMAddr,HwDeviceExtension); + + SiS_Pr->SiS_SelectCRT2Rate = 0; + SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2); + +#ifdef LINUX_XF86 + xf86DrvMsgVerb(0, X_PROBED, 3, "(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_GetRatePtrCRT2(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); + + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2; + } + + if(RefreshRateTableIndex != 0xFFFF) { + SiS_SetSync(SiS_Pr,ROMAddr,RefreshRateTableIndex); + SiS_SetCRT1CRTC(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwDeviceExtension); + SiS_SetCRT1Offset(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwDeviceExtension); + SiS_SetCRT1VCLK(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,RefreshRateTableIndex); + } + +#ifdef SIS300 + if(HwDeviceExtension->jChipType == SIS_300) { + SiS_SetCRT1FIFO_300(SiS_Pr,ROMAddr,ModeNo,HwDeviceExtension,RefreshRateTableIndex); + } + if((HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730) || + (HwDeviceExtension->jChipType == SIS_540)) { + SiS_SetCRT1FIFO_630(SiS_Pr,ROMAddr,ModeNo,HwDeviceExtension,RefreshRateTableIndex); + } +#endif +#ifdef SIS315H + if(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_SetCRT1FIFO_310(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); + } +#endif + + SiS_SetCRT1ModeRegs(SiS_Pr,ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex,RefreshRateTableIndex); + + SiS_LoadDAC(SiS_Pr,HwDeviceExtension,ROMAddr,ModeNo,ModeIdIndex); + +#ifndef LINUX_XF86 + if(SiS_Pr->SiS_flag_clearbuffer) { + SiS_ClearBuffer(SiS_Pr,HwDeviceExtension,ModeNo); + } +#endif + + if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2 | SetCRT2ToLCDA))) { + SiS_LongWait(SiS_Pr); + SiS_DisplayOn(SiS_Pr); + } +} + +#ifdef LINUX_XF86 +void +SiS_SetPitch(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, UShort BaseAddr) +{ + SISPtr pSiS = SISPTR(pScrn); + + /* TW: We need to set pitch for CRT1 if bridge is in SlaveMode, too */ + if( (pSiS->VBFlags & DISPTYPE_DISP1) || + ( (pSiS->VBFlags & VB_VIDEOBRIDGE) && + ( ((pSiS->VGAEngine == SIS_300_VGA) && (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) || + ((pSiS->VGAEngine == SIS_315_VGA) && (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) ) { + SiS_SetPitchCRT1(SiS_Pr, pScrn, BaseAddr); + } + if (pSiS->VBFlags & DISPTYPE_DISP2) { + SiS_SetPitchCRT2(SiS_Pr, pScrn, BaseAddr); + } +} + +void +SiS_SetPitchCRT1(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, UShort BaseAddr) +{ + SISPtr pSiS = SISPTR(pScrn); + ULong HDisplay,temp; + + HDisplay = pSiS->scrnPitch / 8; + SiS_SetReg1(SiS_Pr->SiS_P3d4, 0x13, (HDisplay & 0xFF)); + temp = (SiS_GetReg1(SiS_Pr->SiS_P3c4, 0x0E) & 0xF0) | (HDisplay>>8); + SiS_SetReg1(SiS_Pr->SiS_P3c4, 0x0E, temp); +} + +void +SiS_SetPitchCRT2(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, UShort BaseAddr) +{ + SISPtr pSiS = SISPTR(pScrn); + ULong HDisplay,temp; + + HDisplay = pSiS->scrnPitch / 8; + + /* 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_SetReg1(SiS_Pr->SiS_Part1Port,0x07, (HDisplay & 0xFF)); + temp = (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x09) & 0xF0) | ((HDisplay >> 8) & 0xFF); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x09, temp); +} +#endif + +/* TW: Checked against 650/301 and 630/301B BIOS */ +/* TW: Re-written for 650/301LVx 1.10.6s BIOS */ +void +SiS_GetVBType(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT flag=0, rev=0, nolcd=0; + + SiS_Pr->SiS_VBType = 0; + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) return; + + flag = SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x00); + + /* TW: Illegal values not welcome... */ + if(flag > 10) return; + + rev = SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x01); + + if (flag >= 2) { + SiS_Pr->SiS_VBType = VB_SIS302B; + } else if (flag == 1) { + SiS_Pr->SiS_VBType = VB_SIS301; + if(rev >= 0xB0) { + SiS_Pr->SiS_VBType = VB_SIS301B; + if((HwDeviceExtension->jChipType >= SIS_315H) || + (HwDeviceExtension->jChipType == SIS_300)) { + /* 650/301LV and 300/301LV use this, 630/301B does not */ + nolcd = SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x23); + if(!(nolcd & 0x02)) + SiS_Pr->SiS_VBType |= VB_NoLCD; + } + } + } + if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS302B)) { + if(rev >= 0xD0) { + SiS_Pr->SiS_VBType &= ~(VB_SIS301B | VB_SIS302B); + SiS_Pr->SiS_VBType |= VB_SIS30xLV; + SiS_Pr->SiS_VBType &= ~(VB_NoLCD); + if(rev >= 0xE0) { + SiS_Pr->SiS_VBType &= ~(VB_SIS30xLV); + SiS_Pr->SiS_VBType |= VB_SIS30xNEW; + } + } + } +} + +/* TW: Checked against 650/301LVx 1.10.6s */ +BOOLEAN +SiS_SearchModeID(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT *ModeNo,USHORT *ModeIdIndex) +{ + UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO; + + if(*ModeNo <= 0x13) { + + if((*ModeNo) <= 5) (*ModeNo) |= 1; + + 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 <= 3) { + 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; +} + +/* For SiS 300 oem util: Search VBModeID */ +BOOLEAN +SiS_SearchVBModeID(SiS_Private *SiS_Pr, UCHAR *ROMAddr, 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 FALSE; + } + + if(*ModeNo != 0x07) { + if(*ModeNo > 0x03) return ((BOOLEAN)ModeIdIndex); + if(VGAINFO & 0x80) return ((BOOLEAN)ModeIdIndex); + ModeIdIndex++; + } + if(VGAINFO & 0x10) ModeIdIndex++; /* 400 lines */ + /* else 350 lines */ + return ((BOOLEAN)ModeIdIndex); +} + +/* TW: Checked against 630/301B, 315 1.09 and 650/301LVx 1.10.6s BIOS */ +BOOLEAN +SiS_CheckMemorySize(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT memorysize,modeflag; + ULONG temp; + + 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++; + + temp = GetDRAMSize(SiS_Pr, HwDeviceExtension); /* Get adapter memory size */ + temp /= (1024*1024); /* (in MB) */ + + if(temp < memorysize) return(FALSE); + else return(TRUE); +} + +UCHAR +SiS_GetModePtr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + UCHAR index; + + if(ModeNo <= 0x13) { + index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex; + } else { + if(SiS_Pr->SiS_ModeType <= 0x02) index = 0x1B; /* 02 -> ModeEGA */ + else index = 0x0F; + } + return index; +} + +/* TW: Checked against 300, 330, 650/LVDS (1.10.07, 1.10a) and 650/301LV BIOS */ +void +SiS_SetSeqRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex) +{ + UCHAR SRdata; + USHORT i; + + SiS_SetReg1(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(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_SetReg1(SiS_Pr->SiS_P3c4,0x01,SRdata); + + for(i = 2; i <= 4; i++) { + SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1]; + SiS_SetReg1(SiS_Pr->SiS_P3c4,i,SRdata); + } +} + +/* Checked against 300, 650/301LVx 1.10.6s and 650/LVDS 1.10.07 BIOS */ +void +SiS_SetMiscRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex) +{ + UCHAR Miscdata; + + Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC; + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + Miscdata |= 0x0C; + } + } + + SiS_SetReg3(SiS_Pr->SiS_P3c2,Miscdata); +} + +/* Checked against 300, 330, 650/LVDS (1.10.07) and 650/301LVx (1.10.6s) BIOS (630 code still there!) */ +void +SiS_SetCRTCRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension, + 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_SetReg1(SiS_Pr->SiS_P3d4,i,CRTCdata); /* Set CRTC(3d4) */ + } + if( ( (HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730) ) && + (HwDeviceExtension->jChipRevision >= 0x30) ) { /* for 630S0 */ + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) { + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x18,0xFE); + } + } + } +} + +/* TW: Checked against 300, 650/LVDS (1.10.07), 650/301LVx (1.10.6s) and 630/301B BIOS */ +void +SiS_SetATTRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + 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) { + 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(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(HwDeviceExtension->jChipType >= SIS_315H) { + /* TW: From 650/LVDS 1.10.07, 1.10a; 650/301LVx 1.10.6s; not in 330 BIOS */ + ARdata = 0; + } else { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + ARdata=0; + } + } + } + } + SiS_GetReg2(SiS_Pr->SiS_P3da); /* reset 3da */ + SiS_SetReg3(SiS_Pr->SiS_P3c0,i); /* set index */ + SiS_SetReg3(SiS_Pr->SiS_P3c0,ARdata); /* set data */ + } + SiS_GetReg2(SiS_Pr->SiS_P3da); /* reset 3da */ + SiS_SetReg3(SiS_Pr->SiS_P3c0,0x14); /* set index */ + SiS_SetReg3(SiS_Pr->SiS_P3c0,0x00); /* set data */ + + SiS_GetReg2(SiS_Pr->SiS_P3da); + SiS_SetReg3(SiS_Pr->SiS_P3c0,0x20); /* Enable Attribute */ + SiS_GetReg2(SiS_Pr->SiS_P3da); +} + +/* TW: Checked against 300, 330, 650/LVDS (1.10.07, 1.10a) and 650/301LV BIOS */ +void +SiS_SetGRCRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex) +{ + UCHAR GRdata; + USHORT i; + + for(i = 0; i <= 0x08; i++) { + GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i]; + SiS_SetReg1(SiS_Pr->SiS_P3ce,i,GRdata); /* Set GR(3ce) */ + } + + if(SiS_Pr->SiS_ModeType > ModeVGA) { + SiS_SetRegAND(SiS_Pr->SiS_P3ce,0x05,0xBF); /* 256 color disable */ + } +} + +/* TW: Checked against 650/LVDS (1.10.07, 1.10a), 650/301LVx (1.10.6s) and 630/301B BIOS */ +void +SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT i; + + for(i = 0x0A; i <= 0x0E; i++) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,i,0x00); /* Clear SR0A-SR0E */ + } + + /* TW: New from 330, 650/LVDS/301LV BIOSes: */ + if(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE); + } +} + +/* TW: Checked against 300, 330, 650/LVDS (1.10.07) and 650/301LV BIOS */ +void +SiS_SetSync(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT RefreshRateTableIndex) +{ + USHORT sync; + USHORT temp; + + if(SiS_Pr->UseCustomMode) { + sync = SiS_Pr->CInfoFlag >> 8; + } else { + sync = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8; + } + + sync &= 0xC0; + temp = 0x2F | sync; + SiS_SetReg3(SiS_Pr->SiS_P3c2,temp); /* Set Misc(3c2) */ +} + +/* TW: Checked against 300, 330, 650/LVDS (1.10.07) and 650/301LVx (1.10.6s) BIOS */ +void +SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + UCHAR index; + USHORT tempah,i,modeflag,j; +#ifdef SIS315H + USHORT temp; + USHORT ResInfo,DisplayType; + const SiS_LCDACRT1DataStruct *LCDACRT1Ptr = NULL; +#endif + + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); /*unlock cr0-7 */ + + 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; + } + } + + if((SiS_Pr->SiS_IF_DEF_LVDS == 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + +#ifdef SIS315H + + /* LCDA */ + + temp = SiS_GetLCDACRT1Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,&ResInfo,&DisplayType); + + switch(DisplayType) { + case Panel_800x600 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT1800x600_1; break; + case Panel_1024x768 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1; break; + case Panel_1280x1024 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_1; break; + case Panel_1400x1050 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_1; break; + case Panel_1600x1200 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_1; break; + case Panel_800x600 + 16 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT1800x600_1_H; break; + case Panel_1024x768 + 16 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1_H; break; + case Panel_1280x1024 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_1_H; break; + case Panel_1400x1050 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_1_H; break; + case Panel_1600x1200 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_1_H; break; + case Panel_800x600 + 32 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT1800x600_2; break; + case Panel_1024x768 + 32 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_2; break; + case Panel_1280x1024 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2; break; + case Panel_1400x1050 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_2; break; + case Panel_1600x1200 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_2; break; + case Panel_800x600 + 48 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT1800x600_2_H; break; + case Panel_1024x768 + 48 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_2_H; break; + case Panel_1280x1024 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2_H; break; + case Panel_1400x1050 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_2_H; break; + case Panel_1600x1200 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_2_H; break; + default: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1; break; + } + + tempah = (LCDACRT1Ptr+ResInfo)->CR[0]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x00,tempah); + for(i=0x01,j=1;i<=0x07;i++,j++){ + tempah = (LCDACRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x10,j=8;i<=0x12;i++,j++){ + tempah = (LCDACRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x15,j=11;i<=0x16;i++,j++){ + tempah =(LCDACRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x0A,j=13;i<=0x0C;i++,j++){ + tempah = (LCDACRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3c4,i,tempah); + } + + tempah = (LCDACRT1Ptr+ResInfo)->CR[16]; + tempah &= 0x0E0; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x0E,tempah); + + tempah = (LCDACRT1Ptr+ResInfo)->CR[16]; + tempah &= 0x01; + tempah <<= 5; + if(modeflag & DoubleScanMode) tempah |= 0x080; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah); + +#endif + + } else { + + /* LVDS, 301, 301B, 301LV, 302LV, ... (non-LCDA) */ + + if(SiS_Pr->UseCustomMode) { + + for(i=0,j=0;i<=07;i++,j++) { + SiS_SetReg1(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]); + } + for(j=0x10;i<=10;i++,j++) { + SiS_SetReg1(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]); + } + for(j=0x15;i<=12;i++,j++) { + SiS_SetReg1(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]); + } + for(j=0x0A;i<=15;i++,j++) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]); + } + + tempah = SiS_Pr->CCRT1CRTC[16] & 0xE0; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x0E,tempah); + + tempah = SiS_Pr->CCRT1CRTC[16]; + tempah &= 0x01; + tempah <<= 5; + if(modeflag & DoubleScanMode) tempah |= 0x80; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,tempah); + + + } else { + + index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; /* Get index */ +#if 0 /* Not any longer... */ + if(HwDeviceExtension->jChipType < SIS_315H) { + index &= 0x3F; + } +#endif + + for(i=0,j=0;i<=07;i++,j++) { + tempah=SiS_Pr->SiS_CRT1Table[index].CR[i]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,j,tempah); + } + for(j=0x10;i<=10;i++,j++) { + tempah=SiS_Pr->SiS_CRT1Table[index].CR[i]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,j,tempah); + } + for(j=0x15;i<=12;i++,j++) { + tempah=SiS_Pr->SiS_CRT1Table[index].CR[i]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,j,tempah); + } + for(j=0x0A;i<=15;i++,j++) { + tempah=SiS_Pr->SiS_CRT1Table[index].CR[i]; + SiS_SetReg1(SiS_Pr->SiS_P3c4,j,tempah); + } + + tempah = SiS_Pr->SiS_CRT1Table[index].CR[16]; + tempah &= 0xE0; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x0E,tempah); + + tempah = SiS_Pr->SiS_CRT1Table[index].CR[16]; + tempah &= 0x01; + tempah <<= 5; + if(modeflag & DoubleScanMode) tempah |= 0x80; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,tempah); + + } + } + + if(SiS_Pr->SiS_ModeType > ModeVGA) SiS_SetReg1(SiS_Pr->SiS_P3d4,0x14,0x4F); +} + +BOOLEAN +SiS_GetLCDACRT1Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *ResInfo, + USHORT *DisplayType) + { + USHORT tempbx=0,modeflag=0; + USHORT CRT2CRTC=0; + + 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[RefreshRateTableIndex].Ext_CRT2CRTC; + } + + tempbx = SiS_Pr->SiS_LCDResInfo; + + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 32; + if(modeflag & HalfDCLK) tempbx += 16; + + *ResInfo = CRT2CRTC & 0x3F; + *DisplayType = tempbx; + + return 1; +} + +/* TW: Set offset and pitch - partly overruled by SetPitch() in XF86 */ +/* TW: Checked against 330, 650/LVDS (1.10.07), 650/301LV and 315 BIOS */ +void +SiS_SetCRT1Offset(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + 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,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + + temp = (DisplayUnit >> 8) & 0x0f; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp); + + temp = DisplayUnit & 0xFF; + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x13,temp); + + if(infoflag & InterlaceMode) DisplayUnit >>= 1; + + DisplayUnit <<= 5; + temp = (DisplayUnit & 0xff00) >> 8; + if (DisplayUnit & 0xff) temp++; + temp++; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x10,temp); +} + +/* TW: New from 650/LVDS 1.10.07, 630/301B and 630/LVDS BIOS */ +void +SiS_ResetCRT1VCLK(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT index; + + /* TW: We only need to do this if Panel Link is to be + * initialized, thus on 630/LVDS/301B, and 650/LVDS + */ + if(HwDeviceExtension->jChipType >= SIS_315H) { + 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(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xCF,0x20); + } else { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,0x20); + } + index = 1; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[index].SR2B); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[index].SR2C); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2D,0x80); + if(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10); + } else { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,0x10); + } + index = 0; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[index].SR2B); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[index].SR2C); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2D,0x80); +} + +/* TW: Checked against 300, 330, 650/LVDS, 650/301LVx, 315, 630/301B, 630/LVDS BIOS */ +void +SiS_SetCRT1VCLK(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT RefreshRateTableIndex) +{ + USHORT index=0; + + if(!SiS_Pr->UseCustomMode) { + index = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + } + + if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) + && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ){ + + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF); + + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VBVCLKData[index].Part4_A); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VBVCLKData[index].Part4_B); + + if(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2D,0x01); + } else { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2D,0x80); + } + + } else { + + if(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF); + } else { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,0x00); + } + + if(SiS_Pr->UseCustomMode) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->CSR2B); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->CSR2C); + } else { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[index].SR2B); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[index].SR2C); + } + + if(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2D,0x01); + } else { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2D,0x80); + } + } +} + +#if 0 /* TW: Not used */ +void +SiS_IsLowResolution(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT ModeFlag; + + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0x7F); + + if(ModeNo > 0x13) { + ModeFlag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + if ((ModeFlag & HalfDCLK) && (ModeFlag & DoubleScanMode)) { + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x80); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xF7); + } + } +} +#endif + +/* TW: Checked against 300, 630/LVDS, 650/LVDS, 315 and 330 BIOS */ +void +SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex) +{ + USHORT data,data2,data3; + USHORT infoflag=0,modeflag; + USHORT resindex,xres; + + if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + infoflag = SiS_Pr->CInfoFlag; + } else { + if(ModeNo > 0x13) { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag; + } else { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } + } + + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F); /* DAC pedestal */ + + if(ModeNo > 0x13) data = infoflag; + else data = 0; + + data2 = 0; + if(ModeNo > 0x13) { + if(SiS_Pr->SiS_ModeType > 0x02) { + data2 |= 0x02; + data3 = (SiS_Pr->SiS_ModeType - ModeVGA) << 2; + data2 |= data3; + } + } +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "Debug: Mode infoflag = %x, Chiptype %d\n", + data, HwDeviceExtension->jChipType); +#endif + if(data & InterlaceMode) data2 |= 0x20; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data2); + + if(SiS_Pr->UseCustomMode) { + xres = SiS_Pr->CHDisplay; + } else { + resindex = SiS_GetResInfo(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex); + if(ModeNo <= 0x13) { + xres = SiS_Pr->SiS_StResInfo[resindex].HTotal; + } else { + xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal; + } + } + + if(HwDeviceExtension->jChipType != SIS_300) { + data = 0x0000; + if(infoflag & InterlaceMode) { + if(xres == 1024) data = 0x0035; + else data = 0x0048; + } + data2 = data & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x19,data2); + data2 = (data & 0xFF00) >> 8; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,data2); + } + + if(modeflag & HalfDCLK) { + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08); + } + + if(HwDeviceExtension->jChipType == SIS_300) { + if(modeflag & LineCompareOff) { + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x08); + } else { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xF7); + } + } else if(HwDeviceExtension->jChipType < SIS_315H) { + if(modeflag & LineCompareOff) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,0x08); + } else { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xB7); + } + /* 630 BIOS does something for mode 0x12 here */ + } else { + if(modeflag & LineCompareOff) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,0x08); + } else { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xB7); + } + } + + if(HwDeviceExtension->jChipType != SIS_300) { + if(SiS_Pr->SiS_ModeType == ModeEGA) { + if(ModeNo > 0x13) { + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x40); + } + } + } + +#ifdef SIS315H + /* TW: 315 BIOS sets SR17 at this point */ + if(HwDeviceExtension->jChipType == SIS_315PRO) { + data = SiS_Get310DRAMType(SiS_Pr,ROMAddr,HwDeviceExtension); + data = SiS_Pr->SiS_SR15[2][data]; + if(SiS_Pr->SiS_ModeType == ModeText) { + data &= 0xc7; + } else { + data2 = SiS_GetOffset(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + data2 >>= 1; + if(infoflag & InterlaceMode) data2 >>= 1; + data3 = SiS_GetColorDepth(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex); + data3 >>= 1; + if(data3 == 0) data3++; + data2 /= data3; + if(data2 >= 0x50) { + data &= 0x0f; + data |= 0x50; + } + } + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x17,data); + } + + /* TW: 330 BIOS sets SR17 at this point */ + if(HwDeviceExtension->jChipType == SIS_330) { + data = SiS_Get310DRAMType(SiS_Pr,ROMAddr,HwDeviceExtension); + data = SiS_Pr->SiS_SR15[2][data]; + if(SiS_Pr->SiS_ModeType <= ModeEGA) { + data &= 0xc7; + } else { + if(SiS_Pr->UseCustomMode) { + data2 = SiS_Pr->CSRClock; + } else { + data2 = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK; + } + + data3 = SiS_GetColorDepth(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex); + data3 >>= 1; + + data2 *= data3; + + data3 = SiS_GetMCLK(SiS_Pr,ROMAddr, HwDeviceExtension); + data3 *= 1024; + + data2 = data3 / data2; + + 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; + } + } + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x17,data); + } +#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,ROMAddr,HwDeviceExtension,ModeNo,RefreshRateTableIndex,ModeIdIndex); + +#ifdef SIS315H + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x40) { + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x52,0x2c); + } else { + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x52,0x6c); + } + } +#endif +} + +/* TW: Checked against 300, 315, 330, 650/LVDS, 650/301LVx, 630/301B and 630/LVDS BIOS */ +void +SiS_SetVCLKState(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT ModeNo,USHORT RefreshRateTableIndex, + USHORT ModeIdIndex) +{ + USHORT data, data2=0; + USHORT VCLK, index=0; + + if (ModeNo <= 0x13) VCLK = 0; + else { + if(SiS_Pr->UseCustomMode) { + VCLK = SiS_Pr->CSRClock; + } else { + index = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; + } + } + + if(HwDeviceExtension->jChipType < SIS_315H) { /* 300 series */ + + data2 = 0x00; + if(VCLK > 150) data2 |= 0x80; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data2); /* DAC speed */ + + data2 = 0x00; + if(VCLK >= 150) data2 |= 0x08; /* VCLK > 150 */ + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data2); + + } else { /* 310/325 series */ + + data = 0; + if(VCLK >= 166) data |= 0x0c; /* TW: Was 200; is 166 in 650, 315 and 330 BIOSes */ + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data); + + if(VCLK >= 166) { /* TW: Was 200, is 166 in 650, 315 and 330 BIOSes */ + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7); + } +#if 0 /* Not done in 315 and 650/301LV/LVDS BIOSes: */ + data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1F); /* DAC pedestal */ + data &= 0xE7; + if(VCLK<200) data |= 0x10; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1F,data); /* DAC pedestal */ +#endif + } + + data2 = 0x03; + if((VCLK >= 135) && (VCLK < 160)) data2 = 0x02; + if((VCLK >= 160) && (VCLK < 260)) data2 = 0x01; + if(VCLK >= 260) data2 = 0x00; + + if(HwDeviceExtension->jChipType == SIS_540) { + if((VCLK == 203) || (VCLK < 234)) data2 = 0x02; + } + + if(HwDeviceExtension->jChipType < SIS_315H) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data2); /* DAC speed */ + } else { + if(HwDeviceExtension->jChipType > SIS_315PRO) { + /* TW: This "if" is done in 330 and 650/LVDS/301LV BIOSes; Not in 315 BIOS */ + if(ModeNo > 0x13) data2 &= 0xfc; + } + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data2); /* DAC speed */ + } +} + +/* TW: Checked against 650/301LVx 1.10.6s, 315, 630/301B BIOS */ +void +SiS_LoadDAC(SiS_Private *SiS_Pr,PSIS_HW_DEVICE_INFO HwDeviceExtension, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT data,data2; + USHORT time,i,j,k; + USHORT m,n,o; + USHORT si,di,bx,dl; + USHORT al,ah,dh; + USHORT DACAddr, DACData, shiftflag; + const USHORT *table = NULL; +#if 0 + USHORT tempah,tempch,tempcl,tempdh,tempal,tempbx; +#endif + + 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; + } + } + +#if 0 + if(!(ds:489 & 0x08)) { +#endif + + 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( ( (HwDeviceExtension->jChipType == SIS_630) && /* 630/301B LCD */ + (SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS302B)) && + (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ) || + (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_SetReg3(SiS_Pr->SiS_P3c6,0xFF); + } else { + shiftflag = 1; + DACAddr = SiS_Pr->SiS_Part5Port; + DACData = SiS_Pr->SiS_Part5Port + 1; + } + + SiS_SetReg3(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_SetReg3(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_SetReg3(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 */ + } +#if 0 + } /* ds:489 & 0x08 */ +#endif + +#if 0 + if((!(ds:489 & 0x08)) && (ds:489 & 0x06)) { + tempbx = 0; + for(i=0; i< 256; i++) { + SiS_SetReg3(SiS_Pr->SiS_P3c8-1,tempbx); /* 7f87 */ + tempah = SiS_GetReg3(SiS_Pr->SiS_P3c8+1); /* 7f83 */ + tempch = SiS_GetReg3(SiS_Pr->SiS_P3c8+1); + tempcl = SiS_GetReg3(SiS_Pr->SiS_P3c8+1); + tempdh = tempah; + tempal = 0x4d * tempdh; /* 7fb8 */ + tempbx += tempal; + tempal = 0x97 * tempch; + tempbx += tempal; + tempal = 0x1c * tempcl; + tempbx += tempal; + if((tempbx & 0x00ff) > 0x80) tempbx += 0x100; + tempdh = (tempbx & 0x00ff) >> 8; + tempch = tempdh; + tempcl = tempdh; + SiS_SetReg3(SiS_Pr->SiS_P3c8,(tempbx & 0xff)); /* 7f7c */ + SiS_SetReg3(SiS_Pr->SiS_P3c8+1,tempdh); /* 7f92 */ + SiS_SetReg3(SiS_Pr->SiS_P3c8+1,tempch); + SiS_SetReg3(SiS_Pr->SiS_P3c8+1,tempcl); + } + } +#endif +} + +void +SiS_WriteDAC(SiS_Private *SiS_Pr, USHORT DACData, USHORT shiftflag, + USHORT dl, USHORT ah, USHORT al, USHORT dh) +{ + USHORT temp; + USHORT 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_SetReg3(DACData,(USHORT)dh); + SiS_SetReg3(DACData,(USHORT)bh); + SiS_SetReg3(DACData,(USHORT)bl); +} + +static ULONG +GetDRAMSize(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + ULONG AdapterMemorySize = 0; +#ifdef SIS315H + USHORT counter; +#endif + +#ifdef SIS315H + if ((HwDeviceExtension->jChipType == SIS_315H) || + (HwDeviceExtension->jChipType == SIS_315) || + (HwDeviceExtension->jChipType == SIS_315PRO)) { + + counter = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); + AdapterMemorySize = 1 << ((counter & 0xF0) >> 4); + counter >>= 2; + counter &= 0x03; + if(counter == 0x02) { + AdapterMemorySize += (AdapterMemorySize / 2); /* DDR asymetric */ + } else if(counter != 0) { + AdapterMemorySize <<= 1; /* SINGLE_CHANNEL_2_RANK or DUAL_CHANNEL_1_RANK */ + } + AdapterMemorySize *= (1024*1024); + + } else if(HwDeviceExtension->jChipType == SIS_330) { + + counter = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); + AdapterMemorySize = 1 << ((counter & 0xF0) >> 4); + counter &= 0x0c; + if(counter != 0) { + AdapterMemorySize <<= 1; + } + AdapterMemorySize *= (1024*1024); + + } else if((HwDeviceExtension->jChipType == SIS_550) || + (HwDeviceExtension->jChipType == SIS_740) || + (HwDeviceExtension->jChipType == SIS_650)) { + + counter = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14) & 0x3F; + counter++; + AdapterMemorySize = counter * 4; + AdapterMemorySize *= (1024*1024); + } +#endif + +#ifdef SIS300 + if ((HwDeviceExtension->jChipType==SIS_300) || + (HwDeviceExtension->jChipType==SIS_540) || + (HwDeviceExtension->jChipType==SIS_630) || + (HwDeviceExtension->jChipType==SIS_730)) { + + AdapterMemorySize = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14) & 0x3F; + AdapterMemorySize++; + AdapterMemorySize *= (1024*1024); + + } +#endif + + return AdapterMemorySize; +} + +#ifndef LINUX_XF86 +void +SiS_ClearBuffer(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo) +{ + PVOID VideoMemoryAddress = (PVOID)HwDeviceExtension->pjVideoMemoryAddress; + ULONG AdapterMemorySize = (ULONG)HwDeviceExtension->ulVideoMemorySize; + PUSHORT pBuffer; + int i; + + if (SiS_Pr->SiS_ModeType>=ModeEGA) { + if(ModeNo > 0x13) { + AdapterMemorySize = GetDRAMSize(SiS_Pr, HwDeviceExtension); + SiS_SetMemory(VideoMemoryAddress,AdapterMemorySize,0); + } else { + pBuffer = VideoMemoryAddress; + for(i=0; i<0x4000; i++) + pBuffer[i] = 0x0000; + } + } else { + pBuffer = VideoMemoryAddress; + if (SiS_Pr->SiS_ModeType < ModeCGA) { + for(i=0; i<0x4000; i++) + pBuffer[i] = 0x0720; + } else { + SiS_SetMemory(VideoMemoryAddress,0x8000,0); + } + } +} +#endif + +void +SiS_DisplayOn(SiS_Private *SiS_Pr) +{ + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x01,0xDF,0x00); +} + +void +SiS_DisplayOff(SiS_Private *SiS_Pr) +{ + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x01,0xDF,0x20); +} + + +/* ========================================== */ +/* SR CRTC GR */ +void +SiS_SetReg1(USHORT port, USHORT index, USHORT data) +{ + OutPortByte(port,index); + OutPortByte(port+1,data); +} + +/* ========================================== */ +/* AR(3C0) */ +void +SiS_SetReg2(SiS_Private *SiS_Pr, USHORT port, USHORT index, USHORT data) +{ + InPortByte(port+0x3da-0x3c0); + OutPortByte(SiS_Pr->SiS_P3c0,index); + OutPortByte(SiS_Pr->SiS_P3c0,data); + OutPortByte(SiS_Pr->SiS_P3c0,0x20); +} + +void +SiS_SetReg3(USHORT port, USHORT data) +{ + OutPortByte(port,data); +} + +void +SiS_SetReg4(USHORT port, ULONG data) +{ + OutPortLong(port,data); +} + +void +SiS_SetReg5(USHORT port, USHORT data) +{ + OutPortWord(port,data); +} + +UCHAR SiS_GetReg1(USHORT port, USHORT index) +{ + UCHAR data; + + OutPortByte(port,index); + data = InPortByte(port+1); + + return(data); +} + +UCHAR +SiS_GetReg2(USHORT port) +{ + UCHAR data; + + data= InPortByte(port); + + return(data); +} + +ULONG +SiS_GetReg3(USHORT port) +{ + ULONG data; + + data = InPortLong(port); + + return(data); +} + +USHORT +SiS_GetReg4(USHORT port) +{ + ULONG data; + + data = InPortWord(port); + + return(data); +} + +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); + } + +} + +#if 0 /* TW: Unused */ +void +SiS_SetInterlace(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT RefreshRateTableIndex) +{ + ULONG Temp; + USHORT data,Temp2; + + if (ModeNo<=0x13) return; + + Temp = (ULONG)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x01); + Temp++; + Temp <<= 3; + + if(Temp == 1024) data = 0x0035; + else if(Temp == 1280) data = 0x0048; + else data = 0x0000; + + Temp2 = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag; + Temp2 &= InterlaceMode; + if(Temp2 == 0) data=0x0000; + + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x19,data); + + Temp = (ULONG)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x1A); + Temp = (USHORT)(Temp & 0xFC); + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x1A,(USHORT)Temp); + + Temp = (ULONG)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x0f); + Temp2 = (USHORT)Temp & 0xBF; + if(ModeNo==0x37) Temp2 |= 0x40; + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x1A,(USHORT)Temp2); +} +#endif + +/* TW: Checked against 330, 650/LVDS (1.10.07), 650/301LVx (1.10.6s) and 315 BIOS */ +#ifdef SIS315H +void +SiS_SetCRT1FIFO_310(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT modeflag; + + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE); /* disable auto-threshold */ + + if(ModeNo > 0x13) { + if(SiS_Pr->UseCustomMode) { + modeflag = SiS_Pr->CModeFlag; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + } + if( (!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x08,0x34); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0); + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01); + } else { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x08,0xAE); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0); + } + } else { + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x08,0xAE); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0); + } +} +#endif + +#ifdef SIS300 +void +SiS_SetCRT1FIFO_300(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,PSIS_HW_DEVICE_INFO HwDeviceExtension, + 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_GetReg1(SiS_Pr->SiS_P3c4,0x3A); + index &= 0x07; + MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */ + + tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x35); + tempah &= 0xc3; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,tempah); + + do { + ThresholdLow = SiS_CalcDelay(SiS_Pr, ROMAddr, VCLK, colorth, MCLK); + ThresholdLow++; + if(ThresholdLow < 0x13) break; + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc); + ThresholdLow = 0x13; + tempah = SiS_GetReg1(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_SetReg1(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_SetReg1(SiS_Pr->SiS_P3c4,0x3B,0x09); + + /* Write CRT/CPU threshold high */ + temp = ThresholdLow + 3; + if(temp > 0x0f) temp = 0x0f; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x09,temp); +} + +USHORT +SiS_CalcDelay(SiS_Private *SiS_Pr, UCHAR *ROMAddr, 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); +} + +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_GetReg1(SiS_Pr->SiS_P3c4,0x18); + tempah &= 0x62; + tempah >>= 1; + tempal = tempah; + tempah >>= 3; + tempal |= tempah; + tempal &= 0x07; + tempcl = ThTiming[tempal]; + tempbx = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); + tempbx >>= 6; + tempah = SiS_GetReg1(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); +} + +#if 0 /* TW: Old fragment, unused */ +USHORT +SiS_CalcDelay(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT key) +{ + USHORT data,data2,temp0,temp1; + 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}; + + 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}; + + UCHAR ThTiming[]= {1,2,2,3,0,1,1,2}; + + data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); + data=data>>6; + data2=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); + data2=(data2>>4)&0x0C; + data=data|data2; + data=data<1; + if(key==0) { + temp0=(USHORT)ThLowA[data]; + temp1=(USHORT)ThLowA[data+1]; + } else { + temp0=(USHORT)ThLowB[data]; + temp1=(USHORT)ThLowB[data+1]; + } + + data2=0; + data=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x18); + if(data&0x02) data2=data2|0x01; + if(data&0x20) data2=data2|0x02; + if(data&0x40) data2=data2|0x04; + + data=temp1*ThTiming[data2]+temp0; + return(data); +} +#endif + +void +SiS_SetCRT1FIFO_630(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo, + PSIS_HW_DEVICE_INFO HwDeviceExtension, + 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_GetReg1(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(HwDeviceExtension->jChipType == SIS_730) { + + do { + B = SiS_CalcDelay2(SiS_Pr, ROMAddr, FQBQData730[i], HwDeviceExtension) * 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, ROMAddr, FQBQData[i], HwDeviceExtension) * 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(HwDeviceExtension->jChipType == SIS_730) { + } else { + i = 9; + } + ThresholdLow = 0x02; + } + + /* Write foreground and background queue */ + if(HwDeviceExtension->jChipType == SIS_730) { + + data2 = FQBQData730[i]; + data2 = (data2 & 0xC0) >> 5; + data2 <<= 8; + +#ifndef LINUX_XF86 + SiS_SetReg4(0xcf8,0x80000050); + eax = SiS_GetReg3(0xcfc); + eax &= 0xfffff9ff; + eax |= data2; + SiS_SetReg4(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; + +#ifndef LINUX_XF86 + SiS_SetReg4(0xcf8,0x800000A0); + eax = SiS_GetReg3(0xcfc); + eax &= 0x00ffffff; + eax |= data2; + SiS_SetReg4(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; + +#ifndef LINUX_XF86 + SiS_SetReg4(0xcf8,0x80000050); + eax = SiS_GetReg3(0xcfc); + eax &= 0xf0ffffff; + eax |= data2; + SiS_SetReg4(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; + +#ifndef LINUX_XF86 + SiS_SetReg4(0xcf8,0x800000A0); + eax = SiS_GetReg3(0xcfc); + eax &= 0xf0ffffff; + eax |= data2; + SiS_SetReg4(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_SetReg1(SiS_Pr->SiS_P3c4,0x08,data); + + data = (ThresholdLow & 0x10) << 1; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data); + + /* What is this? */ + SiS_SetReg1(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); +} + +USHORT +SiS_CalcDelay2(SiS_Private *SiS_Pr, UCHAR *ROMAddr,UCHAR key, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + 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(HwDeviceExtension->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_GetReg1(SiS_Pr->SiS_P3c4,0x14); + if(data & 0x0080) index += 12; + data = LatencyFactor[index]; + } + return(data); +} +#endif + +/* =============== Autodetection ================ */ +/* I N C O M P L E T E */ + +BOOLEAN +SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + 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, 0x0000, 0x0000, 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,tempah,temp; + + if(HwDeviceExtension->jChipType < SIS_315H) { + + tempax = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x18); + tempbx = tempax & 0x0F; + if(!(tempax & 0x10)){ + if(SiS_Pr->SiS_IF_DEF_LVDS == 1){ + tempbx = 0; + temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x38); + if(temp & 0x40) tempbx |= 0x08; + if(temp & 0x20) tempbx |= 0x02; + if(temp & 0x01) tempbx |= 0x01; + temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x39); + if(temp & 0x80) tempbx |= 0x04; + } else { + return 0; + } + } + tempbx = PanelTypeTable300[tempbx]; + tempbx |= LCDSync; + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x36,temp); + temp = (tempbx & 0xFF00) >> 8; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,~(LCDSyncBit|LCDRGB18Bit),temp); + + } else { + + tempax = tempah = SiS_GetReg1(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_SetReg1(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_IF_DEF_LVDS == 0) { + temp = tempbx & 0x04; + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x39,0xfb,temp); + } + + } + return 1; +} + + +#ifdef LINUXBIOS + +void +SiS_DetectMonitor(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr) +{ + UCHAR DAC_TEST_PARMS[] = {0x0F,0x0F,0x0F}; + UCHAR DAC_CLR_PARMS[] = {0x00,0x00,0x00}; + USHORT SR1F; + + SR1F = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1F); /* backup DAC pedestal */ + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1F,0x04); + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + if(!(SiS_BridgeIsOn(SiS_Pr, BaseAddr))) { + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x30,0x41); + } + } + + SiSSetMode(SiS_Pr,HwDeviceExtension,0x2E); + if(HwDeviceExtension->jChipType >= SIS_650) { + /* TW: On 650 only - enable CRT1 */ + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x63,0xbf); + } + SiS_SetReg3(SiS_Pr->SiS_P3c6,0xff); + SiS_ClearDAC(SiS_Pr, SiS_Pr->SiS_P3c8); + SiS_LongWait(SiS_Pr); + SiS_LongWait(SiS_Pr); + SiS_LongWait(SiS_Pr); + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x32,0xDF,0x00); + if(SiS_TestMonitorType(SiS_Pr, DAC_TEST_PARMS[0],DAC_TEST_PARMS[1],DAC_TEST_PARMS[2])) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x32,0xDF,0x20); + } else if(SiS_TestMonitorType(SiS_Pr, DAC_TEST_PARMS[0],DAC_TEST_PARMS[1],DAC_TEST_PARMS[2])) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x32,0xDF,0x20); + } + SiS_TestMonitorType(SiS_Pr, DAC_CLR_PARMS[0],DAC_CLR_PARMS[1],DAC_CLR_PARMS[2]); + + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1F,SR1F); +} + +USHORT +SiS_TestMonitorType(SiS_Private *SiS_Pr, UCHAR R_DAC,UCHAR G_DAC,UCHAR B_DAC) +{ + USHORT temp,tempbx; + + tempbx = R_DAC * 0x4d + G_DAC * 0x97 + B_DAC * 0x1c; + if((tempbx & 0x00ff) > 0x80) tempbx += 0x100; + tempbx = (tempbx & 0xFF00) >> 8; + R_DAC = (UCHAR) tempbx; + G_DAC = (UCHAR) tempbx; + B_DAC = (UCHAR) tempbx; + + SiS_SetReg3(SiS_Pr->SiS_P3c8,0x00); + SiS_SetReg3(SiS_Pr->SiS_P3c9,R_DAC); + SiS_SetReg3(SiS_Pr->SiS_P3c9,G_DAC); + SiS_SetReg3(SiS_Pr->SiS_P3c9,B_DAC); + SiS_LongWait(SiS_Pr); + temp=SiS_GetReg2(SiS_Pr->SiS_P3c2); + if(temp & 0x10) return(1); + else return(0); +} + +void +SiS_GetSenseStatus(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,UCHAR *ROMAddr) +{ + USHORT tempax=0,tempbx,tempcx,temp; + USHORT P2reg0=0,SenseModeNo=0,OutputSelect=*SiS_Pr->pSiS_OutputSelect; + USHORT ModeIdIndex,i; + USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1){ + SiS_GetPanelID(SiS_Pr); + temp=LCDSense; + temp=temp|SiS_SenseCHTV(SiS_Pr); + tempbx=~(LCDSense|AVIDEOSense|SVIDEOSense); + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x32,tempbx,temp); + } else { /* for 301 */ + if(SiS_Pr->SiS_IF_DEF_HiVision==1) { /* for HiVision */ + tempax=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x38); + temp=tempax&0x01; + tempax=SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3A); + temp=temp|(tempax&0x02); + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x32,0xA0,temp); + } else { + if(SiS_BridgeIsOn(SiS_Pr, BaseAddr)==0) { /* TW: Inserted "==0" */ + P2reg0 = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x00); + if(!(SiS_BridgeIsEnable(SiS_Pr, BaseAddr,HwDeviceExtension))) { + SenseModeNo=0x2e; + temp = SiS_SearchModeID(SiS_Pr, ROMAddr,&SenseModeNo,&ModeIdIndex); + SiS_Pr->SiS_SetFlag = 0x00; + SiS_Pr->SiS_ModeType = ModeVGA; + SiS_Pr->SiS_VBInfo = SetCRT2ToRAMDAC |LoadDACFlag |SetInSlaveMode; + SiS_SetCRT2Group301(SiS_Pr, BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension); + for(i=0;i<20;i++) { + SiS_LongWait(SiS_Pr); + } + } + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x00,0x1c); + tempax=0; + tempbx=*SiS_Pr->pSiS_RGBSenseData; + if(SiS_Is301B(SiS_Pr, BaseAddr)){ + tempbx=*SiS_Pr->pSiS_RGBSenseData2; + } + tempcx=0x0E08; + if(SiS_Sense(SiS_Pr, tempbx,tempcx)){ + if(SiS_Sense(SiS_Pr, tempbx,tempcx)){ + tempax=tempax|Monitor2Sense; + } + } + tempbx=*SiS_Pr->pSiS_YCSenseData; + if(SiS_Is301B(SiS_Pr, BaseAddr)){ + tempbx=*SiS_Pr->pSiS_YCSenseData2; + } + tempcx=0x0604; + if(SiS_Sense(SiS_Pr, tempbx,tempcx)){ + if(SiS_Sense(SiS_Pr,tempbx,tempcx)){ + tempax=tempax|SVIDEOSense; + } + } + + if(ROMAddr && SiS_Pr->SiS_UseROM) { +#ifdef SIS300 + if((HwDeviceExtension->jChipType==SIS_630)|| + (HwDeviceExtension->jChipType==SIS_730)) { + OutputSelect = ROMAddr[0xfe]; + } +#endif +#ifdef SIS315H + if(HwDeviceExtension->jChipType >= SIS_315H) { + OutputSelect = ROMAddr[0xf3]; + if(HwDeviceExtension->jChipType == SIS_330) { + OutputSelect = ROMAddr[0x11b]; + } + } +#endif + } + if(OutputSelect & BoardTVType){ + tempbx = *SiS_Pr->pSiS_VideoSenseData; + if(SiS_Is301B(SiS_Pr, BaseAddr)){ + tempbx = *SiS_Pr->pSiS_VideoSenseData2; + } + tempcx = 0x0804; + if(SiS_Sense(SiS_Pr, tempbx,tempcx)){ + if(SiS_Sense(SiS_Pr, tempbx,tempcx)){ + tempax |= AVIDEOSense; + } + } + } else { + if(!(tempax & SVIDEOSense)){ + tempbx = *SiS_Pr->pSiS_VideoSenseData; + if(SiS_Is301B(SiS_Pr, BaseAddr)){ + tempbx = *SiS_Pr->pSiS_VideoSenseData2; + } + tempcx = 0x0804; + if(SiS_Sense(SiS_Pr,tempbx,tempcx)){ + if(SiS_Sense(SiS_Pr, tempbx,tempcx)){ + tempax |= AVIDEOSense; + } + } + } + } + } + + if(SiS_SenseLCD(SiS_Pr, HwDeviceExtension)){ + tempax |= LCDSense; + } + + tempbx=0; + tempcx=0; + SiS_Sense(SiS_Pr, tempbx,tempcx); + + if(SiS_Pr->SiS_VBType & (VB_SIS30xLV|VB_SIS30xNEW)) { + tempax &= 0x00ef; /* 301lv to disable CRT2*/ + } + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x32,~0xDF,tempax); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x00,P2reg0); + if(!(P2reg0 & 0x20)) { + SiS_Pr->SiS_VBInfo = DisableCRT2Display; + SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension); + } + } + } +} + +BOOLEAN +SiS_Sense(SiS_Private *SiS_Pr, USHORT tempbx,USHORT tempcx) +{ + USHORT temp,i,tempch; + + temp = tempbx & 0xFF; + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x11,temp); + temp = (tempbx & 0xFF00) >> 8; + temp |= (tempcx & 0x00FF); + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,~0x1F,temp); + + for(i=0; i<10; i++) SiS_LongWait(SiS_Pr); + + tempch = (tempcx & 0x7F00) >> 8; + temp = SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x03); + temp ^= 0x0E; + temp &= tempch; + if(temp>0) return 1; + else return 0; +} + +USHORT +SiS_SenseLCD(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT temp; + + temp=SiS_GetPanelID(SiS_Pr); + if(!temp) temp=SiS_GetLCDDDCInfo(SiS_Pr, HwDeviceExtension); + return(temp); +} + +BOOLEAN +SiS_GetLCDDDCInfo(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT temp; + /*add lcd sense*/ + if(HwDeviceExtension->ulCRT2LCDType==LCD_UNKNOWN) + return 0; + else{ + temp=(USHORT)HwDeviceExtension->ulCRT2LCDType; + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x36,temp); + return 1; + } +} + +USHORT +SiS_SenseCHTV(SiS_Private *SiS_Pr) +{ + USHORT temp,push0e,status; + + status=0; + push0e = SiS_GetCH700x(SiS_Pr, 0x0e); + push0e = (push0e << 8) | 0x0e; + SiS_SetCH700x(SiS_Pr, 0x0b0e); + SiS_SetCH700x(SiS_Pr, 0x0110); + SiS_SetCH700x(SiS_Pr, 0x0010); + temp = SiS_GetCH700x(SiS_Pr, 0x10); + if(temp & 0x08) status |= SVIDEOSense; + if(temp & 0x02) status |= AVIDEOSense; + SiS_SetCH700x(SiS_Pr, push0e); + return(status); +} +#endif /* LINUXBIOS */ + +/* ================ for TC only ================= */ + +#ifdef TC + +int +INT1AReturnCode(union REGS regs) +{ + if (regs.x.cflag) + { + /*printf("Error to find pci device!\n"); */ + return 1; + } + + switch(regs.h.ah) + { + case 0: return 0; + break; + case 0x81: printf("Function not support\n"); + break; + case 0x83: printf("bad vendor id\n"); + break; + case 0x86: printf("device not found\n"); + break; + case 0x87: printf("bad register number\n"); + break; + case 0x88: printf("set failed\n"); + break; + case 0x89: printf("buffer too small"); + break; + } + return 1; +} + +unsigned +FindPCIIOBase(unsigned index,unsigned deviceid) +{ + union REGS regs; + + regs.h.ah = 0xb1; /*PCI_FUNCTION_ID */ + regs.h.al = 0x02; /*FIND_PCI_DEVICE */ + regs.x.cx = deviceid; + regs.x.dx = 0x1039; + regs.x.si = index; /* find n-th device */ + + int86(0x1A, ®s, ®s); + + if (INT1AReturnCode(regs)!=0) + return 0; + + /* regs.h.bh *//* bus number */ + /* regs.h.bl *//* device number */ + regs.h.ah = 0xb1; /*PCI_FUNCTION_ID */ + regs.h.al = 0x09; /*READ_CONFIG_WORD */ + regs.x.cx = deviceid; + regs.x.dx = 0x1039; + regs.x.di = 0x18; /* register number */ + int86(0x1A, ®s, ®s); + + if (INT1AReturnCode(regs)!=0) + return 0; + return regs.x.cx; +} + + +void +main(int argc, char *argv[]) +{ + SIS_HW_DEVICE_INFO HwDeviceExtension; + USHORT temp; + USHORT ModeNo; + + /*HwDeviceExtension.pjVirtualRomBase =(PUCHAR) MK_FP(0xC000,0); */ + /*HwDeviceExtension.pjVideoMemoryAddress = (PUCHAR)MK_FP(0xA000,0);*/ + +#ifdef SIS300 + HwDeviceExtension.ulIOAddress = (FindPCIIOBase(0,0x6300)&0xFF80) + 0x30; + HwDeviceExtension.jChipType = SIS_630; +#endif + +#ifdef SIS315H +// HwDeviceExtension.ulIOAddress = (FindPCIIOBase(0,0x5315)&0xFF80) + 0x30; +// HwDeviceExtension.jChipType = SIS_550; + HwDeviceExtension.ulIOAddress = (FindPCIIOBase(0,0x325)&0xFF80) + 0x30; + HwDeviceExtension.jChipType = SIS_315H; +#endif + + HwDeviceExtension.ujVBChipID = VB_CHIP_301; + strcpy(HwDeviceExtension.szVBIOSVer,"0.84"); + HwDeviceExtension.bSkipDramSizing = FALSE; + HwDeviceExtension.ulVideoMemorySize = 0; + if(argc==2) { + ModeNo=atoi(argv[1]); + } + else { + ModeNo=0x2e; + /*ModeNo=0x37; */ /* 1024x768x 4bpp */ + /*ModeNo=0x38; *//* 1024x768x 8bpp */ + /*ModeNo=0x4A; *//* 1024x768x 16bpp */ + /*ModeNo=0x47;*/ /* 800x600x 16bpp */ + } + /* SiSInit(SiS_Pr, &HwDeviceExtension);*/ + SiSSetMode(SiS_Pr, &HwDeviceExtension, ModeNo); +} +#endif /* TC END */ + +/* ================ LINUX XFREE86 ====================== */ + +/* Helper functions */ + +#ifdef LINUX_XF86 +USHORT +SiS_CalcModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + SISPtr pSiS = SISPTR(pScrn); + UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; + UShort ModeIndex = 0; + + if((pSiS->HaveCustomModes) && (!(mode->type & M_T_DEFAULT))) + return 0xfe; + + switch(mode->HDisplay) + { + case 320: + if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_320x480[i]; + } + break; + case 512: + if(mode->VDisplay == 384) { + ModeIndex = ModeIndex_512x384[i]; + } + break; + case 640: + if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_640x480[i]; + } else if(mode->VDisplay == 400) { + ModeIndex = ModeIndex_640x400[i]; + } + break; + case 720: + if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_720x480[i]; + } else if(mode->VDisplay == 576) { + ModeIndex = ModeIndex_720x576[i]; + } + break; + case 800: + if(mode->VDisplay == 600) { + ModeIndex = ModeIndex_800x600[i]; + } else if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_800x480[i]; + } + break; + case 848: + if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_848x480[i]; + } + break; + case 856: + if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_856x480[i]; + } + break; + case 1024: + if(mode->VDisplay == 768) { + ModeIndex = ModeIndex_1024x768[i]; + } else if(mode->VDisplay == 576) { + ModeIndex = ModeIndex_1024x576[i]; + } else if(pSiS->VGAEngine == SIS_300_VGA) { + if(mode->VDisplay == 600) { + ModeIndex = ModeIndex_1024x600[i]; + } + } + break; + case 1152: + if(mode->VDisplay == 864) { + ModeIndex = ModeIndex_1152x864[i]; + } else if(pSiS->VGAEngine == SIS_300_VGA) { + if(mode->VDisplay == 768) { + ModeIndex = ModeIndex_1152x768[i]; + } + } + break; + case 1280: + if(mode->VDisplay == 960) { + if(pSiS->VGAEngine == SIS_300_VGA) { + ModeIndex = ModeIndex_300_1280x960[i]; + } else { + ModeIndex = ModeIndex_310_1280x960[i]; + } + } else if (mode->VDisplay == 1024) { + ModeIndex = ModeIndex_1280x1024[i]; + } else if (mode->VDisplay == 720) { + ModeIndex = ModeIndex_1280x720[i]; + } else if(pSiS->VGAEngine == SIS_315_VGA) { + if (mode->VDisplay == 768) { + ModeIndex = ModeIndex_1280x768[i]; + } + } + break; + case 1360: + if(mode->VDisplay == 768) { + ModeIndex = ModeIndex_1360x768[i]; + } + break; + case 1400: + if(pSiS->VGAEngine == SIS_315_VGA) { + if(mode->VDisplay == 1050) { + ModeIndex = ModeIndex_1400x1050[i]; + } + } + break; + case 1600: + if(mode->VDisplay == 1200) { + ModeIndex = ModeIndex_1600x1200[i]; + } + break; + case 1920: + if(mode->VDisplay == 1440) { + ModeIndex = ModeIndex_1920x1440[i]; + } + break; + case 2048: + if(mode->VDisplay == 1536) { + if(pSiS->VGAEngine == SIS_300_VGA) { + ModeIndex = ModeIndex_300_2048x1536[i]; + } else { + ModeIndex = ModeIndex_310_2048x1536[i]; + } + } + break; + } + + return(ModeIndex); +} + +USHORT +SiS_CheckCalcModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags) +{ + SISPtr pSiS = SISPTR(pScrn); + UShort i = (pSiS->CurrentLayout.bitsPerPixel+7)/8 - 1; + UShort ModeIndex = 0; + + if(VBFlags & CRT2_LCD) { + + if( (mode->HDisplay <= pSiS->LCDwidth) && + (mode->VDisplay <= pSiS->LCDheight) ) { + + if(VBFlags & VB_LVDS) { /* LCD on LVDS */ + + switch(mode->HDisplay) + { + case 512: + if(mode->VDisplay == 384) { + if(pSiS->LCDwidth != 1024 || pSiS->LCDheight != 600) { /* not supported on 1024x600 panels */ + ModeIndex = ModeIndex_512x384[i]; + } + } + break; + case 640: + if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_640x480[i]; + } else if(mode->VDisplay == 400) { + ModeIndex = ModeIndex_640x400[i]; + } + break; + case 800: + if(mode->VDisplay == 600) { + ModeIndex = ModeIndex_800x600[i]; + } + break; + case 1024: + if(mode->VDisplay == 768) { + ModeIndex = ModeIndex_1024x768[i]; + } else if(pSiS->VGAEngine == SIS_300_VGA) { + if(mode->VDisplay == 600) { + if(pSiS->LCDheight == 600) { /* This mode only supported on 1024x600 panels */ + ModeIndex = ModeIndex_1024x600[i]; + } + } + } + break; + case 1152: + if(pSiS->VGAEngine == SIS_300_VGA) { + if(mode->VDisplay == 768) { + ModeIndex = ModeIndex_1152x768[i]; + } + } + break; + case 1280: + if(mode->VDisplay == 1024) { + ModeIndex = ModeIndex_1280x1024[i]; + } else if(pSiS->VGAEngine == SIS_315_VGA) { + if(mode->VDisplay == 768) { + ModeIndex = ModeIndex_1280x768[i]; + } + } + break; + case 1400: + if(mode->VDisplay == 1050) { + if(pSiS->VGAEngine == SIS_315_VGA) { + ModeIndex = ModeIndex_1400x1050[i]; + } + } + break; + } + + } else { /* LCD on 301(B) */ + + switch(mode->HDisplay) + { + case 512: + if(mode->VDisplay == 384) { + ModeIndex = ModeIndex_512x384[i]; + } + break; + case 640: + if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_640x480[i]; + } else if(mode->VDisplay == 400) { + ModeIndex = ModeIndex_640x400[i]; + } + break; + case 800: + if(mode->VDisplay == 600) { + ModeIndex = ModeIndex_800x600[i]; + } + break; + case 1024: + if(mode->VDisplay == 768) { + ModeIndex = ModeIndex_1024x768[i]; + } + break; + case 1280: + if(mode->VDisplay == 960) { + if(pSiS->VGAEngine == SIS_300_VGA) { + ModeIndex = ModeIndex_300_1280x960[i]; + } else { + ModeIndex = ModeIndex_310_1280x960[i]; + } + } else if (mode->VDisplay == 1024) { + ModeIndex = ModeIndex_1280x1024[i]; + } + break; + case 1400: + if(mode->VDisplay == 1050) { + if(pSiS->VGAEngine == SIS_315_VGA) { + ModeIndex = ModeIndex_1400x1050[i]; + } + } + break; + case 1600: + if(mode->VDisplay == 1200) { + ModeIndex = ModeIndex_1600x1200[i]; + } + break; + } + + } + + } + + } else if(VBFlags & CRT2_TV) { + + if(VBFlags & VB_CHRONTEL) { /* TV on Chrontel */ + + switch(mode->HDisplay) + { + case 512: + if(pSiS->VGAEngine == SIS_315_VGA) { + if(mode->VDisplay == 384) { + ModeIndex = ModeIndex_512x384[i]; + } + } + break; + case 640: + if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_640x480[i]; + } else if(mode->VDisplay == 400) { + ModeIndex = ModeIndex_640x400[i]; + } + break; + case 800: + if(mode->VDisplay == 600) { + ModeIndex = ModeIndex_800x600[i]; + } + break; + case 1024: + if(mode->VDisplay == 768) { + if(pSiS->VGAEngine == SIS_315_VGA) { + ModeIndex = ModeIndex_1024x768[i]; + } + } + break; + } + + } else { /* TV on 301(B/LV) */ + + switch(mode->HDisplay) + { + case 512: + if(mode->VDisplay == 384) { + ModeIndex = ModeIndex_512x384[i]; + } + break; + case 640: + if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_640x480[i]; + } + break; + case 720: + if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_720x480[i]; + } else if(mode->VDisplay == 576) { + ModeIndex = ModeIndex_720x576[i]; + } + break; + case 800: + if(mode->VDisplay == 600) { + ModeIndex = ModeIndex_800x600[i]; + } + break; + case 1024: /* Not supported with depth 32 */ + if((mode->VDisplay == 768) && (i != 3) ) { + if(VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) { + ModeIndex = ModeIndex_1024x768[i]; + } + } + break; + } + + } + + } else if(VBFlags & CRT2_VGA) { /* CRT2 is VGA2 */ + + switch(mode->HDisplay) + { + case 640: + if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_640x480[i]; + } else if(mode->VDisplay == 400) { + ModeIndex = ModeIndex_640x400[i]; + } + break; + case 800: + if(mode->VDisplay == 600) { + ModeIndex = ModeIndex_800x600[i]; + } else if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_800x480[i]; + } + break; + case 848: + if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_848x480[i]; + } + break; + case 856: + if(mode->VDisplay == 480) { + ModeIndex = ModeIndex_856x480[i]; + } + break; + case 1024: + if(mode->VDisplay == 768) { + ModeIndex = ModeIndex_1024x768[i]; + } else if(mode->VDisplay == 576) { + ModeIndex = ModeIndex_1024x576[i]; + } + break; + case 1152: + if(mode->VDisplay == 864) { + ModeIndex = ModeIndex_1152x864[i]; + } else if(pSiS->VGAEngine == SIS_300_VGA) { + if(mode->VDisplay == 768) { + ModeIndex = ModeIndex_1152x768[i]; + } + } + break; + case 1280: + if (mode->VDisplay == 1024) { + ModeIndex = ModeIndex_1280x1024[i]; + } else if (mode->VDisplay == 720) { + ModeIndex = ModeIndex_1280x720[i]; + } else if(pSiS->VGAEngine == SIS_315_VGA) { + if (mode->VDisplay == 768) { + ModeIndex = ModeIndex_1280x768[i]; + } + } + break; + } + + } else { /* CRT1 only, no CRT2 */ + + ModeIndex = SiS_CalcModeIndex(pScrn, mode); + + } + + return(ModeIndex); +} + +USHORT +SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags) +{ + SISPtr pSiS = SISPTR(pScrn); + int out_n, out_dn, out_div, out_sbit, out_scale; + int depth = pSiS->CurrentLayout.bitsPerPixel; + +#ifdef SISDUALHEAD + if( ((!pSiS->DualHeadMode) && (VBFlags & DISPTYPE_DISP2)) || + ((pSiS->DualHeadMode) && (!pSiS->SecondHead)) ) return 0; +#else + if(VBFlags & DISPTYPE_DISP2) return 0; +#endif + + 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->CHBlankStart = pSiS->SiS_Pr->CHDisplay; + pSiS->SiS_Pr->CHBlankEnd = pSiS->SiS_Pr->CHTotal; + + 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->CVBlankStart = pSiS->SiS_Pr->CVSyncStart - 1; + pSiS->SiS_Pr->CVBlankEnd = pSiS->SiS_Pr->CVTotal; + + pSiS->SiS_Pr->CFlags = mode->Flags; + + SiS_compute_vclk(pSiS->SiS_Pr->CDClock, &out_n, &out_dn, &out_div, &out_sbit, &out_scale); + +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sb %d sc %d\n", + pSiS->SiS_Pr->CDClock, out_n, out_dn, out_div, out_sbit, out_scale); +#endif + + pSiS->SiS_Pr->CSR2B = (out_div == 2) ? 0x80 : 0x00; + pSiS->SiS_Pr->CSR2B |= ((out_n - 1) & 0x7f); + pSiS->SiS_Pr->CSR2C = (out_dn - 1) & 0x1f; + pSiS->SiS_Pr->CSR2C |= (((out_scale - 1) & 3) << 5); + pSiS->SiS_Pr->CSR2C |= ((out_sbit & 0x01) << 7); + pSiS->SiS_Pr->CSRClock = (pSiS->SiS_Pr->CDClock / 1000) + 1; + + pSiS->SiS_Pr->CCRT1CRTC[0] = ((pSiS->SiS_Pr->CHTotal >> 3) - 5) & 0xff; + pSiS->SiS_Pr->CCRT1CRTC[1] = (pSiS->SiS_Pr->CHDisplay >> 3) - 1; + pSiS->SiS_Pr->CCRT1CRTC[2] = (pSiS->SiS_Pr->CHBlankStart >> 3) - 1; + pSiS->SiS_Pr->CCRT1CRTC[3] = (((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80; + pSiS->SiS_Pr->CCRT1CRTC[4] = (pSiS->SiS_Pr->CHSyncStart >> 3) + 3; + pSiS->SiS_Pr->CCRT1CRTC[5] = ((((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) | + (((pSiS->SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F); + + pSiS->SiS_Pr->CCRT1CRTC[6] = (pSiS->SiS_Pr->CVTotal - 2) & 0xFF; + pSiS->SiS_Pr->CCRT1CRTC[7] = (((pSiS->SiS_Pr->CVTotal - 2) & 0x100) >> 8) + | (((pSiS->SiS_Pr->CVDisplay - 1) & 0x100) >> 7) + | ((pSiS->SiS_Pr->CVSyncStart & 0x100) >> 6) + | (((pSiS->SiS_Pr->CVBlankStart - 1) & 0x100) >> 5) + | 0x10 + | (((pSiS->SiS_Pr->CVTotal - 2) & 0x200) >> 4) + | (((pSiS->SiS_Pr->CVDisplay - 1) & 0x200) >> 3) + | ((pSiS->SiS_Pr->CVSyncStart & 0x200) >> 2); + + pSiS->SiS_Pr->CCRT1CRTC[16] = ((((pSiS->SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); /* cr9 */ + +#if 0 + if (mode->VScan >= 32) + regp->CRTC[9] |= 0x1F; + else if (mode->VScan > 1) + regp->CRTC[9] |= mode->VScan - 1; +#endif + + pSiS->SiS_Pr->CCRT1CRTC[8] = (pSiS->SiS_Pr->CVSyncStart - 1) & 0xFF; /* cr10 */ + pSiS->SiS_Pr->CCRT1CRTC[9] = ((pSiS->SiS_Pr->CVSyncEnd - 1) & 0x0F) | 0x80; /* cr11 */ + pSiS->SiS_Pr->CCRT1CRTC[10] = (pSiS->SiS_Pr->CVDisplay - 1) & 0xFF; /* cr12 */ + pSiS->SiS_Pr->CCRT1CRTC[11] = (pSiS->SiS_Pr->CVBlankStart - 1) & 0xFF; /* cr15 */ + pSiS->SiS_Pr->CCRT1CRTC[12] = (pSiS->SiS_Pr->CVBlankEnd - 1) & 0xFF; /* cr16 */ + + pSiS->SiS_Pr->CCRT1CRTC[13] = + GETBITSTR((pSiS->SiS_Pr->CVTotal -2), 10:10, 0:0) | + GETBITSTR((pSiS->SiS_Pr->CVDisplay -1), 10:10, 1:1) | + GETBITSTR((pSiS->SiS_Pr->CVBlankStart-1), 10:10, 2:2) | + GETBITSTR((pSiS->SiS_Pr->CVSyncStart ), 10:10, 3:3) | + GETBITSTR((pSiS->SiS_Pr->CVBlankEnd -1), 8:8, 4:4) | + GETBITSTR((pSiS->SiS_Pr->CVSyncEnd -1), 4:4, 5:5) ; + + pSiS->SiS_Pr->CCRT1CRTC[14] = + GETBITSTR((pSiS->SiS_Pr->CHTotal >> 3) - 5, 9:8, 1:0) | + GETBITSTR((pSiS->SiS_Pr->CHDisplay >> 3) - 1, 9:8, 3:2) | + GETBITSTR((pSiS->SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) | + GETBITSTR((pSiS->SiS_Pr->CHSyncStart >> 3) + 3, 9:8, 7:6) ; + + + pSiS->SiS_Pr->CCRT1CRTC[15] = + GETBITSTR((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) | + GETBITSTR((pSiS->SiS_Pr->CHSyncEnd >> 3) + 3, 5:5, 2:2) ; + + 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; +} + +/* TW: Build a list of supported modes */ +DisplayModePtr +SiSBuildBuiltInModeList(ScrnInfoPtr pScrn) +{ + 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, index, vclkindex; + DisplayModePtr new = NULL, current = NULL, first = NULL, backup = NULL; + + pSiS->backupmodelist = NULL; + + /* 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; +#if 0 /* Not any longer */ + if(pSiS->VGAEngine == SIS_300_VGA) index &= 0x3F; +#endif + + if(((pSiS->SiS_Pr->SiS_RefIndex[i].XRes < 512) && (!pSiS->DSTN)) || + ((pSiS->DSTN) && + (pSiS->SiS_Pr->SiS_RefIndex[i].XRes < 512) && + (pSiS->SiS_Pr->SiS_RefIndex[i].XRes != 320) && + (pSiS->SiS_Pr->SiS_RefIndex[i].YRes != 480))) { + 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; + + 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; + + 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); + + D = B - F - C; + + 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; + } + + if((backup = xalloc(sizeof(DisplayModeRec)))) { + if(!pSiS->backupmodelist) pSiS->backupmodelist = backup; + else { + pSiS->backupmodelist->next = backup; + backup->prev = pSiS->backupmodelist; + } + backup->next = NULL; + backup->HDisplay = current->HDisplay; + backup->HSyncStart = current->HSyncStart; + backup->HSyncEnd = current->HSyncEnd; + backup->HTotal = current->HTotal; + backup->VDisplay = current->VDisplay; + backup->VSyncStart = current->VSyncStart; + backup->VSyncEnd = current->VSyncEnd; + backup->VTotal = current->VTotal; + backup->Flags = current->Flags; + backup->Clock = current->Clock; + } + +#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); +#endif + + i++; + } + + return first; + +} + +#define MODEID_OFF 0x449 + +unsigned char +SiS_GetSetModeID(ScrnInfoPtr pScrn, unsigned char id) +{ + return(SiS_GetSetBIOSScratch(pScrn, MODEID_OFF, id)); +} + +unsigned char +SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, USHORT offset, unsigned char value) +{ + unsigned char ret; + unsigned char *base; + + base = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO, 0, 0x2000); + if(!base) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "(init.c: Could not map BIOS scratch area)\n"); + return 0; + } + + ret = *(base + offset); + + /* value != 0xff means: set register */ + if (value != 0xff) + *(base + offset) = value; + + xf86UnMapVidMem(pScrn->scrnIndex, base, 0x2000); + + return ret; +} + +#endif + + + diff --git a/src/init.h b/src/init.h new file mode 100644 index 0000000..8663509 --- /dev/null +++ b/src/init.h @@ -0,0 +1,316 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/init.h,v 1.5 2003/02/10 01:14:16 tsi Exp $ */ + +#ifndef _INIT_ +#define _INIT_ + +#include "osdef.h" +#include "initdef.h" +#include "vgatypes.h" +#include "vstruct.h" + +#ifdef TC +#include <stdio.h> +#include <string.h> +#include <conio.h> +#include <dos.h> +#include <stdlib.h> +#endif + +#ifdef LINUX_XF86 +#include "xf86.h" +#include "xf86Pci.h" +#include "xf86PciInfo.h" +#include "xf86_OSproc.h" +#include "sis.h" +#include "sis_regs.h" +#endif + +#ifdef LINUX_KERNEL +#include <linux/types.h> +#include <asm/io.h> +#include <linux/sisfb.h> +#endif + +#ifdef WIN2000 +#include <stdio.h> +#include <string.h> +#include <miniport.h> +#include "dderror.h" +#include "devioctl.h" +#include "miniport.h" +#include "ntddvdeo.h" +#include "video.h" +#include "sisv.h" +#include "tools.h" +#endif + +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} +}; + +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} +}; + +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} +}; + +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 +}; + +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 +}; + +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 +}; + +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 +}; + +void SiS_SetReg1(USHORT, USHORT, USHORT); +void SiS_SetReg2(SiS_Private *, USHORT, USHORT, USHORT); +void SiS_SetReg3(USHORT, USHORT); +void SiS_SetReg4(USHORT, ULONG); +void SiS_SetReg5(USHORT, USHORT); +UCHAR SiS_GetReg1(USHORT, USHORT); +UCHAR SiS_GetReg2(USHORT); +ULONG SiS_GetReg3(USHORT); +USHORT SiS_GetReg4(USHORT); +void SiS_ClearDAC(SiS_Private *SiS_Pr, ULONG); +void SiS_SetMemoryClock(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetDRAMModeRegister(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension); +BOOLEAN SiS_SearchVBModeID(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT *ModeNo); +void SiS_IsLowResolution(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex); + +#ifdef SIS300 +void SiS_SetDRAMSize_300(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +USHORT SiS_ChkBUSWidth_300(SiS_Private *SiS_Pr, ULONG FBAddress); +#endif + +#ifdef SIS315H +UCHAR SiS_Get310DRAMType(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_DDR_MRS(SiS_Private *SiS_Pr); +void SiS_SDR_MRS(SiS_Private *SiS_Pr); +void SiS_DisableRefresh(SiS_Private *SiS_Pr); +void SiS_EnableRefresh(SiS_Private *SiS_Pr, UCHAR *ROMAddr); +void SiS_SetDRAMSize_310(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO); +void SiS_DisableChannelInterleaving(SiS_Private *SiS_Pr, int index,USHORT SiS_DDRDRAM_TYPE[][5]); +void SiS_SetDRAMSizingType(SiS_Private *SiS_Pr, int index,USHORT DRAMTYPE_TABLE[][5]); +void SiS_CheckBusWidth_310(SiS_Private *SiS_Pr, UCHAR *ROMAddress,ULONG FBAddress, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +int SiS_SetRank(SiS_Private *SiS_Pr, int index,UCHAR RankNo,USHORT DRAMTYPE_TABLE[][5]); +int SiS_SetDDRChannel(SiS_Private *SiS_Pr, int index,UCHAR ChannelNo, + USHORT DRAMTYPE_TABLE[][5]); +int SiS_CheckColumn(SiS_Private *SiS_Pr, int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress); +int SiS_CheckBanks(SiS_Private *SiS_Pr, int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress); +int SiS_CheckRank(SiS_Private *SiS_Pr, int RankNo,int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress); +int SiS_CheckDDRRank(SiS_Private *SiS_Pr, int RankNo,int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress); +int SiS_CheckRanks(SiS_Private *SiS_Pr, int RankNo,int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress); +int SiS_CheckDDRRanks(SiS_Private *SiS_Pr, int RankNo,int index,USHORT DRAMTYPE_TABLE[][5],ULONG FBAddress); +int SiS_SDRSizing(SiS_Private *SiS_Pr, ULONG FBAddress); +int SiS_DDRSizing(SiS_Private *SiS_Pr, ULONG FBAddress); +int Is315E(SiS_Private *SiS_Pr); +void SiS_VerifyMclk(SiS_Private *SiS_Pr, ULONG FBAddr); +#endif + +void SiS_HandleCRT1(SiS_Private *SiS_Pr); +void SiS_Handle301B_1400x1050(SiS_Private *SiS_Pr, USHORT ModeNo); +void SiS_SetEnableDstn(SiS_Private *SiS_Pr); +void SiS_Delay15us(SiS_Private *SiS_Pr); +BOOLEAN SiS_SearchModeID(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT *ModeNo,USHORT *ModeIdIndex); +BOOLEAN SiS_CheckMemorySize(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT ModeNo,USHORT ModeIdIndex); +UCHAR SiS_GetModePtr(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT ModeNo,USHORT ModeIdIndex); +void SiS_SetSeqRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex); +void SiS_SetMiscRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex); +void SiS_SetCRTCRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT StandTableIndex); +void SiS_SetATTRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetGRCRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex); +void SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetSync(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT RefreshRateTableIndex); +void SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +BOOLEAN SiS_GetLCDACRT1Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *ResInfo,USHORT *DisplayType); +void SiS_ResetCRT1VCLK(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetCRT1VCLK(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,PSIS_HW_DEVICE_INFO, + USHORT RefreshRateTableIndex); +void SiS_SetVCLKState(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO, USHORT ModeNo, + USHORT RefreshRateTableIndex, USHORT ModeIdIndex); +void SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex); +void SiS_WriteDAC(SiS_Private *SiS_Pr, USHORT, USHORT, USHORT, USHORT, USHORT, USHORT); +void SiS_DisplayOn(SiS_Private *SiS_Pr); +void SiS_DisplayOff(SiS_Private *SiS_Pr); +void SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO,USHORT ModeNo, + USHORT ModeIdIndex,USHORT RefreshRateTableIndex); +void SiS_GetVBType(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO); +USHORT SiS_ChkBUSWidth(SiS_Private *SiS_Pr, UCHAR *ROMAddr); +USHORT SiS_GetModeIDLength(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT); +USHORT SiS_GetRefindexLength(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT); +void SiS_SetInterlace(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT RefreshRateTableIndex); +void SiS_Set_LVDS_TRUMPION(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetCRT1Offset(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT,USHORT,USHORT,PSIS_HW_DEVICE_INFO); +#ifdef SIS315H +void SiS_SetCRT1FIFO_310(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT,USHORT,PSIS_HW_DEVICE_INFO); +#endif +#ifdef SIS300 +void SiS_SetCRT1FIFO_300(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,PSIS_HW_DEVICE_INFO, + USHORT RefreshRateTableIndex); +void SiS_SetCRT1FIFO_630(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,PSIS_HW_DEVICE_INFO, + USHORT RefreshRateTableIndex); +USHORT SiS_CalcDelay(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT VCLK, + USHORT colordepth, USHORT MCLK); +USHORT SiS_DoCalcDelay(SiS_Private *SiS_Pr, USHORT MCLK, USHORT VCLK, USHORT colordepth, USHORT key); +USHORT SiS_CalcDelay2(SiS_Private *SiS_Pr, UCHAR *ROMAddr, UCHAR,PSIS_HW_DEVICE_INFO HwDeviceExtension); +#endif +void SiS_ClearBuffer(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO,USHORT ModeNo); +void SiS_SetCRT1Group(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT ModeNo,USHORT ModeIdIndex,USHORT BaseAddr); +void SiS_DetectMonitor(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr); +void SiS_GetSenseStatus(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,UCHAR *ROMAddr); +USHORT SiS_TestMonitorType(SiS_Private *SiS_Pr, UCHAR R_DAC,UCHAR G_DAC,UCHAR B_DAC); +USHORT SiS_SenseCHTV(SiS_Private *SiS_Pr); +BOOLEAN SiS_Sense(SiS_Private *SiS_Pr, USHORT tempbx,USHORT tempcx); +BOOLEAN SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO); +BOOLEAN SiS_GetLCDDDCInfo(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO); +USHORT SiS_SenseLCD(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO); +void SiSRegInit(SiS_Private *SiS_Pr, USHORT BaseAddr); +void SiSInitPtr(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo); +void SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, UCHAR *ROMAddr); + +#ifdef LINUX_XF86 +USHORT SiS_CalcModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode); +USHORT SiS_CheckCalcModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags); +USHORT SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags); +void SiS_SetPitch(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, UShort BaseAddr); +void SiS_SetPitchCRT1(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, UShort BaseAddr); +void SiS_SetPitchCRT2(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, UShort BaseAddr); +unsigned char SiS_GetSetModeID(ScrnInfoPtr pScrn, unsigned char id); +unsigned char SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, USHORT offset, unsigned char value); +extern int SiS_compute_vclk(int Clock, int *out_n, int *out_dn, int *out_div, + int *out_sbit, int *out_scale); +#endif + +extern USHORT SiS_GetOffset(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +extern USHORT SiS_GetColorDepth(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex); +extern void SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +extern BOOLEAN SiS_SetCRT2Group301(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +extern void SiS_PresetScratchregister(SiS_Private *SiS_Pr, USHORT SiS_P3d4, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +extern void SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr); +extern void SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr); +extern BOOLEAN SiS_BridgeIsOn(SiS_Private *SiS_Pr, USHORT BaseAddr); +extern BOOLEAN SiS_BridgeIsEnable(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO ); +extern void SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + USHORT ModeIdIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension, int chkcrt2mode); +extern BOOLEAN SiS_GetLCDResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo, + USHORT ModeIdIndex, PSIS_HW_DEVICE_INFO HwDeviceExtension); +extern void SiS_SetHiVision(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension); +extern USHORT SiS_GetRatePtrCRT2(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +extern void SiS_WhatIsThis(SiS_Private *SiS_Pr, USHORT myvbinfo); +extern void SiS_LongWait(SiS_Private *SiS_Pr); +extern void SiS_SetRegOR(USHORT Port,USHORT Index,USHORT DataOR); +extern void SiS_SetRegAND(USHORT Port,USHORT Index,USHORT DataAND); +extern void SiS_SetRegANDOR(USHORT Port,USHORT Index,USHORT DataAND,USHORT DataOR); +extern USHORT SiS_GetResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex); +extern void SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempax); +extern USHORT SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempax); +extern void SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempax); +extern USHORT SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempax); +extern void SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempax); +extern USHORT SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempax); +extern BOOLEAN SiS_GetLVDSCRT1Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + USHORT *ResInfo,USHORT *DisplayType); +extern USHORT SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +extern BOOLEAN SiS_Is301B(SiS_Private *SiS_Pr, USHORT BaseAddr); +extern BOOLEAN SiS_IsM650(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +extern BOOLEAN SiS_LowModeStuff(SiS_Private *SiS_Pr, USHORT ModeNo,PSIS_HW_DEVICE_INFO HwDeviceExtension); +extern BOOLEAN SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +extern BOOLEAN SiS_IsDualEdge(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +extern USHORT SiS_GetMCLK(SiS_Private *SiS_Pr, UCHAR *ROMAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension); + +#endif + diff --git a/src/init301.c b/src/init301.c new file mode 100644 index 0000000..0c2b635 --- /dev/null +++ b/src/init301.c @@ -0,0 +1,10798 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/init301.c,v 1.10 2003/02/04 02:44:28 dawes Exp $ */ +/* + * Mode switching code (CRT2 section) for SiS 300/540/630/730/315/550/650/740/330 + * (Universal module for Linux kernel framebuffer, XFree86 4.x) + * + * Assembler-To-C translation + * Copyright 2002, 2003 by Thomas Winischhofer <thomas@winischhofer.net> + * Minor parts Copyright SiS, Inc. + * + * Based on BIOS + * 1.10.07, 1.10a for SiS650/LVDS+CH7019 + * 1.11.05 for 650/LVDS (w/o Chrontel) + * 1.07.1b, 1.10.6s, 1.11.6w, 1.11.7w, 1.11.8r for SiS650/301(B/LV), 650/301LVx + * 2.04.50 (I) and 2.04.5c (II) for SiS630/301(B) + * 2.02.3b, 2.03.02, 2.04.2c, 2.04.5c, 2.07a and 2.08.b3 for 630/LVDS/LVDS+CH7005 + * 2.04.5c, 2.04.6c for 730+LVDS+CH7005 + * 1.09b for 315/301(B) + * 1.16.51 for 300+301LVX (ECS A907) + * 1.01.03 for 330 (Xabre 400) + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holder not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The copyright holder makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * 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 "init301.h" + +#if 0 +#define TWNEWPANEL +#endif + +#if 1 /* TW: Emulate 650/301LVx BIOS 1.10.6s (should be set) */ +#define SIS650301NEW +#endif + +#ifdef SIS300 +#include "oem300.h" +#endif + +#ifdef SIS315H +#include "oem310.h" +#endif + +#define SiS_I2CDELAY 1000 +#define SiS_I2CDELAYSHORT 333 + +BOOLEAN +SiS_SetCRT2Group301(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT ModeIdIndex; + USHORT RefreshRateTableIndex; + + SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; + + if(!SiS_Pr->UseCustomMode) { + SiS_SearchModeID(SiS_Pr,ROMAddr,&ModeNo,&ModeIdIndex); + } else { + ModeIdIndex = 0; + } + + /* TW: Used for shifting CR33 */ + SiS_Pr->SiS_SelectCRT2Rate = 4; + + SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr); + + RefreshRateTableIndex = SiS_GetRatePtrCRT2(SiS_Pr, ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); + + SiS_SaveCRT2Info(SiS_Pr,ModeNo); + + if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) { + SiS_DisableBridge(SiS_Pr,HwDeviceExtension,BaseAddr); + if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (HwDeviceExtension->jChipType == SIS_730)) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x00,0x80); + } + SiS_SetCRT2ModeRegs(SiS_Pr,BaseAddr,ModeNo,ModeIdIndex,HwDeviceExtension); + } + + if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) { + SiS_LockCRT2(SiS_Pr,HwDeviceExtension, BaseAddr); + SiS_DisplayOn(SiS_Pr); + return(TRUE); + } + + if(SiS_Pr->UseCustomMode) return(FALSE); + + SiS_GetCRT2Data(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + HwDeviceExtension); + + /* LVDS, 650/301LV(LCDA) and 630/301B BIOS set up Panel Link */ + /* 300+LV does not */ + if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || + ((HwDeviceExtension->jChipType != SIS_300) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV))) { + SiS_GetLVDSDesData(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + HwDeviceExtension); + } else { + SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0; + } + +#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_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) { + SiS_SetGroup1(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, + HwDeviceExtension,RefreshRateTableIndex); + } + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + + if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) { + + SiS_SetGroup2(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + SiS_SetGroup3(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, + HwDeviceExtension); + SiS_SetGroup4(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + SiS_SetGroup5(SiS_Pr,HwDeviceExtension, BaseAddr,ROMAddr, + ModeNo,ModeIdIndex); + + /* TW: 630/301B BIOS does all this: */ + if((HwDeviceExtension->jChipType < SIS_315H) && + (HwDeviceExtension->jChipType != SIS_300)) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) { + if(!((SiS_Pr->SiS_SetFlag & CRT2IsVGA) && ((ModeNo == 0x03) || (ModeNo = 0x10)))) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + SiS_ModCRT1CRTC(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + } + } + } + SiS_SetCRT2ECLK(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + } + } + + } + + } else { + + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) { + if (SiS_Pr->SiS_IF_DEF_TRUMPION == 0) { + SiS_ModCRT1CRTC(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + } + } + if(SiS_Pr->SiS_IF_DEF_FSTN == 0) { + SiS_SetCRT2ECLK(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + } + if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + /* TW: Inserted from 650/LVDS BIOS */ + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + SiS_SetCH701xForLCD(SiS_Pr,HwDeviceExtension,BaseAddr); + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + /* TW: Set Chrontel registers only if CRT2 is TV */ + SiS_SetCHTVReg(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex); + } + } + } + + } + +#ifdef SIS300 + if ( (HwDeviceExtension->jChipType == SIS_540) || + (HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730) || + (HwDeviceExtension->jChipType == SIS_300) ) + { + if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) { + if(SiS_Pr->SiS_UseOEM) { + if((SiS_Pr->SiS_UseROM) && ROMAddr && (SiS_Pr->SiS_UseOEM == -1)) { + if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) { + SiS_OEM300Setting(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo); + } + } else { + SiS_OEM300Setting(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo); + } + } + } + } +#endif + +#ifdef SIS315H + if ( (HwDeviceExtension->jChipType == SIS_315H) || + (HwDeviceExtension->jChipType == SIS_315) || + (HwDeviceExtension->jChipType == SIS_315PRO)|| + (HwDeviceExtension->jChipType == SIS_550) || + (HwDeviceExtension->jChipType == SIS_740) || + (HwDeviceExtension->jChipType == SIS_650) || + (HwDeviceExtension->jChipType == SIS_330) ) + { + if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) { +#ifdef SIS650301NEW + SiS_FinalizeLCD(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, HwDeviceExtension); +#else + SiS_OEMLCD(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex); +#endif + if(SiS_Pr->SiS_UseOEM) { + SiS_OEM310Setting(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex); + } + SiS_CRT2AutoThreshold(SiS_Pr,BaseAddr); + } + } +#endif + + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(HwDeviceExtension->jChipType != SIS_730) { + SiS_DisplayOn(SiS_Pr); + } + } + } + + if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(HwDeviceExtension->jChipType == SIS_730) { + SiS_DisplayOn(SiS_Pr); + } + } + SiS_EnableBridge(SiS_Pr,HwDeviceExtension,BaseAddr); + } + + SiS_DisplayOn(SiS_Pr); + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + /* TW: Disable LCD panel when using TV */ + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x11,0x0C); + } else { + /* TW: Disable TV when using LCD */ + SiS_SetCH70xxANDOR(SiS_Pr,0x010E,0xF8); + } + } + + if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) { + SiS_LockCRT2(SiS_Pr,HwDeviceExtension, BaseAddr); + } + + return 1; +} + +/* TW: Checked with 330, 650/LVDS (1.10.07) and 630+301B/LVDS BIOS */ +BOOLEAN +SiS_LowModeStuff(SiS_Private *SiS_Pr, USHORT ModeNo, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT temp,temp1,temp2; + + if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12)) + return(1); + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x11); + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80); + temp1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x00); + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x00,0x55); + temp2 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x00); + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x00,temp1); + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x11,temp); + if((HwDeviceExtension->jChipType >= SIS_315H) || + (HwDeviceExtension->jChipType == SIS_300)) { + if(temp2 == 0x55) return(0); + else return(1); + } else { + if(temp2 != 0x55) return(1); + else { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01); + return(0); + } + } +} + +/* TW: Set Part1 registers */ +/* TW: Checked with 650/LVDS (1.10.07), 650/301LV (II) and 630/301B (II) BIOS */ +/* TW: Pass 2: Checked with 650/301LVx 1.10.6s, 630/301B 2.04.5a */ +void +SiS_SetGroup1(SiS_Private *SiS_Pr,USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + USHORT ModeIdIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT RefreshRateTableIndex) +{ + USHORT temp=0, tempax=0, tempbx=0, tempcx=0; + USHORT pushbx=0, CRT1Index=0; +#ifdef SIS315H + USHORT pushcx=0, tempbl=0; +#endif + USHORT modeflag, resinfo=0; + + if(ModeNo<=0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + } 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; + } + + /* TW: LCDA exists with LVDS as well */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + + SiS_SetCRT2Sync(SiS_Pr,BaseAddr,ROMAddr,ModeNo, + RefreshRateTableIndex,HwDeviceExtension); + + SiS_SetGroup1_LCDA(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, + HwDeviceExtension,RefreshRateTableIndex); + + } else { + + if( (HwDeviceExtension->jChipType >= SIS_315H) && + (SiS_Pr->SiS_IF_DEF_LVDS == 1) && + (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + + SiS_SetCRT2Sync(SiS_Pr,BaseAddr,ROMAddr,ModeNo, + RefreshRateTableIndex,HwDeviceExtension); + + } else { + + SiS_SetCRT2Offset(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + + if (HwDeviceExtension->jChipType < SIS_315H ) { +#ifdef SIS300 + SiS_SetCRT2FIFO_300(SiS_Pr,ROMAddr,ModeNo,HwDeviceExtension); +#endif + } else { +#ifdef SIS315H + SiS_SetCRT2FIFO_310(SiS_Pr,ROMAddr,ModeNo,HwDeviceExtension); +#endif + } + + SiS_SetCRT2Sync(SiS_Pr,BaseAddr,ROMAddr,ModeNo, + RefreshRateTableIndex,HwDeviceExtension); + + /* 1. Horizontal setup */ + + if (HwDeviceExtension->jChipType < SIS_315H ) { + +#ifdef SIS300 /* ------------- 300 series --------------*/ + + temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */ + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,temp); /* TW: CRT2 Horizontal Total */ + + temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp); /* TW: CRT2 Horizontal Total Overflow [7:4] */ + + temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */ + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0A,temp); /* TW: CRT2 Horizontal Display Enable End */ + + pushbx = SiS_Pr->SiS_VGAHDE + 12; /* bx BTVGA@HRS 0x0B,0x0C */ + tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2; + tempbx = pushbx + tempcx; + tempcx <<= 1; + tempcx += tempbx; + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC){ + /* CRT1Index &= 0x3F; - Not any longer */ + tempbx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4]; + tempbx |= ((SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14] & 0xC0) << 2); + tempbx = (tempbx - 1) << 3; + tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5]; + tempcx &= 0x1F; + temp = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15]; + temp = (temp & 0x04) << (6-2); + tempcx = ((tempcx | temp) - 1) << 3; + } + + if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (resinfo == 0x08)){ + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)){ + tempbx = 1040; + tempcx = 1042; + } + } + } + + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0B,temp); /* TW: CRT2 Horizontal Retrace Start */ +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* ----------------- 310/325 series ------------- */ + + tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HT 0x08,0x09 */ + pushcx = tempcx; + if(modeflag & HalfDCLK) { + if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->SiS_IF_DEF_CH70xx == 0)) { + tempax = SiS_Pr->SiS_VGAHDE >> 1; + tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) { + tempcx = SiS_Pr->SiS_HT - tempax; + } + } else { + tempcx >>= 1; + } + } + tempcx--; + + temp = tempcx & 0xff; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,temp); /* TW: CRT2 Horizontal Total */ + + temp = ((tempcx & 0xff00) >> 8) << 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp); /* TW: CRT2 Horizontal Total Overflow [7:4] */ + + tempcx = pushcx; /* BTVGA2HDEE 0x0A,0x0C */ + tempbx = SiS_Pr->SiS_VGAHDE; + tempcx -= tempbx; + tempcx >>= 2; + if(modeflag & HalfDCLK) { + tempbx >>= 1; + tempcx >>= 1; + } + tempbx += 16; + + temp = tempbx & 0xff; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0A,temp); /* TW: CRT2 Horizontal Display Enable End */ + + pushbx = tempbx; + tempcx >>= 1; + tempbx += tempcx; + tempcx += tempbx; + + if(SiS_Pr->SiS_IF_DEF_LVDS==0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { + tempbx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4]; + tempbx |= ((SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14] & 0xC0) << 2); + tempbx = (tempbx - 3) << 3; /*(VGAHRS-3)*8 */ + tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5]; + tempcx &= 0x1F; + temp = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15]; + temp = (temp & 0x04) << (5-2); /* VGAHRE D[5] */ + tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */ + tempcx &= 0x00FF; + tempcx |= (tempbx & 0xFF00); + tempbx += 16; + tempcx += 16; + tempax = SiS_Pr->SiS_VGAHT; + if (modeflag & HalfDCLK) tempax >>= 1; + tempax--; + if (tempcx > tempax) tempcx = tempax; + } + if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (resinfo == 0x08)){ + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)){ + tempbx = 1040; + tempcx = 1042; + } + } + /* TW: Makes no sense, but is in 650/301LVx 1.10.6s */ + if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (resinfo == 0x08)){ + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV)) { + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + tempbx = 1040; + tempcx = 1042; + } + } + } + } + + temp = tempbx & 0xff; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0B,temp); /* TW: CRT2 Horizontal Retrace Start */ +#endif /* SIS315H */ + + } /* 310 series */ + + /* TW: The following is done for all bridge/chip types/series */ + + tempax = tempbx & 0xFF00; + tempbx = pushbx; + tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4); + tempax |= (tempbx & 0xFF00); + temp = (tempax & 0xFF00) >> 8; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0C,temp); /* TW: Overflow */ + + temp = tempcx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0D,temp); /* TW: CRT2 Horizontal Retrace End */ + + /* 2. Vertical setup */ + + tempcx = SiS_Pr->SiS_VGAVT - 1; + temp = tempcx & 0x00FF; + + /* TW: Matches 650/301LV, 650/LVDS, 630/LVDS(CLEVO), 630/LVDS(no-Ch7005) */ + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO|SetCRT2ToAVIDEO)) { + temp--; + } + } + } else { + temp--; + } + } else if(HwDeviceExtension->jChipType >= SIS_315H) { + /* TW: Inserted from 650/301LVx 1.10.6s */ + temp--; + } + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0E,temp); /* TW: CRT2 Vertical Total */ + + tempbx = SiS_Pr->SiS_VGAVDE - 1; + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0F,temp); /* TW: CRT2 Vertical Display Enable End */ + + temp = ((tempbx & 0xFF00) << 3) >> 8; + temp |= ((tempcx & 0xFF00) >> 8); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x12,temp); /* TW: Overflow (and HWCursor Test Mode) */ + + /* TW: For 650/LVDS (1.10.07), 650/301LVx (1.10.6s) */ + if(HwDeviceExtension->jChipType >= SIS_315H) { + tempbx++; + tempax = tempbx; + tempcx++; + tempcx -= tempax; + tempcx >>= 2; + tempbx += tempcx; + if(tempcx < 4) tempcx = 4; + tempcx >>= 2; + tempcx += tempbx; + tempcx++; + } else { + /* TW: For 300/630/LVDS/301B: */ + 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_IF_DEF_LVDS == 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC){ + tempbx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8]; + temp = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7]; + if(temp & 0x04) tempbx |= 0x0100; + if(temp & 0x80) tempbx |= 0x0200; + temp = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13]; + if(temp & 0x08) tempbx |= 0x0400; + temp = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9]; + tempcx = (tempcx & 0xFF00) | (temp & 0x00FF); + } + } + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x10,temp); /* TW: CRT2 Vertical Retrace Start */ + + temp = ((tempbx & 0xFF00) >> 8) << 4; + temp |= (tempcx & 0x000F); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x11,temp); /* TW: CRT2 Vert. Retrace End; Overflow; "Enable CRTC Check" */ + + /* 3. Panel compensation delay */ + + if(HwDeviceExtension->jChipType < SIS_315H) { + +#ifdef SIS300 /* ---------- 300 series -------------- */ + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + temp = 0x20; + + if(HwDeviceExtension->jChipType == SIS_300) { + temp = 0x10; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) temp = 0x2c; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) temp = 0x24; + } + if(SiS_Pr->SiS_VBType & VB_SIS301) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20; + } +#if 0 /* TW: Not in 630/301B BIOS */ + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) temp = 0x24; +#endif + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x08; +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) temp = 0x2c; + else temp = 0x20; + } +#endif + if((ROMAddr) && (SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) { + if(ROMAddr[0x220] & 0x80) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV-SetCRT2ToHiVisionTV)) + temp = ROMAddr[0x221]; + else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) + temp = ROMAddr[0x222]; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) + temp = ROMAddr[0x223]; + else + temp = ROMAddr[0x224]; + temp &= 0x3c; + } + } + if(HwDeviceExtension->pdc) { + temp = HwDeviceExtension->pdc & 0x3c; + } + } else { + temp = 0x20; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) temp = 0x04; + } + if((ROMAddr) && SiS_Pr->SiS_UseROM) { + if(ROMAddr[0x220] & 0x80) { + temp = ROMAddr[0x220] & 0x3c; + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(HwDeviceExtension->pdc) { + temp = HwDeviceExtension->pdc & 0x3c; + } + } + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x03C,temp); /* TW: Panel Link Delay Compensation; (Software Command Reset; Power Saving) */ + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* ----------- 310/325 series ---------------*/ + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + temp = 0x10; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) temp = 0x2c; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) temp = 0x24; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x08; + tempbl = 0xF0; + } else { + temp = 0x00; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a; + tempbl = 0xF0; + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F; + } + } +#if 0 /* TW: Not done in 650/301LVx 1.10.6s */ + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + temp >>= 2; + } +#endif + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp); /* TW: Panel Link Delay Compensation */ + + 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_IF_DEF_LVDS == 0) { + + /* TW: 630/301B BIOS sets up Panel Link, too! (300/301LV and 650/LV do not) */ + if( (HwDeviceExtension->jChipType < SIS_315H) && + (HwDeviceExtension->jChipType != SIS_300) && + (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && + (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ) { + + SiS_SetGroup1_LVDS(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, + HwDeviceExtension,RefreshRateTableIndex); + + } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + + SiS_SetGroup1_301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, + HwDeviceExtension,RefreshRateTableIndex); + } + + } else { + + if(HwDeviceExtension->jChipType < SIS_315H) { + SiS_SetGroup1_LVDS(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, + HwDeviceExtension,RefreshRateTableIndex); + } else { + /* TW: For 650/LVDS */ + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + SiS_SetGroup1_LVDS(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, + HwDeviceExtension,RefreshRateTableIndex); + } + } else { + SiS_SetGroup1_LVDS(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, + HwDeviceExtension,RefreshRateTableIndex); + } + } + + } + } /* LCDA */ +} + +/* TW: Checked against 650/301LV and 630/301B (II) BIOS */ +/* TW: Pass 2: Checked with 650/301LVx (1.10.6s) and 630/301B (2.04.5a) */ +void +SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex) +{ + USHORT push1,push2; + USHORT tempax,tempbx,tempcx,temp; + USHORT resinfo,modeflag; + + if(ModeNo<=0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + } + + /* TW: The following is only done if bridge is in slave mode: */ + + tempax = 0xFFFF; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempax = SiS_GetVGAHT2(SiS_Pr); + + /* TW: 630/301B, 300/301LV do not check this flag, assume it is set */ + /* 650/LV and 650/301LVx BIOS do not check this either; so we set it... */ + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + modeflag |= Charx8Dot; + } + + if(modeflag & Charx8Dot) tempcx = 0x08; + else tempcx = 0x09; + + if(tempax >= SiS_Pr->SiS_VGAHT) tempax = SiS_Pr->SiS_VGAHT; + + if(modeflag & HalfDCLK) tempax >>= 1; + + tempax = (tempax / tempcx) - 5; + tempbx = tempax & 0xFF; + + temp = 0xFF; /* set MAX HT */ + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x03,temp); + + tempax = SiS_Pr->SiS_VGAHDE; /* 0x04 Horizontal Display End */ + if(modeflag & HalfDCLK) tempax >>= 1; + tempax = (tempax / tempcx) - 1; + tempbx |= ((tempax & 0x00FF) << 8); + temp = tempax & 0xFF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x04,temp); + + temp = (tempbx & 0xFF00) >> 8; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) { + temp += 2; + } +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) { + if(resinfo == 7) temp -= 2; + } +#endif + } + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x05,temp); /* 0x05 Horizontal Display Start */ + + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x06,0x03); /* 0x06 Horizontal Blank end */ + +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) { + temp = (tempbx & 0x00FF) - 1; + if(!(modeflag & HalfDCLK)) { + temp -= 6; + if(SiS_Pr->SiS_SetFlag & TVSimuMode) { + temp -= 2; + if(ModeNo > 0x13) temp -= 10; + } + } + } else { +#endif + tempcx = tempbx & 0x00FF; + tempbx = (tempbx & 0xFF00) >> 8; + 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; + /* TW: Inserted from 650/301 BIOS, 630/301B/301 don't do this */ + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VGAHDE == 800) temp += 2; + } + } + } + } else { + if(!(modeflag & HalfDCLK)) { + temp -= 4; + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x960) { + if(SiS_Pr->SiS_VGAHDE >= 800){ + temp -= 7; + if(HwDeviceExtension->jChipType < SIS_315H) { + /* 650/301LV(x) does not do this, 630/301B, 300/301LV do */ + if(SiS_Pr->SiS_ModeType == ModeEGA){ + if(SiS_Pr->SiS_VGAVDE == 1024){ + temp += 15; + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024) temp += 7; + } + } + } + if(SiS_Pr->SiS_VGAHDE >= 1280){ + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x960) { + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) temp += 28; + } + } + } + } + } + } +#ifdef oldHV + } +#endif + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,temp); /* 0x07 Horizontal Retrace Start */ + + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x00); /* 0x08 Horizontal Retrace End */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_Pr->SiS_SetFlag & TVSimuMode) { + if(ModeNo <= 1) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x2a); + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x61); + } else { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x41); + } + } else if(SiS_Pr->SiS_ModeType == ModeText) { + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x54); + } else { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x55); + } + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x00); + } else if(ModeNo <= 0x13) { + if(modeflag & HalfDCLK) { + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x30); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x03); + } else { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x2f); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x02); + } + } else { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x5b); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x03); + } + } else if( ((HwDeviceExtension->jChipType >= SIS_315H) && (ModeNo == 0x50)) || + ((HwDeviceExtension->jChipType < SIS_315H) && (resinfo == 0 || resinfo == 1)) ) { + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x30); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x03); + } else { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x2f); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x03); + } + } + + } + } + + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,0x03); /* 0x18 SR08 */ + + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x19,0xF0); + + tempbx = SiS_Pr->SiS_VGAVT; + push1 = tempbx; + + SiS_SetReg1(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; + if(tempbx == 360) tempbx = 350; + if(tempbx == 375) tempbx = 350; + if(tempbx == 405) tempbx = 400; + if(tempbx == 420) tempbx = 400; + if(tempbx == 525) tempbx = 480; + push2 = tempbx; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) { + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) { + if(tempbx == 350) tempbx += 5; + if(tempbx == 480) tempbx += 5; + } + } + } + tempbx--; + temp = tempbx & 0x00FF; + tempbx--; + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x10,temp); /* 0x10 vertical Blank Start */ + + tempbx = push2; + tempbx--; + temp = tempbx & 0x00FF; +#if 0 + /* TW: Missing code from 630/301B 2.04.5a and 650/301LVx 1.10.6s (calles int 2f) */ + if(xxx()) { + if(temp == 0xdf) temp = 0xda; + } +#endif + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0E,temp); + + if(tempbx & 0x0100) { + tempcx |= 0x0002; + if(SiS_Pr->SiS_VBType & VB_SIS301) tempcx |= 0x000a; + } + + tempax = 0x000B; + if(modeflag & DoubleScanMode) tempax |= 0x8000; + + if(tempbx & 0x0200) { + tempcx |= 0x0040; + if(SiS_Pr->SiS_VBType & VB_SIS301) tempax |= 0x2000; + } + + if(SiS_Pr->SiS_VBType & VB_SIS301) { + if(SiS_Pr->SiS_VBInfo & SetPALTV) { + if(SiS_Pr->SiS_VGAVDE == 480) { + tempax = (tempax & 0x00ff) | 0x2000; + if(modeflag & DoubleScanMode) tempax |= 0x8000; + } + } + } + + temp = (tempax & 0xFF00) >> 8; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0B,temp); + + if(tempbx & 0x0400) tempcx |= 0x0600; + + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x11,0x00); /* 0x11 Vertical Blank End */ + + tempax = push1; + tempax -= tempbx; + tempax >>= 2; + push1 = tempax; + + if(HwDeviceExtension->jChipType >= SIS_315H) { + /* TW: Inserted from 650/301LVx 1.10.6s */ + if(ModeNo > 0x13) { + if(resinfo != 0x09) { + tempax <<= 1; + tempbx += tempax; + } + } else { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1400x1050) { + tempax <<= 1; + tempbx += tempax; + } + } + } else if((resinfo != 0x09) || (SiS_Pr->SiS_VBType & VB_SIS301)) { + tempax <<= 1; + tempbx += tempax; + } +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) { + tempbx -= 10; + } else { +#endif + if(SiS_Pr->SiS_SetFlag & TVSimuMode) { + if(SiS_Pr->SiS_VBInfo & SetPALTV) { + if(!(SiS_Pr->SiS_HiVision & 0x03)) { + tempbx += 40; + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VGAHDE == 800) tempbx += 10; + } + } + } + } +#ifdef oldHV + } +#endif + tempax = push1; + tempax >>= 2; + tempax++; + tempax += tempbx; + push1 = tempax; + if(SiS_Pr->SiS_VBInfo & SetPALTV) { + if(tempbx <= 513) { + if(tempax >= 513) tempbx = 513; + } + } + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0C,temp); /* 0x0C Vertical Retrace Start */ + + if(!(SiS_Pr->SiS_VBType & VB_SIS301)) { + tempbx--; + temp = tempbx & 0x00FF; + SiS_SetReg1(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(SiS_Pr->SiS_VBType & VB_SIS301) tempcx |= 0x0800; + else tempcx |= 0x0C00; + } + + tempbx = push1; + temp = tempbx & 0x00FF; + temp &= 0x0F; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0D,temp); /* 0x0D vertical Retrace End */ + + if(tempbx & 0x0010) tempcx |= 0x2000; + + temp = tempcx & 0x00FF; + if(SiS_Pr->SiS_VBType & VB_SIS301) { + if(SiS_Pr->SiS_VBInfo & SetPALTV) { + if(SiS_Pr->SiS_VGAVDE == 480) temp = 0xa3; + } + } + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0A,temp); /* 0x0A CR07 */ + + temp = (tempcx & 0xFF00) >> 8; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x17,temp); /* 0x17 SR0A */ + + tempax = modeflag; + temp = (tempax & 0xFF00) >> 8; + temp = (temp >> 1) & 0x09; + /* TW: Inserted from 630/301B and 650/301(LV/LVX) BIOS; not in 630/301 BIOS */ + if(!(SiS_Pr->SiS_VBType & VB_SIS301)) { + temp |= 0x01; + } + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x16,temp); /* 0x16 SR01 */ + + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0F,0x00); /* 0x0F CR14 */ + + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x12,0x00); /* 0x12 CR17 */ + + if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) { + if(HwDeviceExtension->jChipType >= SIS_315H) { + /* TW: Inserted from 650/301LVx 1.10.6s */ + if(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x01) { + temp = 0x80; + } + } else temp = 0x80; + } else temp = 0x00; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1A,temp); /* 0x1A SR0E */ + + return; +} + +/* TW: Checked against 650/LVDS 1.10.07, 630/301B (I,II) and 630/LVDS BIOS */ +void +SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + USHORT ModeIdIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT RefreshRateTableIndex) +{ + USHORT modeflag, resinfo; + USHORT push1, push2, tempax, tempbx, tempcx, temp; +#ifdef SIS315H + USHORT pushcx; +#endif + ULONG tempeax=0, tempebx, tempecx, tempvcfact=0; + + if(ModeNo<=0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + } + + /* TW: Set up Panel Link */ + + /* 1. Horizontal setup */ + + tempax = SiS_Pr->SiS_LCDHDES; + + if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) { + tempax -= 8; + } + + tempcx = SiS_Pr->SiS_HT; /* Horiz. Total */ + + tempbx = SiS_Pr->SiS_HDE; /* Horiz. Display End */ + + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) { + if(!SiS_Pr->SiS_IF_DEF_DSTN) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempbx = 800; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx = 1024; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) tempbx = 1024; /* TW: not done in BIOS */ + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) tempbx = 1152; /* TW: not done in BIOS */ + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempbx = 1280; /* TW */ + else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) tempbx = 1400; /* TW */ + } + } + tempcx = (tempcx - tempbx) >> 2; /* HT-HDE / 4 */ + + push1 = tempax; + + tempax += tempbx; + + if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT; + + push2 = tempax; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(!SiS_Pr->SiS_IF_DEF_DSTN){ + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempcx = 0x0028; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x0030; + else if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) || + (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) ) { + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + tempcx = 0x0017; +#ifdef TWNEWPANEL + tempcx = 0x0018; +#endif + } else { + tempcx = 0x0017; /* A901; other 301B BIOS 0x0018; */ + } + } else { + tempcx = 0x0018; + } + } + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) tempcx = 0x0018; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x0040; + else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) tempcx = 0x0030; + } + } + + tempcx += tempax; /* lcdhrs */ + if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT; + + tempax = tempcx >> 3; /* BPLHRS */ + temp = tempax & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x14,temp); /* Part1_14h; TW: Panel Link Horizontal Retrace Start */ + + temp = (tempax & 0x00FF) + 10; + + /* TW: Inserted this entire "if"-section from 650/LVDS BIOS */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(!SiS_Pr->SiS_IF_DEF_DSTN){ + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) { + temp += 6; + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) { + temp++; + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1024x768) { + temp += 7; + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200) { + temp -= 10; + } + } + } + } + } + } + } + + temp &= 0x1F; + temp |= ((tempcx & 0x0007) << 5); + if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x15,temp); /* Part1_15h; TW: Panel Link Horizontal Retrace End/Skew */ + + tempbx = push2; + tempcx = push1; /* lcdhdes */ + + temp = (tempcx & 0x0007); /* BPLHDESKEW */ + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1A,temp); /* Part1_1Ah; TW: Panel Link Vertical Retrace Start (2:0) */ + + tempcx >>= 3; /* BPLHDES */ + temp = (tempcx & 0x00FF); + if(ModeNo == 0x5b) temp--; /* fix fstn mode=5b */ + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x16,temp); /* Part1_16h; TW: Panel Link Horizontal Display Enable Start */ + + if(HwDeviceExtension->jChipType < SIS_315H) { /* TW: Not done in LVDS BIOS 1.10.07 */ + if(tempbx & 0x07) tempbx += 8; /* TW: Done in 630/301B and 630/LVDS BIOSes */ + } + tempbx >>= 3; /* BPLHDEE */ + temp = tempbx & 0x00FF; + if(ModeNo == 0x5b) temp--; /* fix fstn mode=5b */ + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x17,temp); /* Part1_17h; TW: Panel Link Horizontal Display Enable End */ + + /* 2. Vertical setup */ + + if(HwDeviceExtension->jChipType < SIS_315H) { + + /* TW: This entire section from 630/301B and 630/LVDS/LVDS+CH BIOS */ + tempcx = SiS_Pr->SiS_VGAVT; + tempbx = SiS_Pr->SiS_VGAVDE; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) { + tempbx = 600; + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) { + tempbx = 768; + if( (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1024x768) && + (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1152x768) ) { + tempbx = 600; + } + } + } + } + tempcx -= tempbx; + + } else { + + tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE; /* VGAVT-VGAVDE */ + + } + + tempbx = SiS_Pr->SiS_LCDVDES; /* VGAVDES */ + push1 = tempbx; + + tempax = SiS_Pr->SiS_VGAVDE; + + if((SiS_Pr->SiS_IF_DEF_TRUMPION == 0) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) + && (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(!SiS_Pr->SiS_IF_DEF_DSTN){ + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempax = 600; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempax = 768; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) tempax = 600; /* TW */ + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) tempax = 768; /* TW */ + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempax = 1024; /* TW */ + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempax = 1050; /* TW */ + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempax = 1200; /* TW */ + else tempax = 600; + } + } + } + + tempbx += tempax; + if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT; + + push2 = tempbx; + + tempcx >>= 1; + + if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)){ + if(!SiS_Pr->SiS_IF_DEF_DSTN){ + if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) || + (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) ) { /* TW: @@@ TEST - not in BIOS! */ + tempcx = 0x0001; + } else if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) || + (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) ) { + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + tempcx = 0x0002; +#ifdef TWNEWPANEL + tempcx = 0x0003; +#endif + } else { + tempcx = 0x0002; /* TW: A901; other 301B BIOS sets 0x0003; */ + } + } else tempcx = 0x0003; + } + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) tempcx = 0x0003; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempcx = 0x0001; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x0001; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x0001; + else tempcx = 0x0057; + } + } + + tempbx += tempcx; /* BPLVRS */ + + if(HwDeviceExtension->jChipType < SIS_315H) { + tempbx++; + } + + if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT; + + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,temp); /* Part1_18h; TW: Panel Link Vertical Retrace Start */ + + tempcx >>= 3; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if( (HwDeviceExtension->jChipType < SIS_315H) && + (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) ) tempcx = 0x0001; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x0002; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x0002; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempcx = 0x0003; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) tempcx = 0x0005; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) tempcx = 0x0005; + else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) { + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + tempcx = 0x0004; +#ifdef TWNEWPANEL + tempcx = 0x0005; +#endif + } else { + tempcx = 0x0004; /* A901; Other BIOS sets 0x0005; */ + } + } else { + tempcx = 0x0005; + } + } + } + + tempcx = tempcx + tempbx + 1; /* BPLVRE */ + temp = tempcx & 0x000F; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xf0,temp); /* Part1_19h; TW: Panel Link Vertical Retrace End (3:0); Misc. */ + + temp = ((tempbx & 0x0700) >> 8) << 3; /* BPLDESKEW =0 */ + if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40; + if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) temp |= 0x40; + if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) { + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x01) { /* TW: Inserted from 650/LVDS 1.10.07 */ + temp |= 0x80; + } + } else { + if( (HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730) ) { + if(HwDeviceExtension->jChipRevision >= 0x30) { + temp |= 0x80; + } + } + } + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,0x87,temp); /* Part1_1Ah; TW: Panel Link Control Signal (7:3); Vertical Retrace Start (2:0) */ + + if (HwDeviceExtension->jChipType < SIS_315H) { + +#ifdef SIS300 /* 300 series */ + + tempeax = SiS_Pr->SiS_VGAVDE << 6; + temp = (USHORT)(tempeax % (ULONG)SiS_Pr->SiS_VDE); + tempeax = tempeax / (ULONG)SiS_Pr->SiS_VDE; + if(temp != 0) tempeax++; + tempebx = tempeax; /* BPLVCFACT */ + + if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) { + tempebx = 0x003F; + } + + temp = (USHORT)(tempebx & 0x00FF); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1E,temp); /* Part1_1Eh; TW: Panel Link Vertical Scaling Factor */ + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* 310/325 series */ + + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1E,0x23); + + tempeax = SiS_Pr->SiS_VGAVDE << 18; + temp = (USHORT)(tempeax % (ULONG)SiS_Pr->SiS_VDE); + tempeax = tempeax / SiS_Pr->SiS_VDE; + if(temp != 0) tempeax++; + tempebx = tempeax; /* BPLVCFACT */ + tempvcfact = tempeax; + temp = (USHORT)(tempebx & 0x00FF); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x37,temp); /* Part1_37h; TW: Panel Link Vertical Scaling Factor */ + temp = (USHORT)((tempebx & 0x00FF00) >> 8); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x36,temp); /* Part1_36h; TW: Panel Link Vertical Scaling Factor */ + temp = (USHORT)((tempebx & 0x00030000) >> 16); + if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x35,temp); /* Part1_35h; TW: Panel Link Vertical Scaling Factor */ + +#endif /* SIS315H */ + + } + + tempbx = push2; /* p bx temppush1 BPLVDEE */ + tempcx = push1; + + push1 = temp; /* TW: For 630/301B and 630/LVDS */ + + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if(!SiS_Pr->SiS_IF_DEF_DSTN){ + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) { + if(resinfo == 15) tempcx++; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) { + if(resinfo == 7) tempcx++; + } + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) { + if(resinfo == 7) tempcx++; + if(resinfo == 8) tempcx++; /* TW: Doesnt make sense anyway... */ + } else if(resinfo == 8) tempcx++; + } else { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) { + if(resinfo == 7) tempcx++; + } + } + } + } + + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) { + tempcx = SiS_Pr->SiS_VGAVDE; + tempbx = SiS_Pr->SiS_VGAVDE - 1; + } + + temp = ((tempbx & 0x0700) >> 8) << 3; + temp |= ((tempcx & 0x0700) >> 8); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1D,temp); /* Part1_1Dh; TW: Vertical Display Overflow; Control Signal */ + + temp = tempbx & 0x00FF; + if(SiS_Pr->SiS_IF_DEF_FSTN) temp++; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1C,temp); /* Part1_1Ch; TW: Panel Link Vertical Display Enable End */ + + temp = tempcx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1B,temp); /* Part1_1Bh; TW: Panel Link Vertical Display Enable Start */ + + /* 3. Additional horizontal setup (scaling, etc) */ + + tempecx = SiS_Pr->SiS_VGAHDE; + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(modeflag & HalfDCLK) + tempecx >>= 1; + } + tempebx = SiS_Pr->SiS_HDE; + if(tempecx == tempebx) tempeax = 0xFFFF; + else { + tempeax = tempecx; + tempeax <<= 16; + temp = (USHORT)(tempeax % tempebx); + tempeax = tempeax / tempebx; + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(temp) tempeax++; + } + } + tempecx = tempeax; + + if (HwDeviceExtension->jChipType >= SIS_315H) { + tempeax = SiS_Pr->SiS_VGAHDE; + if(modeflag & HalfDCLK) + tempeax >>= 1; + tempeax <<= 16; + tempeax = (tempeax / tempecx) - 1; + } else { + tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1; + } + tempecx <<= 16; + tempecx |= (tempeax & 0xFFFF); + temp = (USHORT)(tempecx & 0x00FF); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1F,temp); /* Part1_1Fh; TW: Panel Link DDA Operational Number in each horiz. line */ + + tempbx = SiS_Pr->SiS_VDE; + if (HwDeviceExtension->jChipType >= SIS_315H) { + tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact; + tempbx = (USHORT)(tempeax & 0x0FFFF); + } else { + tempax = SiS_Pr->SiS_VGAVDE << 6; + tempbx = push1; + tempbx &= 0x3f; + if(tempbx == 0) tempbx = 64; + tempax = tempax / tempbx; + tempbx = tempax; + } + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx--; + if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempbx = 1; + + temp = ((tempbx & 0xFF00) >> 8) << 3; + temp |= (USHORT)((tempecx & 0x0700) >> 8); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x20,temp); /* Part1_20h; TW: Overflow register */ + + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x21,temp); /* Part1_21h; TW: Panel Link Vertical Accumulator Register */ + + tempecx >>= 16; /* BPLHCFACT */ + if(HwDeviceExtension->jChipType < SIS_315H) { + if(modeflag & HalfDCLK) tempecx >>= 1; + } + temp = (USHORT)((tempecx & 0xFF00) >> 8); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x22,temp); /* Part1_22h; TW: Panel Link Horizontal Scaling Factor High */ + + temp = (USHORT)(tempecx & 0x00FF); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x23,temp); /* Part1_22h; TW: Panel Link Horizontal Scaling Factor Low */ + + /* 630/301B and 630/LVDS do something for 640x480 panels here */ + +#ifdef SIS315H + /* TW: DSTN/FSTN initialisation - hardcoded for 320x480 panel */ + if(SiS_Pr->SiS_IF_DEF_DSTN) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1E,0x01); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x25,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x26,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x27,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x28,0x87); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x29,0x5A); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2A,0x4B); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x007,0x03); + tempbx = SiS_Pr->SiS_HDE + 64; /*Blps = lcdhdee(lcdhdes+HDE) + 64*/ + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x38,temp); + temp=((tempbx & 0xFF00) >> 8) << 3; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp); + tempbx += 32; /*Blpe=lBlps+32*/ + temp = tempbx & 0x00FF; + if(SiS_Pr->SiS_IF_DEF_FSTN) temp=0; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x39,temp); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3A,0x00); /*Bflml=0*/ + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x007,0x00); + tempbx = SiS_Pr->SiS_VDE / 2; + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3B,temp); + temp = ((tempbx & 0xFF00) >> 8) << 3; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp); + tempeax = SiS_Pr->SiS_HDE << 2; /* BDxFIFOSTOP = (HDE*4)/128 */ + tempebx = 128; + temp = (USHORT)(tempeax % tempebx); + tempeax = tempeax / tempebx; + if(temp != 0) tempeax++; + temp = (USHORT)(tempeax & 0x003F); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x45,~0x0FF,temp); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3F,0x00); /* BDxWadrst0 */ + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3E,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3D,0x10); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x040,0x00); + tempax = SiS_Pr->SiS_HDE >> 4; /* BDxWadroff = HDE*4/8/8 */ + pushcx = tempax; + temp = tempax & 0x00FF; + SiS_SetReg1(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 */ + tempeax = (tempax * pushcx); + tempebx = 0x00100000 + tempeax; + temp = (USHORT)tempebx & 0x000000FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x42,temp); + temp = (USHORT)((tempebx & 0x0000FF00)>>8); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x41,temp); + temp = (USHORT)((tempebx & 0x00FF0000)>>16); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x40,temp); + temp = (USHORT)(((tempebx & 0x01000000)>>24) << 7); + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2F,0x03); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x03,0x50); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x04,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2F,0x01); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x13,0x00); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86); /* Unlock */ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1e,0x62); + if(SiS_Pr->SiS_IF_DEF_FSTN){ + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2b,0x1b); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2c,0xe3); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1e,0x62); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2e,0x04); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2f,0x42); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,0x01); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2b,0x02); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2c,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2d,0x00); + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,0x30); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1e,0x7d); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2e,0xe0); + } +#endif /* SIS315H */ + + return; + +} + +#ifdef SIS315H +void +SiS_CRT2AutoThreshold(SiS_Private *SiS_Pr, USHORT BaseAddr) +{ + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40); +} +#endif + + +/* TW: For LVDS / 302b/lv - LCDA (this must only be called on 310/325 series!) */ +/* TW: Double-checked against 650/LVDS and 650/301 BIOS */ +void +SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex) +{ + USHORT modeflag,resinfo; + USHORT push1,push2,tempax,tempbx,tempcx,temp; + ULONG tempeax=0,tempebx,tempecx,tempvcfact; + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* TW: From 650/LVDS BIOS */ + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04); /* TW: From 650/LVDS BIOS */ + } + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* TW: From 650/LVDS 1.10.07 */ + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00); /* TW: From 650/LVDS 1.10.07 */ + } else { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f); /* TW: From 650/301Lvx 1.10.6s */ + } + + if(ModeNo<=0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + } + + tempax = SiS_Pr->SiS_LCDHDES; + tempbx = SiS_Pr->SiS_HDE; + tempcx = SiS_Pr->SiS_HT; + + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx = 1024; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempbx = 1400; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempbx = 1600; + else tempbx = 1280; + + } + tempcx -= tempbx; /* HT-HDE */ + push1 = tempax; + tempax += tempbx; /* lcdhdee */ + tempbx = SiS_Pr->SiS_HT; + if(tempax >= tempbx) tempax -= tempbx; + + push2 = tempax; /* push ax lcdhdee */ + + tempcx >>= 2; + + /* TW: Inserted from 650/301LVx 1.10.6s */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempcx = 0x28; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x30; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempcx = 0x18; + else tempcx = 0x30; + } + } + + tempcx += tempax; /* lcdhrs */ + if(tempcx >= tempbx) tempcx -= tempbx; + /* v ah,cl */ + tempax = tempcx; + tempax >>= 3; /* BPLHRS */ + temp = tempax & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x14,temp); /* Part1_14h */ + + temp += 10; + temp &= 0x1F; + temp |= ((tempcx & 0x07) << 5); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x15,temp); /* Part1_15h */ + + tempbx = push2; /* lcdhdee */ + tempcx = push1; /* lcdhdes */ + temp = (tempcx & 0x00FF); + temp &= 0x07; /* BPLHDESKEW */ + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1A,temp); /* Part1_1Ah */ + + tempcx >>= 3; /* BPLHDES */ + temp = tempcx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x16,temp); /* Part1_16h */ + + if(tempbx & 0x07) tempbx += 8; + tempbx >>= 3; /* BPLHDEE */ + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x17,temp); /* Part1_17h */ + + tempcx = SiS_Pr->SiS_VGAVT; + tempbx = SiS_Pr->SiS_VGAVDE; + tempcx -= tempbx; /* GAVT-VGAVDE */ + tempbx = SiS_Pr->SiS_LCDVDES; /* VGAVDES */ + push1 = tempbx; /* push bx temppush1 */ + if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0){ + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempax = 768; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempax = 1024; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempax = 1050; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempax = 1200; + else tempax = 960; +#if 0 /* TW: Removed (650/LVDS BIOS) */ + if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + tempax = SiS_Pr->SiS_VGAVDE; + } + } +#endif + } else tempax = SiS_Pr->SiS_VGAVDE; /* Trumpion */ + + tempbx += tempax; + tempax = SiS_Pr->SiS_VT; /* VT */ + if(tempbx >= tempax) tempbx -= tempax; + + push2 = tempbx; /* push bx temppush2 */ + tempcx >>= 2; /* TO CHECK - was 1 */ + + /* TW: Inserted from 650/301LVx 1.10.6s */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempcx = 1; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempcx = 3; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) tempcx = 3; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempcx = 1; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 1; + else tempcx = 0x0057; + } + } + + tempbx += tempcx; + tempbx++; /* BPLVRS */ + if(tempbx >= tempax) tempbx -= tempax; + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,temp); /* Part1_18h */ + + tempcx >>= 3; + tempcx += tempbx; + tempcx++; /* BPLVRE */ + temp = tempcx & 0x00FF; + temp &= 0x0F; + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + /* TW: Inserted from 650/LVDS BIOS */ + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xf0,temp); + } else { + /* TW: Inserted from 650/301LVx 1.10.6s */ + temp |= 0xC0; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp); /* Part1_19h */ + } + + temp = (tempbx & 0xFF00) >> 8; + temp &= 0x07; + temp <<= 3; /* BPLDESKEW =0 */ + tempbx = SiS_Pr->SiS_VGAVDE; + if(tempbx != SiS_Pr->SiS_VDE) temp |= 0x40; + if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) temp |= 0x40; + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + /* TW: Inserted from 650/LVDS 1.10.07 */ + if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp |= 0x80; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,0x87,temp); /* Part1_1Ah */ + } else { + /* TW: Inserted from 650/301LVx 1.10.6s */ + if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) { + if(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,0x87,temp); /* Part1_1Ah */ + } + + tempbx = push2; /* p bx temppush2 BPLVDEE */ + tempcx = push1; /* pop cx temppush1 NPLVDES */ + push1 = (USHORT)(tempeax & 0xFFFF); + + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) { + if(resinfo == 7) tempcx++; + } + } + /* TW: Inserted from 650/301LVx+LVDS BIOSes */ + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) { + tempbx = SiS_Pr->SiS_VGAVDE; + tempcx = tempbx; + tempbx--; + } + + temp = (tempbx & 0xFF00) >> 8; + temp &= 0x07; + temp <<= 3; + temp = temp | (((tempcx & 0xFF00) >> 8) & 0x07); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1D,temp); /* Part1_1Dh */ + + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1C,temp); /* Part1_1Ch */ + + temp = tempcx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1B,temp); /* Part1_1Bh */ + + tempecx = SiS_Pr->SiS_VGAVT; + tempebx = SiS_Pr->SiS_VDE; + tempeax = SiS_Pr->SiS_VGAVDE; + tempecx -= tempeax; /* VGAVT-VGAVDE */ + tempeax <<= 18; + temp = (USHORT)(tempeax % tempebx); + tempeax = tempeax / tempebx; + if(temp) tempeax++; + tempebx = tempeax; /* BPLVCFACT */ + tempvcfact = tempeax; + temp = (USHORT)(tempebx & 0x00FF); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x37,temp); + + temp = (USHORT)((tempebx & 0x00FF00) >> 8); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x36,temp); + + temp = (USHORT)((tempebx & 0x00030000) >> 16); + if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x35,temp); + + tempecx = SiS_Pr->SiS_VGAHDE; + tempebx = SiS_Pr->SiS_HDE; + tempeax = tempecx; + tempeax <<= 16; + temp = tempeax % tempebx; + tempeax = tempeax / tempebx; + if(temp) tempeax++; + if(tempebx == tempecx) tempeax = 0xFFFF; + tempecx = tempeax; + tempeax = SiS_Pr->SiS_VGAHDE; + tempeax <<= 16; + tempeax = tempeax / tempecx; + tempecx <<= 16; + tempeax--; + tempecx = tempecx | (tempeax & 0xFFFF); + temp = (USHORT)(tempecx & 0x00FF); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1F,temp); /* Part1_1Fh */ + + tempeax = SiS_Pr->SiS_VGAVDE; + tempeax <<= 18; + tempeax = tempeax / tempvcfact; + tempbx = (USHORT)(tempeax & 0x0FFFF); + + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx--; + + if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempbx = 1; + + temp = ((tempbx & 0xFF00) >> 8) << 3; + temp = temp | (USHORT)(((tempecx & 0x0000FF00) >> 8) & 0x07); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x20,temp); /* Part1_20h */ + + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x21,temp); /* Part1_21h */ + + tempecx >>= 16; /* BPLHCFACT */ + if(modeflag & HalfDCLK) tempecx >>= 1; + temp = (USHORT)((tempecx & 0x0000FF00) >> 8); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x22,temp); /* Part1_22h */ + + temp=(USHORT)(tempecx & 0x000000FF); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x23,temp); + +#if 0 + /* TW: Missing code (calles int 2f) (650/301LVx 1.10.6s; 1.10.7w doesn't do this) */ + if(xxx()) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0e,0xda); + } +#endif + + /* TW: Only for 650/LVDS and 30xLV/30xLVX */ + if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBInfo & (VB_SIS30xLV|VB_SIS30xNEW))){ + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1e,0x20); + } + + return; +} + +/* TW: Double-checked against 650/LVDS (1.10.07) and 650/301 BIOS */ +void SiS_SetCRT2Offset(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo, + USHORT ModeIdIndex ,USHORT RefreshRateTableIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT offset; + UCHAR temp; + + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return; + + offset = SiS_GetOffset(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + HwDeviceExtension); + temp = (UCHAR)(offset & 0xFF); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,temp); + temp = (UCHAR)((offset & 0xFF00) >> 8); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x09,temp); + temp = (UCHAR)(((offset >> 3) & 0xFF) + 1); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x03,temp); +} + +/* TW: Checked with 650/LVDS and 650/301 BIOS */ +USHORT +SiS_GetOffset(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT temp,colordepth; + USHORT modeinfo,index,infoflag; + + if(SiS_Pr->UseCustomMode) { + infoflag = SiS_Pr->CInfoFlag; + temp = SiS_Pr->CHDisplay / 16; + } else { + infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag; + modeinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeInfo; + + if(HwDeviceExtension->jChipType < SIS_315H ) { + index = (modeinfo >> 4) & 0xFF; + } else { + index = (modeinfo >> 8) & 0xFF; + } + + temp = SiS_Pr->SiS_ScreenOffset[index]; + } + + colordepth = SiS_GetColorDepth(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex); + + if(infoflag & InterlaceMode) temp <<= 1; + + temp *= colordepth; + + /* TW: For 1400x1050 and 856x480 */ + if( ( ((ModeNo >= 0x26) && (ModeNo <= 0x28)) || + ModeNo == 0x3f || + ModeNo == 0x42 || + ModeNo == 0x45 ) || + (SiS_Pr->UseCustomMode && (SiS_Pr->CHDisplay % 16)) ) { + colordepth >>= 1; + temp += colordepth; + } + + return(temp); +} + +/* TW: Checked with 650/LVDS BIOS */ +USHORT +SiS_GetColorDepth(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT ColorDepth[6] = { 1, 2, 4, 4, 6, 8}; + SHORT index; + USHORT 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; + } + + index = (modeflag & ModeInfoFlag) - ModeEGA; + if(index < 0) index = 0; + return(ColorDepth[index]); +} + +/* TW: Checked against 630/301/301B/LVDS, 650/301LVx/LVDS */ +void +SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT tempah=0,tempbl,infoflag,flag; + + flag = 0; + tempbl = 0xC0; + + infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag; + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* LVDS */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + tempah = SiS_Pr->SiS_LCDInfo; + if(HwDeviceExtension->jChipType >= SIS_315H) { + tempbl = tempah & 0xc0; + } + if(SiS_Pr->SiS_LCDInfo & LCDSync) { + flag = 1; + } + } + if(flag != 1) tempah = infoflag >> 8; + tempah &= 0xC0; + tempah |= 0x20; + if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10; + + if (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) { + /* TW: BIOS does something here @@@ */ + } + + tempah &= 0x3f; + tempah |= tempbl; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah); + + } else { + + if(HwDeviceExtension->jChipType < SIS_315H) { + +#ifdef SIS300 /* ---- 300 series --- */ + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* 630 - 301B */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + tempah = SiS_Pr->SiS_LCDInfo; + if(SiS_Pr->SiS_LCDInfo & LCDSync) { + flag = 1; + } + } + if(flag != 1) tempah = infoflag >> 8; + tempah &= 0xC0; + tempah |= 0x20; + + if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10; + + if (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) { + /* TW: BIOS does something here @@@ */ + } + + tempah &= 0x3f; + tempah |= tempbl; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah); + + } else { /* 630 - 301 */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + tempah = SiS_Pr->SiS_LCDInfo; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpandingShift) { /* ! */ + flag = 1; + } + } + if(flag != 1) tempah = infoflag >> 8; + tempah &= 0xC0; + tempah |= 0x30; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x3F,tempah); + + } + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* ----- 310/325 series ---- */ + + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { /* 310/325 - 301LV/LVX */ + + tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37); + tempah &= 0xC0; + tempah |= 0x20; + if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah); + + } else { /* 310/325 - 301, 301B */ + + tempah = infoflag >> 8; + tempah &= 0xC0; + tempah |= 0x20; + + if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10; + + if (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) { + /* TW: BIOS does something here @@@ */ + } + + tempah &= 0x3f; + tempah |= tempbl; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah); + + } +#endif /* SIS315H */ + } + } +} + +/* TW: Set CRT2 FIFO on 300/630/730 */ +/* TW: Checked against 630/301B BIOS; BIOS does not set PCI registers */ +#ifdef SIS300 +void +SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + 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,ROMAddr,&CRT1ModeNo,&modeidindex); + SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2); + SiS_Pr->SiS_SelectCRT2Rate = 0; + refreshratetableindex = SiS_GetRatePtrCRT2(SiS_Pr,ROMAddr,CRT1ModeNo, + modeidindex,HwDeviceExtension); + + if(CRT1ModeNo >= 0x13) { + index = SiS_Pr->SiS_RefIndex[refreshratetableindex].Ext_CRTVCLK; + index &= 0x3F; + VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */ + data2 = SiS_Pr->SiS_ModeType - 2; + } + + } else { + + CRT1ModeNo = 0xfe; + VCLK = SiS_Pr->CSRClock; /* Get VCLK */ + data2 = (SiS_Pr->CModeFlag & ModeInfoFlag) - 2; + + } + + if(CRT1ModeNo >= 0x13) { + if(HwDeviceExtension->jChipType == SIS_300) { + index = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3A); + } else { + index = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1A); + } + index &= 0x07; + MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */ + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "FIFO2: CRT1Mode 0x%x VCLK %d MCLK %d modetype-2 = %d\n", + CRT1ModeNo, VCLK, MCLK, data2); +#endif + + 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; break; + } + data2 = (colorth * VCLK) / MCLK; + + temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); + temp = ((temp & 0x00FF) >> 6) << 1; + if(temp == 0) temp = 1; + temp <<= 2; + temp &= 0xff; + + data2 = temp - data2; + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "FIFO2: data2 (step1) = %d\n", + data2); +#endif + + if((28 * 16) % data2) { + data2 = (28 * 16) / data2; + data2++; + } else { + data2 = (28 * 16) / data2; + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "FIFO2: data2 (step2) = %d\n", + data2); +#endif + + if(HwDeviceExtension->jChipType == SIS_300) { + + tempah = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x18); + tempah &= 0x62; + tempah >>= 1; + tempal = tempah; + tempah >>= 3; + tempal |= tempah; + tempal &= 0x07; + tempcl = ThTiming[tempal]; + tempbx = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); + tempbx >>= 6; + tempah = SiS_GetReg1(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(HwDeviceExtension->jChipType == SIS_730) { + +#ifndef LINUX_XF86 + SiS_SetReg4(0xcf8,0x80000050); + eax = SiS_GetReg3(0xcfc); +#else + eax = pciReadLong(0x00000000, 0x50); +#endif + tempal = (USHORT)(eax >> 8); + tempal &= 0x06; + tempal <<= 5; + +#ifndef LINUX_XF86 + SiS_SetReg4(0xcf8,0x800000A0); + eax = SiS_GetReg3(0xcfc); +#else + eax = pciReadLong(0x00000000, 0xA0); +#endif + temp = (USHORT)(eax >> 28); + temp &= 0x0F; + tempal |= temp; + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "FIFO2: Latencyfactorindex = 0x%x\n", tempal); +#endif + + 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_GetReg1(SiS_Pr->SiS_P3c4,0x14); + if(!(temp & 0x80)) data += 5; + + } else { + + index = 0; + temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14); + if(temp & 0x0080) index += 12; + +#ifndef LINUX_XF86 + SiS_SetReg4(0xcf8,0x800000A0); + eax = SiS_GetReg3(0xcfc); +#else + /* TW: 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; + +#ifndef LINUX_XF86 + SiS_SetReg4(0xcf8,0x80000050); + eax = SiS_GetReg3(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_GetReg1(SiS_Pr->SiS_P3c4,0x14); + if(!(temp & 0x80)) data += 5; + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "FIFO2: latencyfactor (CRT1) = %d\n", data); +#endif + + data += data2; /* CRT1 Request Period */ + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "FIFO2: CRT1 request period = %d\n", data); +#endif + + CRT2ModeNo = ModeNo; + SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; + SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup; + SiS_SearchModeID(SiS_Pr,ROMAddr,&CRT2ModeNo,&modeidindex); + + refreshratetableindex = SiS_GetRatePtrCRT2(SiS_Pr,ROMAddr,CRT2ModeNo, + modeidindex,HwDeviceExtension); + + index = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,CRT2ModeNo,modeidindex, + refreshratetableindex,HwDeviceExtension); + VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */ + + data2 = SiS_Pr->SiS_ModeType - 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; break; + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "FIFO2: CRT2Mode 0x%x VCLK %d MCLK %d modetype-2 = %d, colorth %d\n", + CRT2ModeNo, VCLK, MCLK, data2, colorth); +#endif + + data = data * VCLK * colorth; + if(data % (MCLK << 4)) { + data = data / (MCLK << 4); + data++; + } else { + data = data / (MCLK << 4); + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "FIFO2: data (unclipped) = 0x%x\n", data); +#endif + + if(data <= 6) data = 6; + if(data > 0x14) data = 0x14; + + temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x01); + if(HwDeviceExtension->jChipType == SIS_300) { + if(data <= 0x0f) temp = (temp & (~0x1F)) | 0x13; + else temp = (temp & (~0x1F)) | 0x16; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) { + temp = (temp & (~0x1F)) | 0x13; + } + } else { + if( ( (HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730) ) && + (HwDeviceExtension->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( (HwDeviceExtension->jChipType == SIS_630) && + (HwDeviceExtension->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 + +/* TW: Set FIFO on 310 series */ +#ifdef SIS315H +void +SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + + UCHAR CombCode[] = { 1, 1, 1, 4, 3, 1, 3, 4, + 4, 1, 4, 4, 5, 1, 5, 4}; + UCHAR CRT2ThLow[] = { 39, 63, 55, 79, 78,102, 90,114, + 55, 87, 84,116,103,135,119,151}; + USHORT temp3,tempax,tempbx,tempcx; + USHORT tempcl, tempch; + USHORT index; + USHORT CRT1ModeNo,CRT2ModeNo; + USHORT ModeIdIndex; + USHORT RefreshRateTableIndex; + USHORT SelectRate_backup; + + SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate; + + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x01,0x3B); + + if(!SiS_Pr->CRT1UsesCustomMode) { + + CRT1ModeNo = SiS_Pr->SiS_CRT1Mode; /* get CRT1 ModeNo */ + SiS_SearchModeID(SiS_Pr,ROMAddr,&CRT1ModeNo,&ModeIdIndex); + + SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2); + SiS_Pr->SiS_SelectCRT2Rate = 0; + + /* Get REFIndex for crt1 refreshrate */ + RefreshRateTableIndex = SiS_GetRatePtrCRT2(SiS_Pr,ROMAddr,CRT1ModeNo, + ModeIdIndex,HwDeviceExtension); + + index = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,CRT1ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + tempax = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */ + + tempbx = SiS_GetColorDepth(SiS_Pr,ROMAddr,CRT1ModeNo,ModeIdIndex); /* Get colordepth */ + tempbx >>= 1; + if(!tempbx) tempbx++; + + } else { + + tempax = SiS_Pr->CSRClock; /* Get VCLK */ + tempbx = (SiS_Pr->CModeFlag & ModeInfoFlag) - 2; + switch(tempbx) { /* Get color depth */ + case 0 : tempbx = 1; break; + case 1 : tempbx = 1; break; + case 2 : tempbx = 2; break; + case 3 : tempbx = 2; break; + case 4 : tempbx = 3; break; + case 5 : tempbx = 4; break; + default: tempbx = 2; break; + } + + } + + tempax *= tempbx; + + tempbx = SiS_GetMCLK(SiS_Pr,ROMAddr, HwDeviceExtension); /* Get MCLK */ + + tempax /= tempbx; + + tempbx = tempax; + +#if 0 /* TW: BIOS code is skrewed */ + if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14) & 0x02) { + tempax = 16; + } else { + tempax = 8; + } +#endif + tempax = 16; + + tempax -= tempbx; + + tempbx = tempax; /* tempbx = 16-DRamBus - DCLK*BytePerPixel/MCLK */ + + tempax = ((52 * 16) / tempbx); + + if ((52*16 % tempbx) != 0) { + tempax++; + } + tempcx = tempax; + tempcx += 40; + + /* get DRAM latency */ + tempcl = (SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) >> 3) & 0x7; /* SR17[5:3] DRAM Queue depth */ + tempch = (SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) >> 6) & 0x3; /* SR17[7:6] DRAM Grant length */ + + for (temp3 = 0; temp3 < 16; temp3 += 2) { + if ((CombCode[temp3] == tempcl) && (CombCode[temp3+1] == tempch)) { + temp3 = CRT2ThLow[temp3 >> 1]; + } + } + + tempcx += temp3; /* CRT1 Request Period */ + + CRT2ModeNo = ModeNo; /* get CRT2 ModeNo */ + SiS_SearchModeID(SiS_Pr,ROMAddr,&CRT2ModeNo,&ModeIdIndex); /* Get ModeID Table */ + + SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; + SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup; + + RefreshRateTableIndex = SiS_GetRatePtrCRT2(SiS_Pr,ROMAddr,CRT2ModeNo, + ModeIdIndex,HwDeviceExtension); + + index = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,CRT2ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + tempax = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */ + + tempbx = SiS_GetColorDepth(SiS_Pr,ROMAddr,CRT2ModeNo,ModeIdIndex); /* Get colordepth */ + tempbx >>= 1; + if(!tempbx) tempbx++; + + tempax *= tempbx; + + tempax *= tempcx; + + tempbx = SiS_GetMCLK(SiS_Pr,ROMAddr, HwDeviceExtension); /* Get MCLK */ + tempbx <<= 4; + + tempcx = tempax; + tempax /= tempbx; + if(tempcx % tempbx) tempax++; /* CRT1 Request period * TCLK * BytePerPixel / (MCLK*16) */ + + if (tempax > 0x37) tempax = 0x37; + + /* TW: 650/LVDS (1.10.07, 1.10.00), 650/301LV overrule calculated value; 315 does not */ + if(HwDeviceExtension->jChipType == SIS_650) { + tempax = 0x04; + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3F,tempax); +} + +USHORT +SiS_GetMCLK(SiS_Private *SiS_Pr, UCHAR *ROMAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT index; + + index = SiS_Get310DRAMType(SiS_Pr,ROMAddr,HwDeviceExtension); + if(index >= 4) { + index -= 4; + return(SiS_Pr->SiS_MCLKData_1[index].CLOCK); + } else { + return(SiS_Pr->SiS_MCLKData_0[index].CLOCK); + } +} +#endif + +/* TW: Checked against 650/LVDS 1.10.07 BIOS */ +void +SiS_GetLVDSDesData(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT modeflag; + USHORT PanelIndex,ResIndex; + const SiS_LVDSDesStruct *PanelDesPtr = NULL; + + if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ) { + + SiS_GetLVDSDesPtrA(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + &PanelIndex,&ResIndex); + switch (PanelIndex) + { + case 0: PanelDesPtr = SiS_Pr->LVDS1024x768Des_1; break; /* --- expanding --- */ + case 1: PanelDesPtr = SiS_Pr->LVDS1280x1024Des_1; break; + case 2: PanelDesPtr = SiS_Pr->LVDS1400x1050Des_1; break; + case 3: PanelDesPtr = SiS_Pr->LVDS1600x1200Des_1; break; + case 4: PanelDesPtr = SiS_Pr->LVDS1024x768Des_2; break; /* --- non expanding --- */ + case 5: PanelDesPtr = SiS_Pr->LVDS1280x1024Des_2; break; + case 6: PanelDesPtr = SiS_Pr->LVDS1400x1050Des_2; break; + case 7: PanelDesPtr = SiS_Pr->LVDS1600x1200Des_2; break; + default: PanelDesPtr = SiS_Pr->LVDS1024x768Des_1; break; + } + + } else { + + SiS_GetLVDSDesPtr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + &PanelIndex,&ResIndex,HwDeviceExtension); + + switch (PanelIndex) + { + case 0: PanelDesPtr = SiS_Pr->SiS_PanelType00_1; break; /* --- expanding --- | */ + 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; /* --- non-expanding --- */ + 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_CHTVUNTSCDesData; break; + case 33: PanelDesPtr = SiS_Pr->SiS_CHTVONTSCDesData; break; + case 34: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData; break; + case 35: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData; break; + default: + if(HwDeviceExtension->jChipType < SIS_315H) + PanelDesPtr = SiS_Pr->SiS_PanelType0e_1; + else + PanelDesPtr = SiS_Pr->SiS_PanelType01_1; + break; + } + } + SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES; + SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES; + + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding){ + if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + if(!(modeflag & HalfDCLK)) { + SiS_Pr->SiS_LCDHDES = 632; + } + } + } else { + if(!(SiS_Pr->SiS_SetFlag & CRT2IsVGA)) { + if((HwDeviceExtension->jChipType < SIS_315H) || (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)) { /* TW: New from 650/LVDS 1.10.07 */ + if(SiS_Pr->SiS_LCDResInfo >= SiS_Pr->SiS_Panel1024x768){ + if(ModeNo <= 0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + if(HwDeviceExtension->jChipType < SIS_315H) { + if(!(modeflag & HalfDCLK)) { + SiS_Pr->SiS_LCDHDES = 320; + } + } else { + /* TW: New from 650/LVDS 1.10.07 */ + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) + SiS_Pr->SiS_LCDHDES = 480; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) + SiS_Pr->SiS_LCDHDES = 804; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) + SiS_Pr->SiS_LCDHDES = 704; + if(!(modeflag & HalfDCLK)) { + SiS_Pr->SiS_LCDHDES = 320; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) + SiS_Pr->SiS_LCDHDES = 632; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) + SiS_Pr->SiS_LCDHDES = 542; + } + } + } + } + } + } + } + } + return; +} + +/* TW: Checked against 630/LVDS (2.04.5c) and 650/LVDS (1.10.07) BIOS */ +void +SiS_GetLVDSDesPtr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *PanelIndex, + USHORT *ResIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT tempbx,tempal,modeflag; + + if(ModeNo<=0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + } + + tempbx = 0; + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) { + tempbx = 32; + if((SiS_Pr->SiS_VBInfo & SetPALTV) && (!SiS_Pr->SiS_CHPALM)) tempbx += 2; + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx += 1; + /* TW: Nothing special needed for SOverscan */ + /* PALM uses NTSC data, PALN uses PAL data */ + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + tempbx = SiS_Pr->SiS_LCDTypeInfo; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 16; + /* TW: Inserted from 650/LVDS (1.10.07) BIOS */ + if(SiS_Pr->SiS_LCDInfo & LCDPass11) { + if(modeflag & HalfDCLK) tempbx += 16; + } + } + /* TW: Inserted from 630/LVDS and 650/LVDS (1.10.07) BIOS */ + if(SiS_Pr->SiS_SetFlag & CRT2IsVGA) { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) { + tempal = 0x07; + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x80) tempal++; + } + } + } + + *PanelIndex = tempbx; + *ResIndex = tempal & 0x1F; +} + +void +SiS_GetLVDSDesPtrA(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *PanelIndex, + USHORT *ResIndex) +{ + USHORT tempbx=0,tempal; + + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + tempbx = 3; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) { + tempbx = 4; + } else tempbx = SiS_Pr->SiS_LCDResInfo - SiS_Pr->SiS_PanelMinLVDS; + + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 4; + + if(ModeNo<=0x13) + tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + else + tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + + *PanelIndex = tempbx; + *ResIndex = tempal & 0x1F; +} + +/* TW: Checked against 650/LVDS (1.10.07), 650/301LV, 650/301LVx (!), 630/301 and 630/301B (II) BIOS */ +void +SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT BaseAddr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT i,j,modeflag; + USHORT tempcl,tempah=0; +#ifdef SIS300 + USHORT temp; +#endif +#ifdef SIS315H + USHORT tempbl; +#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; + } + } + + /* TW: BIOS does not do this (neither 301 nor LVDS) */ + /* (But it's harmless; see SetCRT2Offset) */ + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x03,0x00); /* fix write part1 index 0 BTDRAM bit Bug */ + + /* TW: Removed 301B302B301LV302LV check here to match 650/LVDS BIOS */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + + /* TW: 1. for LVDS/302B/302LV **LCDA** */ + + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40); /* FUNCTION CONTROL */ + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7); + + } else { + + for(i=0,j=4; i<3; i++,j++) SiS_SetReg1(SiS_Pr->SiS_Part1Port,j,0); + + tempcl = SiS_Pr->SiS_ModeType; + + if(HwDeviceExtension->jChipType < SIS_315H) { + +#ifdef SIS300 /* ---- 300 series ---- */ + + /* TW: Inserted entire if-section from 630/301B BIOS */ + if((HwDeviceExtension->jChipType != SIS_300) && + (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) { + temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x32); + temp &= 0xef; + temp |= 0x02; + /* If 0x10 not set when using VGA2, monitor will stay black */ + if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) { + temp |= 0x10; + temp &= 0xfd; + } + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,temp); + } + + if(ModeNo > 0x13) { + tempcl -= ModeVGA; + if((tempcl > 0) || (tempcl == 0)) { /* TW: 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 /* ---- 310 series ---- */ + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_VBInfo & CRT2DisplayFlag) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x08); + } + } + + if(ModeNo > 0x13) { + tempcl -= ModeVGA; + if((tempcl > 0) || (tempcl == 0)) { /* TW: 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 & CRT2DisplayFlag) tempah = 0; + + if(HwDeviceExtension->jChipType < SIS_315H) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x00,tempah); /* FUNCTION CONTROL */ + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah); /* FUNCTION CONTROL */ + } + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + + /* TW: 2. for 301 (301B, 302B 301LV, 302LV non-LCDA) */ + + 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 & CRT2DisplayFlag) tempah = 0; + + if(HwDeviceExtension->jChipType < SIS_315H) { + + /* --- 300 series --- */ + + tempah = (tempah << 5) & 0xFF; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x01,tempah); + tempah = (tempah >> 5) & 0xFF; + + } else { + + /* --- 310 series --- */ + + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF8,tempah); + + } + + if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) { + tempah |= 0x10; + } + + /* TW: Inserted from 630/301 BIOS */ + if((HwDeviceExtension->jChipType < SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301)) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) { + tempah |= 0x80; + } + } else { + tempah |= 0x80; + } + + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV - SetCRT2ToHiVisionTV)){ + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + tempah |= 0x20; + } + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah); + + tempah = 0; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + SiS_Pr->SiS_SetFlag |= RPLLDIV2XO; + tempah |= 0x40; + } else { + if(!(SiS_Pr->SiS_SetFlag & TVSimuMode)) { +#ifdef oldHV + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV)) { +#endif + SiS_Pr->SiS_SetFlag |= RPLLDIV2XO; + tempah |= 0x40; +#ifdef oldHV + } +#endif + } + } + } else { + SiS_Pr->SiS_SetFlag |= RPLLDIV2XO; + tempah |= 0x40; + } + } + /* TW: Inserted from 630/301LVx BIOS 1.10.6s */ + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) + tempah |= 0x40; + } + } + + if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) || + (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)) { + tempah |= 0x80; + } + + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0C,tempah); + + } else { + + /* TW: 3. for LVDS */ + + /* TW: Inserted if-statement - Part1Port 0x2e not assigned on 300 series */ + if(HwDeviceExtension->jChipType >= SIS_315H) { + + /* TW: Inserted this entire section (BIOS 650/LVDS); added ModeType check + * (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); + + } else { + + /* TW: (added ModeType check) */ + 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_SetReg1(SiS_Pr->SiS_Part1Port,0x01,tempah); + + } + + } + + } + + /* TW: Inserted the entire following section */ + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + + if(HwDeviceExtension->jChipType >= SIS_315H) { + +#ifdef SIS315H + tempah = 0x04; /* For all bridges */ + tempbl = 0xfb; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + tempah = 0x00; + if(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr)) + tempbl = 0xff; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah); + + /* TW: This in order to fix "TV-blue-bug" on 315+301 */ + if(SiS_Pr->SiS_VBType & VB_SIS301) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xCF); /* For 301 */ + } else { + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xCF,0x30); /* For 301LV */ + } else { + tempah = 0x30; /* For 301B */ + tempbl = 0xcf; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + tempah = 0x00; + if(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr)) { + tempbl = 0xff; + } + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah); + } + } + + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { /* For 301LV */ + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,0xc0); + } else { /* For 301, 301B */ + tempah = 0xc0; + tempbl = 0x3f; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + tempah = 0x00; + if(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr)) { + tempbl = 0xff; + } + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl,tempah); + } + + tempah = 0x00; /* For all bridges */ + tempbl = 0x7f; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + tempbl = 0xff; + if(!(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr))) + tempah |= 0x80; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah); + +#endif /* SIS315H */ + + } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f); + + if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) || + ( (HwDeviceExtension->jChipType != SIS_300) && + (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ) ) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F); + } else { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x23,0x80); + } + + } + + } else { /* LVDS */ + +#ifdef SIS315H + if(HwDeviceExtension->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, HwDeviceExtension, BaseAddr)) + tempbl = 0xff; + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah); + + if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x00); + + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,0x30); + + } + + } +#endif + + } + +} + +void +SiS_GetCRT2Data(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + + SiS_GetCRT2DataLVDS(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + HwDeviceExtension); + } else { + + if((HwDeviceExtension->jChipType < SIS_315H) && + (HwDeviceExtension->jChipType != SIS_300) && + (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) { + + SiS_GetCRT2Data301(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + HwDeviceExtension); + + /* TW: Need LVDS Data for LCD on 630/301B! */ + SiS_GetCRT2DataLVDS(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + HwDeviceExtension); + + } else { + + SiS_GetCRT2Data301(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + HwDeviceExtension); + } + + } + + } else { + + SiS_GetCRT2Data301(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + HwDeviceExtension); + } + + } else { + + SiS_GetCRT2DataLVDS(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + HwDeviceExtension); + } +} + +/* Checked with 650/LVDS 1.10.07 BIOS */ +void +SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT CRT2Index, ResIndex; + const SiS_LVDSDataStruct *LVDSData = NULL; + + SiS_GetCRT2ResInfo(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); + + if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + + 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_GetCRT2PtrA(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + &CRT2Index,&ResIndex); + + switch (CRT2Index) { + case 0: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break; + case 1: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1; break; + case 2: LVDSData = SiS_Pr->SiS_LVDS1280x960Data_1; break; + case 3: LVDSData = SiS_Pr->SiS_LCDA1400x1050Data_1; break; + case 4: LVDSData = SiS_Pr->SiS_LCDA1600x1200Data_1; break; + case 5: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2; break; + case 6: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_2; break; + case 7: LVDSData = SiS_Pr->SiS_LVDS1280x960Data_2; break; + case 8: LVDSData = SiS_Pr->SiS_LCDA1400x1050Data_2; break; + case 9: LVDSData = SiS_Pr->SiS_LCDA1600x1200Data_2; break; + default: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break; + } + + } else { + + /* TW: SiS630/301B needs LVDS Data! */ + if( (HwDeviceExtension->jChipType < SIS_315H) && + (HwDeviceExtension->jChipType != SIS_300) && + (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && + (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ) { + SiS_Pr->SiS_IF_DEF_LVDS = 1; + } + + SiS_GetCRT2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + &CRT2Index,&ResIndex,HwDeviceExtension); + + /* TW: SiS630/301B needs LVDS Data! */ + if( (HwDeviceExtension->jChipType < SIS_315H) && + (HwDeviceExtension->jChipType != SIS_300) && + (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && + (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_LVDS1024x768Data_1; break; + case 2: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1; break; + case 3: LVDSData = SiS_Pr->SiS_LVDS800x600Data_2; break; + case 4: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2; 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; /* TW: New */ + case 8: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_1; break; /* TW: New */ + case 9: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_2; break; /* TW: New */ + 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; /* TW: New */ + case 16: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_1; break; /* TW: New */ + case 17: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_2; break; /* TW: New */ + case 18: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_2; break; /* TW: New */ + case 19: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_1; break; /* TW: New */ + case 20: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2; break; /* TW: New */ + 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; /* TW: 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_IF_DEF_LVDS == 0) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) { + + if(!(SiS_Pr->SiS_LCDInfo & LCDNonExpanding)){ + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768){ + SiS_Pr->SiS_HDE = 1024; + SiS_Pr->SiS_VDE = 768; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024){ + SiS_Pr->SiS_HDE = 1280; + SiS_Pr->SiS_VDE = 1024; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050){ + SiS_Pr->SiS_HDE = 1400; + SiS_Pr->SiS_VDE = 1050; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200){ + SiS_Pr->SiS_HDE = 1600; + SiS_Pr->SiS_VDE = 1200; + } else { + SiS_Pr->SiS_HDE = 1280; + SiS_Pr->SiS_VDE = 960; + } + } + + } else { + + if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) { + if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) { + if((!(SiS_Pr->SiS_LCDInfo & LCDNonExpanding)) || (SiS_Pr->SiS_SetFlag & CRT2IsVGA)) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) { + SiS_Pr->SiS_HDE = 800; + SiS_Pr->SiS_VDE = 600; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) { + SiS_Pr->SiS_HDE = 1024; + SiS_Pr->SiS_VDE = 768; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) { + SiS_Pr->SiS_HDE = 1280; + SiS_Pr->SiS_VDE = 1024; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) { + SiS_Pr->SiS_HDE = 1024; + SiS_Pr->SiS_VDE = 600; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + SiS_Pr->SiS_HDE = 1400; + SiS_Pr->SiS_VDE = 1050; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) { + SiS_Pr->SiS_HDE = 1152; + SiS_Pr->SiS_VDE = 768; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x864) { + SiS_Pr->SiS_HDE = 1152; + SiS_Pr->SiS_VDE = 864; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) { + SiS_Pr->SiS_HDE = 1280; + SiS_Pr->SiS_VDE = 768; + } else { + SiS_Pr->SiS_HDE = 1600; + SiS_Pr->SiS_VDE = 1200; + } + if(SiS_Pr->SiS_IF_DEF_FSTN) { + SiS_Pr->SiS_HDE = 320; + SiS_Pr->SiS_VDE = 480; + } + } + } + } + } + } +} + +/* TW: Checked against 630/301B BIOS; does not check VDE values for LCD */ +void +SiS_GetCRT2Data301(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT tempax,tempbx,modeflag; + USHORT resinfo; + USHORT CRT2Index,ResIndex; + const SiS_LCDDataStruct *LCDPtr = NULL; + const SiS_TVDataStruct *TVPtr = NULL; + + if(ModeNo<=0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + } + 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,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension); + + /* TW: For VGA2 ("RAMDAC2") */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC){ + SiS_GetRAMDAC2DATA(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + HwDeviceExtension); + return; + } + + /* TW: For TV */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + + SiS_GetCRT2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + &CRT2Index,&ResIndex,HwDeviceExtension); + + switch (CRT2Index) { +#ifdef oldHV + case 2: TVPtr = SiS_Pr->SiS_ExtHiTVData; break; + case 7: TVPtr = SiS_Pr->SiS_St1HiTVData; break; + case 12: TVPtr = SiS_Pr->SiS_St2HiTVData; break; +#endif + case 3: TVPtr = SiS_Pr->SiS_ExtPALData; break; + case 4: TVPtr = SiS_Pr->SiS_ExtNTSCData; break; + case 8: TVPtr = SiS_Pr->SiS_StPALData; break; + case 9: TVPtr = SiS_Pr->SiS_StNTSCData; break; + default: TVPtr = SiS_Pr->SiS_StPALData; break; /* TW: Just to avoid a crash */ + } + + 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 & SetCRT2ToHiVisionTV) { /* TW: NOT oldHV! */ + + if(resinfo == 0x08) SiS_Pr->SiS_NewFlickerMode = 0x40; + if(resinfo == 0x09) SiS_Pr->SiS_NewFlickerMode = 0x40; + if(resinfo == 0x12) SiS_Pr->SiS_NewFlickerMode = 0x40; + + if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_SetFlag |= TVSimuMode; + + SiS_Pr->SiS_HT = ExtHiTVHT; + SiS_Pr->SiS_VT = ExtHiTVVT; + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(SiS_Pr->SiS_SetFlag & TVSimuMode) { + SiS_Pr->SiS_HT = StHiTVHT; + SiS_Pr->SiS_VT = StHiTVVT; + if(!(modeflag & Charx8Dot)){ + SiS_Pr->SiS_HT = StHiTextTVHT; + SiS_Pr->SiS_VT = StHiTextTVVT; + } + } + } + + } 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_VBInfo & SetPALTV)) { + SiS_Pr->SiS_HT = NTSCHT; +/* if(SiS_Pr->SiS_VBType & (VB_SIS30xLV|VB_SIS30xNEW)) { */ /* TW: ALL newer 650 BIOSes do this, no idea about 301B */ + if((ModeNo == 0x4a) || (ModeNo == 0x38)) SiS_Pr->SiS_HT = NTSC2HT; +/* } */ + SiS_Pr->SiS_VT = NTSCVT; + } else { + SiS_Pr->SiS_HT = PALHT; + SiS_Pr->SiS_VT = PALVT; + } + + } + + return; + } + + /* TW: For LCD */ + /* TW: Checked against 650/301LV; CRT2Index different (but does not matter) */ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + + SiS_GetCRT2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + &CRT2Index,&ResIndex,HwDeviceExtension); + + switch (CRT2Index) { + case 0: LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break; /* VESA Timing */ + case 1: LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data; break; /* VESA Timing */ + case 5: LCDPtr = SiS_Pr->SiS_StLCD1024x768Data; break; /* Obviously unused */ + case 6: LCDPtr = SiS_Pr->SiS_StLCD1280x1024Data; break; /* Obviously unused */ + case 10: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data; break; /* Non-VESA Timing */ + case 11: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break; /* Non-VESA Timing */ + case 13: LCDPtr = SiS_Pr->SiS_NoScaleData1024x768; break; /* Non-expanding */ + case 14: LCDPtr = SiS_Pr->SiS_NoScaleData1280x1024; break; /* Non-expanding */ + case 15: LCDPtr = SiS_Pr->SiS_LCD1280x960Data; break; /* 1280x960 */ + case 20: LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data; break; /* VESA Timing */ + case 21: LCDPtr = SiS_Pr->SiS_NoScaleData1400x1050; break; /* Non-expanding */ + case 22: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data; break; /* Non-VESA Timing */ + case 23: LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data; break; /* VESA Timing */ + case 24: LCDPtr = SiS_Pr->SiS_NoScaleData1600x1200; break; /* Non-expanding */ + case 25: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data; break; /* Non-VESA Timing */ + default: LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break; /* Just to avoid a crash */ + } + + 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 = 1024; + if(SiS_Pr->SiS_SetFlag & LCDVESATiming) { + if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560; + else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640; + else tempbx = 768; + } 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 tempbx = 768; + } + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024){ + tempax = 1280; + 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 tempbx = 1024; + } + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960){ + tempax = 1280; + 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 tempbx = 960; + } + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050){ + tempax = 1400; + tempbx = 1050; + } + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) { + tempax = SiS_Pr->SiS_VGAHDE; + tempbx = SiS_Pr->SiS_VGAVDE; + } + SiS_Pr->SiS_HDE = tempax; + SiS_Pr->SiS_VDE = tempbx; + return; + } +} + +USHORT +SiS_GetResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT resindex; + + if(ModeNo<=0x13) + resindex=SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; + else + resindex=SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + + return(resindex); +} + +/* TW: Checked against 650/301LV, 650/LVDS, 630/LVDS, 630/301 and 630/301B BIOS */ +void +SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT xres,yres,modeflag=0,resindex; + + resindex = SiS_GetResInfo(SiS_Pr,ROMAddr,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; + } + + /* TW: Inserted entire if-section from 650/LVDS BIOS 1.10.07: */ + if((HwDeviceExtension->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) { + if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & CRT2IsVGA)) { + if(yres == 350) yres = 400; + } + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x3a) & 0x01) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x34) == 0x12) + yres = 400; + } + } + + if(ModeNo > 0x13) { + if(SiS_Pr->SiS_IF_DEF_FSTN == 1){ + xres *= 2; + yres *= 2; + } else { + if(modeflag & HalfDCLK) xres *= 2; + if(modeflag & DoubleScanMode) yres *= 2; + } + } + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + /* TW: Inserted from 650/301LV BIOS */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + if(xres == 720) xres = 640; + } else { + if((HwDeviceExtension->jChipType != SIS_300) || + (SiS_Pr->SiS_VBInfo & (SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | + SetCRT2ToSCART | SetCRT2ToLCD | SetCRT2ToHiVisionTV))) { + if(xres == 720) xres = 640; + } + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) { + if(yres == 400) yres = 405; + if(yres == 350) yres = 360; + if(SiS_Pr->SiS_SetFlag & LCDVESATiming) { + if(yres == 360) yres = 375; + } + } + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768){ + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) { + if(!(SiS_Pr->SiS_LCDInfo & LCDNonExpanding)) { + if(yres == 350) yres = 357; + if(yres == 400) yres = 420; + if(yres == 480) yres = 525; + } + } + } + /* TW: Inserted for 630/301B */ + if( ( (HwDeviceExtension->jChipType < SIS_315H) && + (HwDeviceExtension->jChipType != SIS_300) ) && + (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) { + if(xres == 720) xres = 640; + } + } + } else { + if(xres == 720) xres = 640; + /* TW: Inserted from 650/LVDS and 630/LVDS BIOS */ + if(SiS_Pr->SiS_SetFlag & CRT2IsVGA) { + yres = 400; + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480; + } else { + if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480; + } + } + } + SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres; + SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres; +} + +/* TW: Checked against 650/301 and 650/LVDS (1.10.07) BIOS; modified for new panel resolutions */ +/* TW: Done differently in 630/301B BIOS; but same effect; checked against 630/301 */ +void +SiS_GetCRT2Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *CRT2Index,USHORT *ResIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT tempbx=0,tempal=0; + USHORT Flag,resinfo=0; + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { /* LCD */ + + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) { + tempbx = 15; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + tempbx = 20; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx = 21; + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 22; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) { + tempbx = 23; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx = 24; + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 25; + } else if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) { + tempbx = 13; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempbx++; + } else { + tempbx = SiS_Pr->SiS_LCDResInfo - SiS_Pr->SiS_Panel1024x768; + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) { + tempbx += 5; + /* GetRevisionID(); */ + /* TW: BIOS only adds 5 once */ + tempbx += 5; + } + } + + } else { /* TV */ +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV){ + if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_SetFlag &= (~TVSimuMode); /* TW: Was "(!TVSimuMode)" - WRONG */ + tempbx = 2; + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(!(SiS_Pr->SiS_SetFlag & TVSimuMode)) tempbx = 12; /* TW: Was 10! - WRONG */ + } + } else { +#endif + if(SiS_Pr->SiS_VBInfo & SetPALTV) tempbx = 3; + else tempbx = 4; + if(SiS_Pr->SiS_SetFlag & TVSimuMode) tempbx += 5; +#ifdef oldHV + } +#endif + } + + 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; + } + + tempal &= 0x3F; + + if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && + (SiS_Pr->SiS_VBInfo & (SetCRT2ToTV-SetCRT2ToHiVisionTV))) { + if(tempal == 0x06) tempal = 0x07; + } + + /* TW: Inserted from 300/301LV BIOS */ + if((HwDeviceExtension->jChipType == SIS_300) && + (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) { + if(ModeNo > 0x13) { + if((resinfo == 0x0c) || (resinfo == 0x0d)) /* 720 (index diff. on 310/325!) */ + tempal = 6; + } + } + + if(HwDeviceExtension->jChipType != SIS_300) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if((ModeNo == 0x31) || (ModeNo == 0x32)) tempal = 6; + } + } + + *CRT2Index = tempbx; + *ResIndex = tempal; + + } else { /* LVDS */ + + Flag = 1; + tempbx = 0; + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) { + Flag = 0; + tempbx = 10; + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx += 1; + if(SiS_Pr->SiS_VBInfo & SetPALTV) { + tempbx += 2; + if(SiS_Pr->SiS_CHSOverScan) tempbx = 99; + if(SiS_Pr->SiS_CHPALM) { + tempbx = 90; + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx += 1; + } else if(SiS_Pr->SiS_CHPALN) { + tempbx = 92; + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx += 1; + } + + } + } + } + + if(Flag == 1) { + tempbx = SiS_Pr->SiS_LCDResInfo - SiS_Pr->SiS_PanelMinLVDS; + if(SiS_Pr->SiS_LCDResInfo <= SiS_Pr->SiS_Panel1280x1024) { + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 3; + } else { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + tempbx = 8; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx++; + } + if(SiS_Pr->SiS_LCDInfo & LCDPass11) { + tempbx = 7; + } + + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) tempbx = 6; + + /* TW: Inserted from 630/LVDS 2.04.5c BIOS */ + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) { + tempbx = 15; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 2; + } + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) { + tempbx = 16; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 2; + } + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) { + tempbx = 18; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx++; + } + } + } + + 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_IF_DEF_FSTN){ + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480){ + tempbx = 14; + tempal = 6; + } + } + + /* TW: Inserted from 650/LVDS BIOS */ + if(SiS_Pr->SiS_SetFlag & CRT2IsVGA) { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) tempal = 7; + if(HwDeviceExtension->jChipType < SIS_315H) { + /* TW: Inserted from 630/LVDS (2.04.5c) and 630/301B (II) BIOS */ + if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x80) tempal++; + } + + } + + /* TW: Inserted from 630/301B BIOS */ + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(ModeNo > 0x13) { + if(HwDeviceExtension->jChipType < SIS_315H) { + if((resinfo == 0x0c) || (resinfo == 0x0d)) /* 720 */ + tempal = 6; + } else { + if((resinfo == 0x0d) || (resinfo == 0x0e)) /* 720 */ + tempal = 6; + } + } + } + + *CRT2Index = tempbx; + *ResIndex = tempal & 0x1F; + } +} + +void +SiS_GetCRT2PtrA(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *CRT2Index, + USHORT *ResIndex) +{ + USHORT tempbx,tempal; + + tempbx = SiS_Pr->SiS_LCDResInfo; + + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) { + tempbx = 4; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + tempbx = 3; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) { + tempbx = 2; + } else { + tempbx -= SiS_Pr->SiS_Panel1024x768; + } + + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 5; + + if(ModeNo <= 0x13) + tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + else + tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + + *CRT2Index = tempbx; + *ResIndex = tempal & 0x1F; +} + +/* TW: New from 650/301LVx BIOS */ +void +SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *CRT2Index, + USHORT *ResIndex) +{ + USHORT tempbx,tempal; + + if(ModeNo <= 0x13) + tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + else + tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + + tempbx = SiS_Pr->SiS_LCDResInfo; + + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 16; + else if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx += 32; + + *CRT2Index = tempbx; + *ResIndex = tempal & 0x3F; +} + +/* TW: Checked against all (incl 650/LVDS (1.10.07), 630/301B, 630/301) BIOSes */ +USHORT +SiS_GetRatePtrCRT2(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + SHORT LCDRefreshIndex[] = { 0x00, 0x00, 0x03, 0x01, + 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01 }; + USHORT RefreshRateTableIndex,i,backup_i; + USHORT modeflag,index,temp,backupindex; + + if(SiS_Pr->UseCustomMode) 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); + + /* TW: CR33 holds refresh rate index for CRT1 [3:0] and CRT2 [7:4]. + * On LVDS machines, CRT2 index is always 0 and will be + * set to 0 by the following code; this causes the function + * to take the first non-interlaced mode in SiS_Ext2Struct + */ + + index = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x33); + index >>= SiS_Pr->SiS_SelectCRT2Rate; + index &= 0x0F; + backupindex = index; + + if(index > 0) index--; + + if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0; + } else { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if((HwDeviceExtension->jChipType < SIS_315H) && + (HwDeviceExtension->jChipType != SIS_300)) + index = 0; + else if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) + index = backupindex = 0; + } + } + } + + if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + index = 0; + } + } + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + /* TW: This is not done in 630/301B BIOS */ + temp = LCDRefreshIndex[SiS_Pr->SiS_LCDResInfo]; + if(index > temp) index = temp; + } else { + index = 0; + } + } + } + + RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex; + ModeNo = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].ModeID; + + /* TW: Inserted from 650/LVDS 1.10.07, 650/301LVx 1.10.6s */ + if(HwDeviceExtension->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) + RefreshRateTableIndex++; + } + } + } + + i = 0; + do { + if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + i].ModeID != ModeNo) break; + temp = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + i].Ext_InfoFlag; + temp &= ModeInfoFlag; + 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[RefreshRateTableIndex + 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,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,&i,HwDeviceExtension))) { + /* TW: This is for avoiding random data to be used; i is + * in an undefined state if no matching CRT2 mode is + * found. + */ + i = backup_i; + } + } + + return(RefreshRateTableIndex + i); +} + +/* Checked against all (incl 650/LVDS (1.10.07), 630/301) BIOSes */ +BOOLEAN +SiS_AdjustCRT2Rate(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *i,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT tempax,tempbx,resinfo; + USHORT modeflag,infoflag; + + if (ModeNo <= 0x13) + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + else + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + tempbx = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID; + + tempax = 0; + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + /* TW: For 301, 301B, 302B, 301LV, 302LV */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { + tempax |= SupportRAMDAC2; + if(HwDeviceExtension->jChipType >= SIS_315H) { + tempax |= SupportTV; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if(resinfo == 0x0a) tempax |= SupportTV1024; + } + } + } + } + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + tempax |= SupportLCD; + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200) { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1400x1050) { + if((resinfo == 6) && (SiS_Pr->SiS_LCDInfo & LCDNonExpanding)) { + tempax |= SupportAllCRT2; + (*i) = 0; /* TW: Restore RefreshTableIndex (BIOS 650/301LVx 1.10.6s) */ + return(1); + } else { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024) { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x960) { + if((resinfo == 6) && (SiS_Pr->SiS_LCDInfo & LCDNonExpanding)) { + return(0); + } else { + if((resinfo >= 9) && (resinfo != 0x14)) { + tempax = 0; + return(0); + } + } + } + } + } + } + } + } else { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) { + if((resinfo != 0x0f) && ((resinfo == 4) || (resinfo >= 8))) return(0); + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) { + if((resinfo != 0x10) && (resinfo > 8)) return(0); + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) { + if((resinfo != 0x0e) && (resinfo > 8)) return(0); + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) { + if(resinfo > 9) return(0); + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) { + if(resinfo > 8) return(0); + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) { + if((resinfo == 4) || (resinfo > 7)) return(0); + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) { + if((resinfo == 4) || (resinfo == 3) || (resinfo > 6)) return(0); + } + } + } +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) { /* for HiTV */ + tempax |= SupportHiVisionTV; + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode){ + if(resinfo == 4) return(0); + if(resinfo == 3) { + if(SiS_Pr->SiS_SetFlag & TVSimuMode) return(0); + } + if(resinfo > 7) return(0); + } + } else { +#endif + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) { + tempax |= SupportTV; + tempax |= SupportTV1024; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if((SiS_Pr->SiS_VBInfo & SetNotSimuMode) && (SiS_Pr->SiS_VBInfo & SetPALTV)) { + if(resinfo != 8) { + if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) || + ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != 4)) ) { + tempax &= ~(SupportTV1024); + if(HwDeviceExtension->jChipType >= SIS_315H) { + if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) || + ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != 7)) ) { + if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return(0); + } + } + } else { + if( (resinfo != 3) || + (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || + (SiS_Pr->SiS_VBInfo & SetNotSimuMode) ) { + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if(resinfo == 3) return(0); + if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return (0); + } + } + } else return(0); + } + } + } + } else { + tempax &= ~(SupportTV1024); + if(HwDeviceExtension->jChipType >= SIS_315H) { + if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) || + ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != 7)) ) { + if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return(0); + } + } + } else { + if( (resinfo != 3) || + (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || + (SiS_Pr->SiS_VBInfo & SetNotSimuMode) ) { + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if(resinfo == 3) return(0); + if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return (0); + } + } + } else return(0); + } + } + } else { /* slavemode */ + if(resinfo != 8) { + if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) || + ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != 4) ) ) { + tempax &= ~(SupportTV1024); + if(HwDeviceExtension->jChipType >= SIS_315H) { + if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) || + ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != 7)) ) { + if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return(0); + } + } + } else { + if( (resinfo != 3) || + (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || + (SiS_Pr->SiS_VBInfo & SetNotSimuMode) ) { + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if(resinfo == 3) return(0); + if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return (0); + } + } + } else return(0); + } + } + } + } + } else { /* 301 */ + tempax &= ~(SupportTV1024); + if(HwDeviceExtension->jChipType >= SIS_315H) { + if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) || + ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != 7)) ) { + if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return(0); + } + } + } else { + if( (resinfo != 3) || + (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || + (SiS_Pr->SiS_VBInfo & SetNotSimuMode) ) { + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + if(resinfo == 3) return(0); + if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return (0); + } + } + } else return(0); + } + } + } +#ifdef oldHV + } +#endif + } else { /* TW: for LVDS */ + + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + tempax |= SupportCHTV; + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + tempax |= SupportLCD; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) { + if((resinfo != 0x14) && (resinfo > 0x09)) return(0); + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) { + if((resinfo != 0x0f) && (resinfo > 0x08)) return(0); + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) { + if((resinfo != 0x10) && (resinfo > 0x08)) return(0); + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + if((resinfo != 0x15) && (resinfo > 0x09)) return(0); + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) { + if(resinfo > 0x09) return(0); + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) { + if(resinfo > 0x08) return(0); + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600){ + if(resinfo > 0x07) return(0); + if(resinfo == 0x04) return(0); + } + } + } + /* TW: Look backwards in table for matching CRT2 mode */ + for(; SiS_Pr->SiS_RefIndex[RefreshRateTableIndex+(*i)].ModeID == tempbx; (*i)--) { + infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag; + if(infoflag & tempax) { + return(1); + } + if ((*i) == 0) break; + } + /* TW: 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)++) { + infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag; + if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID != tempbx) { + return(0); + } + if(infoflag & tempax) { + return(1); + } + } + return(1); +} + +/* Checked against 650/LVDS (1.10.07) and 650/301LV BIOS */ +void +SiS_SaveCRT2Info(SiS_Private *SiS_Pr, USHORT ModeNo) +{ + USHORT temp1,temp2; + + /* TW: We store CRT1 ModeNo in CR34 */ + SiS_SetReg1(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); +} + +/* TW: Checked against 650+301, 650/LVDS (1.10.07) and 650/301LVx (1.10.6s) BIOS */ +void +SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + USHORT ModeIdIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension, + int checkcrt2mode) +{ + USHORT tempax,tempbx,temp; + USHORT modeflag, resinfo=0; + UCHAR OutputSelect = *SiS_Pr->pSiS_OutputSelect; + + 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; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + } + } + + SiS_Pr->SiS_SetFlag = 0; + + SiS_Pr->SiS_ModeType = modeflag & ModeInfoFlag; + + tempbx = 0; + if(SiS_BridgeIsOn(SiS_Pr,BaseAddr,HwDeviceExtension) == 0) { /* TW: "== 0" inserted from 630/301B BIOS */ + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + /* SiS_HiVision is only used on 310/325+30xB/LV/LVX */ + if(SiS_Pr->SiS_HiVision & 0x03) { /* TW: New from 650/301LVx 1.10.6s */ + temp &= (SetCRT2ToHiVisionTV | SwitchToCRT2 | SetSimuScanMode); /* 0x83 */ + temp |= SetCRT2ToHiVisionTV; /* 0x80 */ + } + if(SiS_Pr->SiS_HiVision & 0x04) { /* TW: New from 650/301LVx 1.10.6s */ + temp &= (SetCRT2ToHiVisionTV | SwitchToCRT2 | SetSimuScanMode); /* 0x83 */ + temp |= SetCRT2ToSVIDEO; /* 0x08 */ + } + if(SiS_Pr->SiS_IF_DEF_FSTN) { /* fstn must set CR30=0x21 */ + temp = (SetCRT2ToLCD | SetSimuScanMode); + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x30,temp); + } + tempbx |= temp; + tempax = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) << 8; + tempax &= (LoadDACFlag | DriverMode | SetDispDevSwitch | SetNotSimuMode | SetPALTV); + tempbx |= tempax; + tempbx &= ~(SetCHTVOverScan | SetInSlaveMode | DisableCRT2Display);; + +#ifdef SIS315H + + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VBType & (VB_SIS302B | VB_SIS30xLV | VB_SIS30xNEW)) { +#if 0 /* Not in 1.10.8r */ + if(ModeNo == 3) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf); + } +#endif +#if 0 /* Not in 1.10.8r */ + if(!(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) { + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc); + } +#endif + if((tempbx & SetCRT2ToLCD) && (SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD)) { + if((SiS_GetReg1(SiS_Pr->SiS_P3d4, 0x36) & 0x0f) == SiS_Pr->SiS_Panel1400x1050) { + if((ModeNo <= 0x13) || (!(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA)); /* 3 */ + } + } + } else { + if((ModeNo <= 0x13) || (!(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) { + SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA)); /* 3 */ + } + } + } + } + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) { + tempbx |= SetCRT2ToLCDA; + } + } + /* TW: Inserted from 650/LVDS 1.10.07 BIOS: */ + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + if(temp & SetToLCDA) + tempbx |= SetCRT2ToLCDA; + if(temp & EnableLVDSHiVision) + tempbx |= SetCRT2ToHiVisionTV; + } + } + +#endif /* SIS315H */ + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + temp = SetCRT2ToLCDA | SetCRT2ToSCART | SetCRT2ToLCD | + SetCRT2ToRAMDAC | SetCRT2ToSVIDEO | SetCRT2ToAVIDEO; /* = 0x807C; */ + if(SiS_Pr->SiS_IF_DEF_HiVision == 1) + temp |= SetCRT2ToHiVisionTV; /* = 0x80FC; */ + } else { + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) + temp = SetCRT2ToLCDA | SetCRT2ToSCART | + SetCRT2ToLCD | SetCRT2ToHiVisionTV | + SetCRT2ToAVIDEO | SetCRT2ToSVIDEO; /* = 0x80bc */ + 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_IF_DEF_LVDS == 0) { + if(tempbx & SetCRT2ToLCDA) { + tempbx &= (0xFF00|SwitchToCRT2|SetSimuScanMode); + } + if(tempbx & SetCRT2ToRAMDAC) { + tempbx &= (0xFF00|SetCRT2ToRAMDAC|SwitchToCRT2|SetSimuScanMode); + } + if((tempbx & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) { + tempbx &= (0xFF00|SetCRT2ToLCD|SwitchToCRT2|SetSimuScanMode); + } + if(tempbx & SetCRT2ToSCART) { + tempbx &= (0xFF00|SetCRT2ToSCART|SwitchToCRT2|SetSimuScanMode); + tempbx |= SetPALTV; + } +#if 0 /* TW: Not done in 650/301LVx 1.10.6s BIOS */ + } else if(tempbx & SetCRT2ToHiVisionTV){ + tempbx &= (0xFF00|SetCRT2ToHiVisionTV|SwitchToCRT2|SetSimuScanMode); + tempbx |= SetPALTV; + } +#endif + } else { /* LVDS */ + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(tempbx & SetCRT2ToLCDA) + tempbx &= (0xFF00|SwitchToCRT2|SetSimuScanMode); + } + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(tempbx & SetCRT2ToTV) + tempbx &= (0xFF00|SetCRT2ToTV|SwitchToCRT2|SetSimuScanMode); + } + if(tempbx & SetCRT2ToLCD) { + tempbx &= (0xFF00|SetCRT2ToLCD|SwitchToCRT2|SetSimuScanMode); + } + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(tempbx & SetCRT2ToLCDA) + tempbx |= SetCRT2ToLCD; + } + } + + if(tempax & DisableCRT2Display) { + if(!(tempbx & (SwitchToCRT2 | SetSimuScanMode))) { + tempbx = SetSimuScanMode | DisableCRT2Display; + } + } + + if(!(tempbx & DriverMode)){ + tempbx |= SetSimuScanMode; + } + + /* TW: LVDS (LCD/TV) and 630+301B (LCD) can only be slave in 8bpp modes */ + if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->SiS_ModeType <= ModeVGA) ) { + modeflag &= (~CRT2Mode); + } + if( (HwDeviceExtension->jChipType < SIS_315H) && + (HwDeviceExtension->jChipType != SIS_300) && + (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) { + if(SiS_Pr->SiS_ModeType <= ModeVGA) { + if(tempbx & SetCRT2ToLCD) { + modeflag &= (~CRT2Mode); + } + } + } + /* TW end */ + + if(!(tempbx & SetSimuScanMode)){ + if(tempbx & SwitchToCRT2) { + if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) { + if( (HwDeviceExtension->jChipType >= SIS_315H) && + (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) { + if(resinfo != 0x0a) + tempbx |= SetSimuScanMode; + } else { + tempbx |= SetSimuScanMode; + } + } + } else { + if(!(SiS_BridgeIsEnable(SiS_Pr,BaseAddr,HwDeviceExtension))) { + if(!(tempbx & DriverMode)) { + if(SiS_BridgeInSlave(SiS_Pr)) { + tempbx |= SetSimuScanMode; + } + } + } + } + } + + if(!(tempbx & DisableCRT2Display)) { + if(tempbx & DriverMode) { + if(tempbx & SetSimuScanMode) { + if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) { + if( (HwDeviceExtension->jChipType >= SIS_315H) && + (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) { + if(resinfo != 0x0a) { /* TW: Inserted from 650/301 BIOS */ + tempbx |= SetInSlaveMode; + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + if(tempbx & SetCRT2ToTV) { + if(!(tempbx & SetNotSimuMode)) + SiS_Pr->SiS_SetFlag |= TVSimuMode; + } + } + } /* TW: Inserted from 650/301 BIOS */ + } else { + tempbx |= SetInSlaveMode; + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + if(tempbx & SetCRT2ToTV) { + if(!(tempbx & SetNotSimuMode)) + SiS_Pr->SiS_SetFlag |= TVSimuMode; + } + } + } + } + } + } else { + tempbx |= SetInSlaveMode; + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + if(tempbx & SetCRT2ToTV) { + if(!(tempbx & SetNotSimuMode)) + SiS_Pr->SiS_SetFlag |= TVSimuMode; + } + } + } + } + + if(SiS_Pr->SiS_CHOverScan) { + if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) { + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x35); + if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1) ) + tempbx |= SetCHTVOverScan; + } + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x79); + if( (temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1) ) + tempbx |= SetCHTVOverScan; + } + } + } + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { +#ifdef SIS300 + if((HwDeviceExtension->jChipType==SIS_630) || + (HwDeviceExtension->jChipType==SIS_730)) { + if(ROMAddr && SiS_Pr->SiS_UseROM) { + OutputSelect = ROMAddr[0xfe]; + } + if(!(OutputSelect & EnablePALMN)) + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0x3F); + if(tempbx & SetCRT2ToTV) { + if(tempbx & SetPALTV) { + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x35); + if(temp & EnablePALM) tempbx &= (~SetPALTV); + } + } + } +#endif +#ifdef SIS315H + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(ROMAddr && SiS_Pr->SiS_UseROM) { + OutputSelect = ROMAddr[0xf3]; + if(HwDeviceExtension->jChipType == SIS_330) { + OutputSelect = ROMAddr[0x11b]; + } + } + if(!(OutputSelect & EnablePALMN)) + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0x3F); + if(tempbx & SetCRT2ToTV) { + if(tempbx & SetPALTV) { + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + if(temp & EnablePALM) tempbx &= (~SetPALTV); + } + } + } +#endif + } + + /* PALM/PALN on Chrontel 7019 */ + SiS_Pr->SiS_CHPALM = SiS_Pr->SiS_CHPALN = FALSE; + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + if(tempbx & SetCRT2ToTV) { + if(tempbx & SetPALTV) { + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + if(temp & EnablePALM) SiS_Pr->SiS_CHPALM = TRUE; + else if(temp & EnablePALN) SiS_Pr->SiS_CHPALN = TRUE; + } + } + } + + SiS_Pr->SiS_VBInfo = tempbx; + + if(HwDeviceExtension->jChipType == SIS_630) { + SiS_WhatIsThis(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 + +#if 0 /* TW: Incomplete! (But does not seem to be required) */ + if(HwDeviceExtension->jChipType < SIS_315H) { + /* TW: From A901/630+301B BIOS */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x80) + } + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) { + if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x80) + if( [si] == 3) ModeIdIndex = 0x3f2b; + } + } + SiS_SetRegAND(SiS_Pr->SiS_P3d4, 0x31, 0xF7); + if(ModeNo == 0x13) bp+4 = 0x03; + } else { + /* From 650/301LVx BIOS: */ + SiS_SetRegAND(SiS_Pr->SiS_P3d4, 0x31, 0xF7); + if(ModeNo == 0x13) bp+4 = 0x03; + else bp+4 = ModeNo; + } +#endif + + /* TW: 630/301B and 650/301 (not 301LV!) BIOSes do more here, but this seems for DOS mode */ + +} + +void +SiS_WhatIsThis(SiS_Private *SiS_Pr, USHORT myvbinfo) +{ + unsigned long eax, temp; + unsigned short temp1; + + if(!(SiS_Pr->SiS_ChSW)) return; + +#ifndef LINUX_XF86 + SiS_SetReg4(0xcf8,0x80000874); + eax = SiS_GetReg3(0xcfc); +#else + eax = pciReadLong(0x00000800, 0x74); +#endif + eax &= 0xFFFF; + temp = eax; + eax += 0x3c; + temp1 = SiS_GetReg4((USHORT)eax); + temp1 &= 0xFEFF; + SiS_SetReg5((USHORT)eax, temp1); + temp1 = SiS_GetReg4((USHORT)eax); + eax = temp; + eax += 0x3a; + temp1 = SiS_GetReg4((USHORT)eax); + temp1 &= 0xFEFF; + if(!(myvbinfo & SetCRT2ToTV)) { + temp1 |= 0x0100; + } + SiS_SetReg5((USHORT)eax, temp1); + temp1 = SiS_GetReg4((USHORT)eax); +} + +void +SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT tempax,tempbx,temp; + USHORT temp1,modeflag=0,tempcx; + USHORT StandTableIndex,CRT1Index; + USHORT ResInfo,DisplayType; + const SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr = NULL; + + SiS_Pr->SiS_RVBHCMAX = 1; + SiS_Pr->SiS_RVBHCFACT = 1; + + if(ModeNo <= 0x13){ + + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + StandTableIndex = SiS_GetModePtr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex); + tempax = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[0]; + tempbx = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[6]; + temp1 = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[7]; + + } else { + + if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ) { + + temp = SiS_GetLVDSCRT1Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,&ResInfo,&DisplayType); + + if(temp == 0) return; + + switch(DisplayType) { + case 0 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1; break; + case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1; break; + case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1; break; + case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H; break; + case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H; break; + case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H; break; + case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2; break; + case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2; break; + case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2; break; + case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H; break; + case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H; 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; + 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 99: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL; break; + default: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1; break; + } + tempax = (LVDSCRT1Ptr+ResInfo)->CR[0]; + tempax |= (LVDSCRT1Ptr+ResInfo)->CR[14] << 8; + tempax &= 0x03FF; + tempbx = (LVDSCRT1Ptr+ResInfo)->CR[6]; + tempcx = (LVDSCRT1Ptr+ResInfo)->CR[13] << 8; + tempcx &= 0x0100; + tempcx <<= 2; + tempbx |= tempcx; + temp1 = (LVDSCRT1Ptr+ResInfo)->CR[7]; + + } else { + + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; +#if 0 /* Not any longer */ + if(HwDeviceExtension->jChipType < SIS_315H) CRT1Index &= 0x3F; +#endif + tempax = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0]; + tempax |= SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14] << 8; + tempax &= 0x03FF; + tempbx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6]; + tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13] << 8; + tempcx &= 0x0100; + tempcx <<= 2; + tempbx |= tempcx; + temp1 = SiS_Pr->SiS_CRT1Table[CRT1Index].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; + + /* TW: From 650/301LVx 1.10.6s */ + if(modeflag & HalfDCLK) tempax <<= 1; + + SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax; + tempbx++; + SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx; +} + +void +SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr) +{ + if(HwDeviceExtension->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_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr) +{ + if(HwDeviceExtension->jChipType >= SIS_315H) + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE); + else + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE); +} + +void +SiS_EnableCRT2(SiS_Private *SiS_Pr) +{ + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); +} + +/* Checked against all BIOSes */ +void +SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr) +{ +#ifdef SIS315H + USHORT tempah,pushax=0; +#endif + USHORT temp=0; + UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase; + + if (SiS_Pr->SiS_IF_DEF_LVDS == 0) { + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* ===== TW: For 30xB/LV ===== */ + + if(HwDeviceExtension->jChipType < SIS_315H) { + +#ifdef SIS300 /* 300 series */ + + if(HwDeviceExtension->jChipType == SIS_300) { /* New for 300+301LV */ + + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwDeviceExtension))) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xFE,0x00); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + } + if(SiS_Is301B(SiS_Pr,BaseAddr)) { + 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); + if( (!(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension))) || + (!(SiS_CR36BIOSWord23d(SiS_Pr,HwDeviceExtension))) ) { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 2); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xFB,0x04); + } + + } else { + + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwDeviceExtension))) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + } + if(SiS_Is301B(SiS_Pr,BaseAddr)) { + 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,HwDeviceExtension,BaseAddr); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); + if( (!(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension))) || + (!(SiS_CR36BIOSWord23d(SiS_Pr,HwDeviceExtension))) ) { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 2); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xFB,0x04); + } + } + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* 310/325 series */ + + if(IS_SIS650740) { /* 650, 740 */ + +#if 0 + if(SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x00) != 1) return; /* From 1.10.7w */ +#endif + + if(SiS_Pr->SiS_VBType & (VB_SIS30xLV|VB_SIS30xNEW)) { + + if(!(SiS_IsM650or651(SiS_Pr,HwDeviceExtension, BaseAddr))) { + tempah = 0xef; + if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + tempah = 0xf7; + } + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah); + } + + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00); + + if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xFE,0x00); + } else if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xFE,0x00); + } + + SiS_SetReg3(SiS_Pr->SiS_P3c6,0x00); + + pushax = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x06); + + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + + } + + if(SiS_Pr->SiS_VBType & (VB_SIS301B|VB_SIS302B)) { + tempah = 0x3f; + if(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)) { + tempah = 0x7f; + if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) { + tempah = 0xbf; + } + } + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah); + } + + if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + + if(SiS_Pr->SiS_VBType & (VB_SIS301B|VB_SIS302B)) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF); + SiS_DisplayOff(SiS_Pr); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); + } else { + SiS_DisplayOff(SiS_Pr); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 2); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF); + } + + } else { + + if(SiS_Pr->SiS_VBType & (VB_SIS301B|VB_SIS302B)) { + if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf); + SiS_DisplayOff(SiS_Pr); + } + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); + temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x00,temp); + } else { + SiS_DisplayOff(SiS_Pr); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 2); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); + temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x00,temp); + } + + } + + if(SiS_Pr->SiS_VBType & (VB_SIS30xLV|VB_SIS30xNEW)) { + + tempah = 0x3f; + if(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)) { + tempah = 0x7f; + if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) { + tempah = 0xbf; + } + } + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah); + + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f); + + if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf); + } + + if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) { + if(!(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension))) { + if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xFD,0x00); + } + } + } + + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x06,pushax); + + } + + + } else { /* 315, 330 */ + + if(SiS_Is301B(SiS_Pr,BaseAddr)) { + tempah = 0x3f; + if(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)) { + tempah = 0x7f; + if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) { + tempah = 0xbf; + } + } + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah); + if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_DisplayOff(SiS_Pr); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); + } + } + if( (!(SiS_Is301B(SiS_Pr,BaseAddr))) || + (!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) ) { + + if( (!(SiS_Is301B(SiS_Pr,BaseAddr))) || + (!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) ) { + + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); + SiS_DisplayOff(SiS_Pr); + + } + + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80); + + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); + + temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x00,temp); + + } + + } /* 315/330 */ + +#endif /* SIS315H */ + + } + + } else { /* ============ TW: For 301 ================ */ + + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF0,0x0B); + SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 1); + } + } + + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); /* disable VB */ + SiS_DisplayOff(SiS_Pr); + + if(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80); + } + + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); /* disable lock mode */ + + if(HwDeviceExtension->jChipType >= SIS_315H) { + temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10); + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x00,temp); + } else { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */ + } + + } + + } else { /* ============ TW: For LVDS =============*/ + + if(HwDeviceExtension->jChipType < SIS_315H) { + +#ifdef SIS300 /* 300 series */ + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) { + SiS_SetCH700x(SiS_Pr,0x090E); + } + + if(HwDeviceExtension->jChipType == SIS_730) { + if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x11) & 0x08)) { + SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension); + } + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwDeviceExtension))) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + } + } else { + if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x11) & 0x08)) { + + if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x40)) { + + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwDeviceExtension))) { + + SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension); + + if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) { + SiS_DisplayOff(SiS_Pr); + } + + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 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,HwDeviceExtension,BaseAddr); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); + + if( (!(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension))) || + (!(SiS_CR36BIOSWord23d(SiS_Pr,HwDeviceExtension))) ) { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 2); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xFB,0x04); + } + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* 310/325 series */ + + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_Chrontel701xBLOff(SiS_Pr); + SiS_Chrontel701xOff(SiS_Pr); + } else if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_Chrontel701xBLOff(SiS_Pr); + SiS_Chrontel701xOff(SiS_Pr); + } + + if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetCH701x(SiS_Pr,0x0149); + } else if(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_SetCH701x(SiS_Pr,0x0149); + } + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + SiS_DisplayOff(SiS_Pr); + } else if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_DisplayOff(SiS_Pr); + } else if(!(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_DisplayOff(SiS_Pr); + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80); + } else if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80); + } else if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80); + } + + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); + } else if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); + } else if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + if(SiS_CRT2IsLCD(SiS_Pr, BaseAddr,HwDeviceExtension)) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf); + } + } else if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf); + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); + } else { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb); + } + } + + SiS_UnLockCRT2(SiS_Pr,HwDeviceExtension, BaseAddr); + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7); + } else if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7); + } else if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7); + } + +#if 0 /* TW: BIOS code makes no sense */ + if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) { + if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr)) { + /* Nothing there! */ + } + } + } +#endif + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + if(SiS_CRT2IsLCD(SiS_Pr, BaseAddr,HwDeviceExtension)) { + if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 2); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xFB,0x04); + } + } + } + +#endif /* SIS315H */ + + } /* 310 series */ + + } /* LVDS */ + +} + +/* TW: Checked against all BIOSes */ +void +SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr) +{ + USHORT temp=0,tempah; +#ifdef SIS315H + USHORT temp1,pushax=0; + BOOLEAN delaylong = FALSE; +#endif + UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase; + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* TW: ====== For 301B et al ====== */ + + if(HwDeviceExtension->jChipType < SIS_315H) { + +#ifdef SIS300 /* 300 series */ + + if(HwDeviceExtension->jChipType == SIS_300) { + + if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02); + if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwDeviceExtension))) { + SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 0); + } + } + temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */ + if(SiS_BridgeInSlave(SiS_Pr)) { + tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20; + } + SiS_SetReg1(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 */ + if(SiS_Is301B(SiS_Pr,BaseAddr)) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0); + SiS_DisplayOn(SiS_Pr); + } else { + SiS_VBLongWait(SiS_Pr); + SiS_DisplayOn(SiS_Pr); + SiS_VBLongWait(SiS_Pr); + } + if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) { + if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x40)) { + if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16) & 0x10)) { + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwDeviceExtension))) { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 1); + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xfe,0x01); + } + } + } + + } else { + + if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xFB); + if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwDeviceExtension))) { + SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 0); + } + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* Enable CRT2 */ +/* DoSomeThingPCI_On(SiS_Pr) */ + SiS_DisplayOn(SiS_Pr); + SiS_UnLockCRT2(SiS_Pr,HwDeviceExtension, BaseAddr); + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF); + if(SiS_BridgeInSlave(SiS_Pr)) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F); + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40); + } + if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x40)) { + if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16) & 0x10)) { + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwDeviceExtension))) { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 1); + } + SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x00); + } + } + } else { + temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */ + if(SiS_BridgeInSlave(SiS_Pr)) { + tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20; + } + SiS_SetReg1(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 */ + if(SiS_Is301B(SiS_Pr,BaseAddr)) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0); + SiS_DisplayOn(SiS_Pr); + } else { + SiS_VBLongWait(SiS_Pr); + SiS_DisplayOn(SiS_Pr); + SiS_VBLongWait(SiS_Pr); + } + } + + } +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* 310/325 series */ + + if(IS_SIS650740) { /* 650, 740 */ + +#if 0 + if(SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x00) != 1) return; /* From 1.10.7w */ +#endif + + if(SiS_Pr->SiS_VBType & (VB_SIS30xLV|VB_SIS30xNEW)) { + + if(!(SiS_IsM650or651(SiS_Pr,HwDeviceExtension, BaseAddr))) { + tempah = 0x10; + if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + tempah = 0x08; + } + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,tempah); + } + + SiS_SetReg3(SiS_Pr->SiS_P3c6,0x00); + + SiS_DisplayOff(SiS_Pr); + + pushax = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x06); + + if( (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) || + (SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) ) { + if(!(SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02); + } + } + + if(!(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x40)) { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + delaylong = TRUE; + } + + } + + if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) { + temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x32) & 0xDF; + if(SiS_BridgeInSlave(SiS_Pr)) { + tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20; + } + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,temp); + + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */ + if(SiS_Pr->SiS_VBType & (VB_SIS301B|VB_SIS302B)) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f); + temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x2e); + if(!(temp & 0x80)) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80); + } + } else { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 2); + } + } + + if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20); + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20); + + if(SiS_Pr->SiS_VBType & (VB_SIS301B|VB_SIS302B)) { + temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x2e); + if(!(temp & 0x80)) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80); + } + } + + tempah = 0xc0; + if(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)) { + tempah = 0x80; + if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) { + tempah = 0x40; + } + } + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah); + + if(SiS_Pr->SiS_VBType & (VB_SIS301B|VB_SIS302B)) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f); + } + + if(SiS_Pr->SiS_VBType & (VB_SIS30xLV|VB_SIS30xNEW)) { + + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80); + + if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) { + if( (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) || + ((SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension))) ) { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + if(delaylong) { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3); + } + SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension); + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xfe,0x01); + } + } + + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x06,pushax); + SiS_DisplayOn(SiS_Pr); + SiS_SetReg3(SiS_Pr->SiS_P3c6,0xff); + + if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f); + } + + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00); + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c); + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x31,0x05); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x32,0x60); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x33,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10); + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40); + + } + + + } else { /* 315, 330 */ + + if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) { + temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x32) & 0xDF; + if(SiS_BridgeInSlave(SiS_Pr)) { + tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20; + } + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,temp); + + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */ + + temp=SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x2E); + if (!(temp & 0x80)) + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80); + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20); + + if(SiS_Is301B(SiS_Pr,BaseAddr)) { + + temp=SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x2E); + if (!(temp & 0x80)) + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80); + + tempah = 0xc0; + if(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)) { + tempah = 0x80; + if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) { + tempah = 0x40; + } + } + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah); + + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f); + + } else { + + SiS_VBLongWait(SiS_Pr); + SiS_DisplayOn(SiS_Pr); + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7F); + SiS_VBLongWait(SiS_Pr); + + } + + } /* 315, 330 */ + +#endif /* SIS315H */ + + } + + } else { /* ============ TW: For 301 ================ */ + + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) { + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF0,0x0B); + SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 0); + } + } + + temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */ + if(SiS_BridgeInSlave(SiS_Pr)) { + tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20; + } + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,temp); + + SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */ + + if(HwDeviceExtension->jChipType >= SIS_315H) { + temp = SiS_GetReg1(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(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f); + } + SiS_VBLongWait(SiS_Pr); + + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) { + SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 1); + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF0,0x03); + } + } + + } + + } else { /* =================== TW: For LVDS ================== */ + + if(HwDeviceExtension->jChipType < SIS_315H) { + +#ifdef SIS300 /* 300 series */ + + if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) { + if(HwDeviceExtension->jChipType == SIS_730) { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 1); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 1); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 1); + } + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xFB); + if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwDeviceExtension))) { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 0); + } + } + + SiS_EnableCRT2(SiS_Pr); + SiS_DisplayOn(SiS_Pr); + SiS_UnLockCRT2(SiS_Pr,HwDeviceExtension, BaseAddr); + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF); + if(SiS_BridgeInSlave(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,BaseAddr,HwDeviceExtension))) { + SiS_SetCH700x(SiS_Pr,0x0B0E); + } + } + + if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) { + if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x40)) { + if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16) & 0x10)) { + if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwDeviceExtension))) { + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 1); + SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 1); + } + SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xF7); + } + } + } + +#endif /* SIS300 */ + + } else { + +#ifdef SIS315H /* 310/325 series */ + +#if 0 /* BIOS code makes no sense */ + if(SiS_IsVAMode()) { + if(SiS_IsLCDOrLCDA()) { + } + } +#endif + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) { + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xFB); + SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 0); + } + } + + SiS_EnableCRT2(SiS_Pr); + SiS_UnLockCRT2(SiS_Pr,HwDeviceExtension, BaseAddr); + + 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); + } + + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f); + + temp1 = SiS_GetReg1(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); + } + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20); + } + } else if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20); + } + + if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f); + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + + if(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_Chrontel701xOn(SiS_Pr,HwDeviceExtension, BaseAddr); + } + + if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_ChrontelDoSomething1(SiS_Pr,HwDeviceExtension, BaseAddr); + } else if(SiS_IsLCDOrLCDA(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_ChrontelDoSomething1(SiS_Pr,HwDeviceExtension, BaseAddr); + } + + } + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) { + if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) { + SiS_Chrontel701xBLOn(SiS_Pr); + SiS_ChrontelDoSomething4(SiS_Pr,HwDeviceExtension, BaseAddr); + } else if(SiS_IsLCDOrLCDA(SiS_Pr,HwDeviceExtension, BaseAddr)) { +/* if(!SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr)) { */ /* TW: makes no sense */ + SiS_Chrontel701xBLOn(SiS_Pr); + SiS_ChrontelDoSomething4(SiS_Pr,HwDeviceExtension, BaseAddr); +/* } */ + } + } + } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) { + if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) { + SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 1); + SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xF7); + } + } + } + +#endif /* SIS315H */ + + } /* 310 series */ + + } /* LVDS */ + +} + +void +SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; + + /* TW: Switch on LCD backlight on SiS30xLV */ + if( (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) || + (SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) ) { + if(!(SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02); + SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension); + } + if(!(SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01); + } + } +} + +void +SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress; + + /* TW: Switch off LCD backlight on SiS30xLV */ + if( (!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) || + (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xFE,0x00); + } + + if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) { + if(!(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension))) { + if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xFD,0x00); + } + } + } +} + +BOOLEAN +SiS_CR36BIOSWord23b(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT temp,temp1; + UCHAR *ROMAddr; + + if((ROMAddr = (UCHAR *)HwDeviceExtension->pjVirtualRomBase) && SiS_Pr->SiS_UseROM) { + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0xff; + temp >>= 4; + temp = 1 << temp; + temp1 = (ROMAddr[0x23c] << 8) | ROMAddr[0x23b]; + if(temp1 & temp) return(1); + else return(0); + } else { + return(0); + } +} + +BOOLEAN +SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT temp,temp1; + UCHAR *ROMAddr; + + if((ROMAddr = (UCHAR *)HwDeviceExtension->pjVirtualRomBase) && SiS_Pr->SiS_UseROM) { + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0xff; + temp >>= 4; + temp = 1 << temp; + temp1 = (ROMAddr[0x23e] << 8) | ROMAddr[0x23d]; + if(temp1 & temp) return(1); + else return(0); + } else { + return(0); + } +} + +void +SiS_SetPanelDelay(SiS_Private *SiS_Pr, UCHAR *ROMAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT DelayTime) +{ + USHORT PanelID, DelayIndex, Delay; +#ifdef SIS300 + USHORT temp; +#endif + + if(HwDeviceExtension->jChipType < SIS_315H) { + +#ifdef SIS300 + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* 300 series, LVDS */ + + PanelID = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36); + + 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((ROMAddr) && (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); + + } else { /* 300 series, 301(B) */ + + PanelID = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36); + temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x18); + if(!(temp & 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((ROMAddr) && (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 { + + if(HwDeviceExtension->jChipType == SIS_330) return; + +#ifdef SIS315H + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* 310/325 series, LVDS */ + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) { + PanelID = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36); + 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((ROMAddr) && (SiS_Pr->SiS_UseROM)) { + if(ROMAddr[0x13c] & 0x40) { + if(!(DelayTime & 0x01)) { + Delay = (USHORT)ROMAddr[0x17e]; + } else { + Delay = (USHORT)ROMAddr[0x17f]; + } + } + } + } + SiS_ShortDelay(SiS_Pr,Delay); + } + + } else { /* 310/325 series, 301(B) */ + + PanelID = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36); + DelayIndex = PanelID >> 4; + if(!(DelayTime & 0x01)) { + Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0]; + } else { + Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1]; + } + SiS_DDC2Delay(SiS_Pr, Delay * 4); + + } + +#endif /* SIS315H */ + + } + +} + +void +SiS_LongDelay(SiS_Private *SiS_Pr, USHORT delay) +{ + while(delay--) { + SiS_GenericDelay(SiS_Pr,0x19df); + } +} + +void +SiS_ShortDelay(SiS_Private *SiS_Pr, USHORT delay) +{ + while(delay--) { + SiS_GenericDelay(SiS_Pr,0x42); + } +} + +void +SiS_GenericDelay(SiS_Private *SiS_Pr, USHORT delay) +{ + USHORT temp,flag; + + flag = SiS_GetReg3(0x61) & 0x10; + + while(delay) { + temp = SiS_GetReg3(0x61) & 0x10; + if(temp == flag) continue; + flag = temp; + delay--; + } +} + +BOOLEAN +SiS_Is301B(SiS_Private *SiS_Pr, USHORT BaseAddr) +{ + USHORT flag; + + flag = SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x01); + if(flag >= 0x0B0) return(1); + else return(0); +} + +BOOLEAN +SiS_CRT2IsLCD(SiS_Private *SiS_Pr, USHORT BaseAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT flag; + + if(HwDeviceExtension->jChipType == SIS_730) { + flag = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13); + if(flag & 0x20) return(1); + } + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + if(flag & 0x20) return(1); + else return(0); +} + +BOOLEAN +SiS_IsDualEdge(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr) +{ +#ifdef SIS315H + USHORT flag; + + if(HwDeviceExtension->jChipType >= SIS_315H) { + if((HwDeviceExtension->jChipType != SIS_650) || (SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) { + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + if(flag & EnableDualEdge) return(1); + else return(0); + } else return(0); + } else +#endif + return(0); +} + +BOOLEAN +SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr) +{ +#ifdef SIS315H + USHORT flag; + + if(HwDeviceExtension->jChipType >= SIS_315H) { + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + if((flag & EnableDualEdge) && (flag & SetToLCDA)) return(1); +#if 0 /* Not done in 650/301LVx 1.10.6s, but in 650/301LV */ + else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(flag) return(1); + else return(0); + } +#endif + else + return(0); + } else +#endif + return(0); + } + +BOOLEAN +SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr) +{ +#ifdef SIS315H + USHORT flag; + + if(HwDeviceExtension->jChipType >= SIS_315H) { + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x79); + if(flag & 0x10) return(1); + else return(0); + } else +#endif + return(0); + } + +#if 0 +BOOLEAN +SiS_Is315E(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr) +{ +#ifdef SIS315H + USHORT flag; + + if(HwDeviceExtension->jChipType >= SIS_315H) { + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5f); + if(flag & 0x10) return(1); + else return(0); + } else +#endif + return(0); +} +#endif + +BOOLEAN +SiS_IsM650or651(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr) +{ +#ifdef SIS315H + USHORT flag; + + if(HwDeviceExtension->jChipType >= SIS_315H) { + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5f); + flag &= 0xF0; + if((flag == 0xb0) || (flag == 0x90)) return 0; + else return 1; + } else +#endif + return 1; +} + +BOOLEAN +SiS_IsYPbPr(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr) +{ +#ifdef SIS315H + USHORT flag; + + if(HwDeviceExtension->jChipType >= SIS_315H) { + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + if(flag & EnableLVDSHiVision) return(1); /* = YPrPb = 0x08 */ + else return(0); + } else +#endif + return(0); +} + +BOOLEAN +SiS_IsChScart(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr) +{ +#ifdef SIS315H + USHORT flag; + + if(HwDeviceExtension->jChipType >= SIS_315H) { + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + if(flag & EnableLVDSScart) return(1); /* = Scart = 0x04 */ + else return(0); + } else +#endif + return(0); +} + +BOOLEAN +SiS_IsTVOrYPbPrOrScart(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr) +{ + USHORT flag; + +#ifdef SIS315H + if(HwDeviceExtension->jChipType >= SIS_315H) { + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + if(flag & SetCRT2ToTV) return(1); + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + if(flag & EnableLVDSHiVision) return(1); /* = YPrPb = 0x08 */ + if(flag & EnableLVDSScart) return(1); /* = Scart = 0x04- TW inserted */ + else return(0); + } else +#endif + { + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + if(flag & SetCRT2ToTV) return(1); + } + return(0); +} + +BOOLEAN +SiS_IsLCDOrLCDA(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr) +{ + USHORT flag; + +#ifdef SIS315H + if(HwDeviceExtension->jChipType >= SIS_315H) { + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + if(flag & SetCRT2ToLCD) return(1); + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + if(flag & SetToLCDA) return(1); + else return(0); + } else +#endif + { + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + if(flag & SetCRT2ToLCD) return(1); + } + return(0); + +} + +BOOLEAN +SiS_IsDisableCRT2(SiS_Private *SiS_Pr, USHORT BaseAddr) +{ + USHORT flag; + + flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30); + if(flag & 0x20) return(0); + else return(1); +} + +BOOLEAN +SiS_BridgeIsOn(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT flag; + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + return(0); + } else { + flag = SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x00); + if((flag == 1) || (flag == 2)) return(0); + else return(1); + } +} + +BOOLEAN +SiS_BridgeIsEnable(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT flag; + + if(!(SiS_BridgeIsOn(SiS_Pr,BaseAddr,HwDeviceExtension))) { + flag = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00); + if(HwDeviceExtension->jChipType < SIS_315H) { + /* 300 series (630/301B 2.04.5a) */ + flag &= 0xa0; + if((flag == 0x80) || (flag == 0x20)) return 0; + else return 1; + } else { + /* 310/325 series (650/301LVx 1.10.6s) */ + flag &= 0x50; + if((flag == 0x40) || (flag == 0x10)) return 0; + else return 1; + } + } + return 1; +} + +BOOLEAN +SiS_BridgeInSlave(SiS_Private *SiS_Pr) +{ + USHORT flag1; + + flag1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31); + if(flag1 & (SetInSlaveMode >> 8)) return 1; + else return 0; +} + +/* TW: New from 650/301LV(x) 1.10.6s BIOS */ +void +SiS_SetHiVision(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ +#ifdef SIS315H + USHORT temp; +#endif + + /* Note: This variable is only used on 30x/B/LV systems. + CR38 has a different meaning on LVDS/CH7019 systems. + */ + + SiS_Pr->SiS_HiVision = 0; + if(HwDeviceExtension->jChipType >= SIS_315H) { +#ifdef SIS315H + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + /* TW: New from 650/301LVx BIOS 1.10.6s */ + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + if(temp & 0x04) { + temp &= 0x30; + switch(temp) { + case 0x00: SiS_Pr->SiS_HiVision = 4; break; + case 0x10: SiS_Pr->SiS_HiVision = 1; break; + case 0x20: SiS_Pr->SiS_HiVision = 2; break; + default: SiS_Pr->SiS_HiVision = 3; break; + } + } + } +#endif /* SIS315H */ + } +} + +/* TW: Checked against 630/LVDS 2.08, 650/LVDS and 650/301LV BIOS */ +BOOLEAN +SiS_GetLCDResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo, + USHORT ModeIdIndex, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT temp,modeflag,resinfo=0; + const unsigned char SiS300SeriesLCDRes[] = + { 0, 1, 2, 3, 7, 4, 5, 8, + 0, 0, 0, 0, 0, 0, 0, 0 }; + + SiS_Pr->SiS_LCDResInfo = 0; + SiS_Pr->SiS_LCDTypeInfo = 0; + SiS_Pr->SiS_LCDInfo = 0; + + 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; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + } + } + + if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return 0; + + if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2))) return 0; + + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36); + + /* FSTN: Fake CR36 (TypeInfo 2, ResInfo SiS_Panel320x480) */ + if(SiS_Pr->SiS_IF_DEF_FSTN) { + temp = 0x20 | SiS_Pr->SiS_Panel320x480; + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x36,temp); + } + + if(HwDeviceExtension->jChipType < SIS_315H) { + SiS_Pr->SiS_LCDTypeInfo = temp >> 4; + } else { + SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1; + } + temp &= 0x0f; + if(HwDeviceExtension->jChipType < SIS_315H) { + /* TW: Translate 300 series LCDRes to 310/325 series for unified usage */ + temp = SiS300SeriesLCDRes[temp]; + } + SiS_Pr->SiS_LCDResInfo = temp; + + if(SiS_Pr->SiS_IF_DEF_FSTN){ + SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_Panel320x480; + } + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + 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; + } + + if(SiS_Pr->SiS_LCDResInfo > SiS_Pr->SiS_PanelMax) + SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_Panel1024x768; + + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37); + if(SiS_Pr->SiS_IF_DEF_FSTN){ + /* TW: Fake LVDS bridge for FSTN */ + temp = 0x04; + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x37,temp); + } + SiS_Pr->SiS_LCDInfo = temp; + + /* TW: Inserted entire 315-block from 650/LVDS/301+LVx BIOSes */ + if(HwDeviceExtension->jChipType >= SIS_315H) { +#ifdef SIS315H + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + if(ModeNo == 0x3a || ModeNo == 0x4d || ModeNo == 0x65) { + SiS_Pr->SiS_LCDInfo |= LCDNonExpanding; + } + } + } + } + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x01) { + SiS_Pr->SiS_LCDInfo &= 0xFFEF; + SiS_Pr->SiS_LCDInfo |= LCDPass11; + } +#endif + } else { +#ifdef SIS300 + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if((ROMAddr) && SiS_Pr->SiS_UseROM) { + if(!(ROMAddr[0x235] & 0x02)) { + SiS_Pr->SiS_LCDInfo &= 0xEF; + } + } + } else { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if((SiS_Pr->SiS_SetFlag & CRT2IsVGA) && ((ModeNo == 0x03) || (ModeNo == 0x10))) { + SiS_Pr->SiS_LCDInfo &= 0xEF; + } + } + } +#endif + } + +#ifdef LINUX_KERNEL + 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 +#ifdef LINUX_XF86 + xf86DrvMsgVerb(0, X_PROBED, 3, + "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n", + SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo); +#endif + + /* TW: With Trumpion, always Expanding */ + if(SiS_Pr->SiS_IF_DEF_TRUMPION != 0){ + SiS_Pr->SiS_LCDInfo &= (~LCDNonExpanding); + } + + if(!((HwDeviceExtension->jChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & CRT2IsVGA))) { + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) { + if(ModeNo > 0x13) { + if(!(SiS_Pr->SiS_LCDInfo & LCDNonExpanding)) { + if((resinfo == 7) || (resinfo == 3)) { + SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; + } + } + } + } + if(SiS_Pr->SiS_LCDInfo & LCDPass11) { + SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; + } + } + + if(modeflag & HalfDCLK) { + if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) { + if(!(SiS_Pr->SiS_LCDInfo & LCDNonExpanding)) { + if(!(((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (HwDeviceExtension->jChipType < SIS_315H)) && + (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480))) { + if(ModeNo > 0x13) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) { + if(resinfo == 4) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; /* 512x384 */ + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) { + if(resinfo == 3) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; /* 400x300 */ + } + } + } else SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; + } else SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; + } else SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; + } + + } + + /* TW: wdr: if (VBInfo & LCD) && (VBInfo & (SetSimuScanMode | SwitchToCRT2)) { */ + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) { + SiS_Pr->SiS_SetFlag |= LCDVESATiming; + } + } else { + SiS_Pr->SiS_SetFlag |= LCDVESATiming; + } + +#ifdef SIS315H + /* TW: Inserted from 650/301LVx BIOS 1.10.6s */ + if(HwDeviceExtension->jChipType > SIS_315H) { + if(SiS_Pr->SiS_VBType & VB_SIS30xNEW) { + temp = 0x00; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) temp = 0x04; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x04; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) temp = 0x04; + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x39,temp); + } else if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x39,0x00); + } + } +#endif + + return 1; +} + +void +SiS_PresetScratchregister(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + return; + /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x30,0x21); */ + /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x31,0x41); */ + /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x32,0x28); */ + /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x33,0x22); */ + /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x35,0x43); */ + /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x36,0x01); */ + /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x37,0x00); */ +} + +void +SiS_LongWait(SiS_Private *SiS_Pr) +{ + USHORT i; + + i = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1F); + + if(!(i & 0xC0)) { + for(i=0; i<0xFFFF; i++) { + if(!(SiS_GetReg2(SiS_Pr->SiS_P3da) & 0x08)) + break; + } + for(i=0; i<0xFFFF; i++) { + if((SiS_GetReg2(SiS_Pr->SiS_P3da) & 0x08)) + break; + } + } +} + +void +SiS_VBLongWait(SiS_Private *SiS_Pr) +{ + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) { + SiS_VBWait(SiS_Pr); + } else { + SiS_LongWait(SiS_Pr); + } + return; +} + +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_GetReg2(SiS_Pr->SiS_P3da); + if(temp & 0x01) { + if((tempal & 0x08)) continue; + if(!(tempal & 0x08)) break; + } else { + if(!(tempal & 0x08)) continue; + if((tempal & 0x08)) break; + } + } + temp ^= 0x01; + } +} + +void +SiS_WaitVBRetrace(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + if(HwDeviceExtension->jChipType < SIS_315H) { +#ifdef SIS300 + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(!(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return; + } + if(!(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) { + SiS_WaitRetrace1(SiS_Pr,HwDeviceExtension); + } else { + SiS_WaitRetrace2(SiS_Pr,HwDeviceExtension); + } +#endif + } else { +#ifdef SIS315H + if(!(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) { + SiS_WaitRetrace1(SiS_Pr,HwDeviceExtension); + } else { + SiS_WaitRetrace2(SiS_Pr,HwDeviceExtension); + } +#endif + } +} + +void +SiS_WaitRetrace1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT watchdog; +#ifdef SIS300 + USHORT i; +#endif + + if(HwDeviceExtension->jChipType >= SIS_315H) { +#ifdef SIS315H + if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return; + watchdog = 65535; + while( (SiS_GetReg2(SiS_Pr->SiS_P3da) & 0x08) && --watchdog); + watchdog = 65535; + while( (!(SiS_GetReg2(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog); +#endif + } else { +#ifdef SIS300 +#if 0 /* TW: Not done in A901 BIOS */ + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return; + } +#endif + for(i=0; i<10; i++) { + watchdog = 65535; + while( (SiS_GetReg2(SiS_Pr->SiS_P3da) & 0x08) && --watchdog); + if(watchdog) break; + } + for(i=0; i<10; i++) { + watchdog = 65535; + while( (!(SiS_GetReg2(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog); + if(watchdog) break; + } +#endif + } +} + +void +SiS_WaitRetraceDDC(SiS_Private *SiS_Pr) +{ + USHORT watchdog; + + if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return; + watchdog = 65535; + while( (SiS_GetReg2(SiS_Pr->SiS_P3da) & 0x08) && --watchdog); + watchdog = 65535; + while( (!(SiS_GetReg2(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog); +} + +void +SiS_WaitRetrace2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT watchdog; +#ifdef SIS300 + USHORT i; +#endif + + if(HwDeviceExtension->jChipType >= SIS_315H) { +#ifdef SIS315H + watchdog = 65535; + while( (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x30) & 0x02) && --watchdog); + watchdog = 65535; + while( (!(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x30) & 0x02)) && --watchdog); +#endif + } else { +#ifdef SIS300 + for(i=0; i<10; i++) { + watchdog = 65535; + while( (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x25) & 0x02) && --watchdog); + if(watchdog) break; + } + for(i=0; i<10; i++) { + watchdog = 65535; + while( (!(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x25) & 0x02)) && --watchdog); + if(watchdog) break; + } +#endif + } +} + +/* =========== Set and Get register routines ========== */ + +void +SiS_SetRegANDOR(USHORT Port,USHORT Index,USHORT DataAND,USHORT DataOR) +{ + USHORT temp; + + temp = SiS_GetReg1(Port,Index); + temp = (temp & (DataAND)) | DataOR; + SiS_SetReg1(Port,Index,temp); +} + +void +SiS_SetRegAND(USHORT Port,USHORT Index,USHORT DataAND) +{ + USHORT temp; + + temp = SiS_GetReg1(Port,Index); + temp &= DataAND; + SiS_SetReg1(Port,Index,temp); +} + +void SiS_SetRegOR(USHORT Port,USHORT Index,USHORT DataOR) +{ + USHORT temp; + + temp = SiS_GetReg1(Port,Index); + temp |= DataOR; + SiS_SetReg1(Port,Index,temp); +} + +/* ========================================================= */ + +/* TW: Set 301 TV Encoder (and some LCD relevant) registers */ +void +SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr, USHORT ModeNo, + USHORT ModeIdIndex,USHORT RefreshRateTableIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT i, j, tempax, tempbx, tempcx, temp, temp1; + USHORT push1, push2; + const UCHAR *PhasePoint; + const UCHAR *TimingPoint; + const SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL; + USHORT modeflag, resinfo, crt2crtc, resindex, CRT2Index; + ULONG longtemp, tempeax, tempebx, temp2, tempecx; + const UCHAR atable[] = { + 0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02, + 0xab,0x87,0xab,0x9e,0xe7,0x02,0x02 + }; + + /* TW: Inserted from 650/301LV BIOS */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + /* TW: Inserted from 650/301LVx 1.10.6s: (Is at end of SetGroup2!) */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xfc,0x03); + temp = 1; + if(ModeNo <= 0x13) temp = 3; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x0b,temp); + } + } + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + if((ModeNo == 0x4a) || (ModeNo == 0x38)) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1c,0xa7); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1d,0x07); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1e,0xf2); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1f,0x6e); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x20,0x17); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x21,0x8b); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x22,0x73); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x23,0x53); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x24,0x13); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x25,0x40); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x26,0x34); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x27,0xf4); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x28,0x63); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x29,0xbb); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2a,0xcc); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2b,0x7a); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2c,0x58); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2d,0xe4); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2e,0x73); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,0xda); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x30,0x13); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x43,0x72); + } + } + } + } + return; + } + + if(ModeNo<=0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */ + resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; + crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */ + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + } + + tempcx = SiS_Pr->SiS_VBInfo; + tempax = (tempcx & 0x00FF) << 8; + tempbx = (tempcx & 0x00FF) | ((tempcx & 0x00FF) << 8); + tempbx &= 0x0410; + temp = (tempax & 0x0800) >> 8; + temp >>= 1; + temp |= (((tempbx & 0xFF00) >> 8) << 1); + temp |= ((tempbx & 0x00FF) >> 3); + temp ^= 0x0C; + + /* TW: From 1.10.7w (no vb check there) */ + if(SiS_Pr->SiS_VBType & (VB_SIS30xLV | VB_SIS30xNEW)) { + temp |= 0x0c; + } + + PhasePoint = SiS_Pr->SiS_PALPhase; + TimingPoint = SiS_Pr->SiS_PALTiming; +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) { /* PALPhase */ + temp ^= 0x01; + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + TimingPoint = SiS_Pr->SiS_HiTVSt2Timing; + if(SiS_Pr->SiS_SetFlag & TVSimuMode) { + if(modeflag & Charx8Dot) TimingPoint = SiS_Pr->SiS_HiTVSt1Timing; + else TimingPoint = SiS_Pr->SiS_HiTVTextTiming; + } + } else TimingPoint = SiS_Pr->SiS_HiTVExtTiming; + } else { +#endif + if(SiS_Pr->SiS_VBInfo & SetPALTV){ + + TimingPoint = SiS_Pr->SiS_PALTiming; + PhasePoint = SiS_Pr->SiS_PALPhase; + + if( (SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS302B)) && + ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || + (SiS_Pr->SiS_SetFlag & TVSimuMode) ) ) { + PhasePoint = SiS_Pr->SiS_PALPhase2; + } + + } else { + + temp |= 0x10; + TimingPoint = SiS_Pr->SiS_NTSCTiming; + PhasePoint = SiS_Pr->SiS_NTSCPhase; + + if( (SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS302B)) && + ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || + (SiS_Pr->SiS_SetFlag & TVSimuMode) ) ) { + PhasePoint = SiS_Pr->SiS_NTSCPhase2; + } + + } +#ifdef oldHV + } +#endif + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x00,temp); + + temp = 0; + if((HwDeviceExtension->jChipType == SIS_630)|| + (HwDeviceExtension->jChipType == SIS_730)) { + temp = 0x35; + } + if(HwDeviceExtension->jChipType >= SIS_315H) { + temp = 0x38; + } + if(temp) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x01) { + temp1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,temp); + if(temp1 & EnablePALM) { /* 0x40 */ + PhasePoint = SiS_Pr->SiS_PALMPhase; + if( (SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS302B)) && + ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || + (SiS_Pr->SiS_SetFlag & TVSimuMode) ) ) { + PhasePoint = SiS_Pr->SiS_PALMPhase2; + } + } + if(temp1 & EnablePALN) { /* 0x80 */ + PhasePoint = SiS_Pr->SiS_PALNPhase; + if( (SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS302B)) && + ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || + (SiS_Pr->SiS_SetFlag & TVSimuMode) ) ) { + PhasePoint = SiS_Pr->SiS_PALNPhase2; + } + } + } + } + } + +#ifdef SIS315H + /* TW: Inserted from 650/301LV BIOS */ + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* 650/301LV : 301LV | 302LV */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + if((ModeNo == 0x4a) || (ModeNo == 0x38)) { + PhasePoint = SiS_Pr->SiS_SpecialPhase; + } + } + } + } + } +#endif + + for(i=0x31, j=0; i<=0x34; i++, j++){ + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,PhasePoint[j]); + } + + for(i=0x01, j=0; i<=0x2D; i++, j++){ + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]); + } + for(i=0x39; i<=0x45; i++, j++){ + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]); + } + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(!(SiS_Pr->SiS_ModeType & 0x07)) + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F); + } else { + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F); + } + } + + SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode); + + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x35,SiS_Pr->SiS_RY1COE); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x36,SiS_Pr->SiS_RY2COE); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE); + +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) tempax = 950; + else { +#endif + if(SiS_Pr->SiS_VBInfo & SetPALTV) tempax = 520; + else tempax = 440; +#ifdef oldHV + } +#endif + + if( ( ( (!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_HiVision == 3) ) && (SiS_Pr->SiS_VDE <= tempax) ) || + ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (SiS_Pr->SiS_HiVision != 3) && + ( (SiS_Pr->SiS_VGAHDE == 1024) || ((SiS_Pr->SiS_VGAHDE != 1024) && (SiS_Pr->SiS_VDE <= tempax)) ) ) ) { + + tempax -= SiS_Pr->SiS_VDE; + tempax >>= 2; + tempax = (tempax & 0x00FF) | ((tempax & 0x00FF) << 8); + + temp = (tempax & 0xFF00) >> 8; + temp += (USHORT)TimingPoint[0]; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,temp); + + temp = (tempax & 0xFF00) >> 8; + temp += (USHORT)TimingPoint[1]; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,temp); + + if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToTV - SetCRT2ToHiVisionTV)) && + (SiS_Pr->SiS_HiVision != 3) && + (SiS_Pr->SiS_VGAHDE >= 1024) ) { + if(SiS_Pr->SiS_VBInfo & SetPALTV) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x19); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x52); + } else { + if(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x17); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x1d); + } else { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x0b); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x11); + } + } + } + + } + + tempcx = SiS_Pr->SiS_HT; + + /* TW: Inserted from 650/301LVx 1.10.6s */ + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) { + tempcx >>= 1; + } + } + + tempcx--; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + tempcx--; + } + temp = tempcx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1B,temp); + temp = (tempcx & 0xFF00) >> 8; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,temp); + + tempcx++; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + tempcx++; + } + tempcx >>= 1; + + push1 = tempcx; + + tempcx += 7; +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) tempcx -= 4; +#endif + temp = (tempcx & 0x00FF) << 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,temp); + + tempbx = TimingPoint[j] | ((TimingPoint[j+1]) << 8); + tempbx += tempcx; + + push2 = tempbx; + + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x24,temp); + temp = ((tempbx & 0xFF00) >> 8) << 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,temp); + + tempbx = push2; + + tempbx += 8; +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) { + tempbx -= 4; + tempcx = tempbx; + } +#endif + temp = (tempbx & 0x00FF) << 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,temp); + + j += 2; + tempcx += ((TimingPoint[j] | ((TimingPoint[j+1]) << 8))); + temp = tempcx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x27,temp); + temp = ((tempcx & 0xFF00) >> 8) << 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,temp); + + tempcx += 8; +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) tempcx -= 4; +#endif + temp = (tempcx & 0x00FF) << 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,temp); + + tempcx = push1; + + j += 2; + tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8)); + temp = (tempcx & 0x00FF) << 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,temp); + + tempcx -= 11; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) { + tempax = SiS_GetVGAHT2(SiS_Pr) - 1; + tempcx = tempax; + } + temp = tempcx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2E,temp); + + tempbx = SiS_Pr->SiS_VDE; + if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746; + if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746; + if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853; + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempbx >>= 1; + } else { + if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (!(SiS_Pr->SiS_HiVision & 0x03))) { + tempbx >>= 1; + if(SiS_Pr->SiS_SetFlag & TVSimuMode) { + if(ModeNo <= 0x13) { + if(crt2crtc == 1) { + tempbx++; + } + } + } else { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(crt2crtc == 4) /* TW: BIOS calls GetRatePtrCRT2 here - does not make sense */ + if(SiS_Pr->SiS_ModeType <= 3) tempbx++; + } + } + } + } + tempbx -= 2; + temp = tempbx & 0x00FF; +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(ModeNo == 0x2f) temp++; + } + } +#endif + /* TW: From 1.10.7w - doesn't make sense */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) { /* SetFlag?? */ + if(ModeNo == 0x03) temp++; + } + } + } + } + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2F,temp); + + tempax = (tempcx & 0xFF00) | (tempax & 0x00FF); + tempbx = ((tempbx & 0xFF00) << 6) | (tempbx & 0x00FF); + tempax |= (tempbx & 0xFF00); +#ifdef oldHV + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV)) { +#endif + if(HwDeviceExtension->jChipType < SIS_315H) { + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)) { /* TW: New from 630/301B (II) BIOS */ + tempax |= 0x1000; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) tempax |= 0x2000; + } + } else { + tempax |= 0x1000; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) tempax |= 0x2000; + } +#ifdef oldHV + } +#endif + temp = (tempax & 0xFF00) >> 8; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x30,temp); + + /* TW: Inserted from 650/301LVx 1.10.6s */ + if(HwDeviceExtension->jChipType > SIS_315H) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) || + (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) ) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x10,0x60); + } + } + } + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* tv gatingno */ + tempbx = SiS_Pr->SiS_VDE; + if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (!(SiS_Pr->SiS_HiVision & 0x03))) { + tempbx >>= 1; + } + tempbx -= 3; + tempbx &= 0x03ff; + temp = ((tempbx & 0xFF00) >> 8) << 5; + temp |= 0x18; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x46,temp); + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x47,temp); + if(HwDeviceExtension->jChipType >= SIS_315H) { /* TW: Inserted from 650/301LVx 1.10.6s */ + tempax = 0; + if(SiS_Pr->SiS_HiVision & 0x07) { + if(SiS_Pr->SiS_HiVision & 0x04) tempax = 0x1000; + else if(SiS_Pr->SiS_HiVision & 0x01) tempax = 0x3000; + else tempax = 0x5000; + } + temp = (tempax & 0xFF00) >> 8; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x4d,temp); + } + } + + tempbx &= 0x00FF; + if(!(modeflag & HalfDCLK)) { + tempcx = SiS_Pr->SiS_VGAHDE; + if(tempcx >= SiS_Pr->SiS_HDE) { + tempbx |= 0x2000; + tempax &= 0x00FF; + } + } + + tempcx = 0x0101; +/*if(SiS_Pr->SiS_VBInfo & (SetPALTV | SetCRT2ToTV)) { */ /*301b- TW: BIOS BUG? */ + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV - SetCRT2ToHiVisionTV)) { + if(!(SiS_Pr->SiS_HiVision & 0x03)) { + if(SiS_Pr->SiS_VGAHDE >= 1024) { + if((!(modeflag & HalfDCLK)) || + (HwDeviceExtension->jChipType < SIS_315H)) { /* TW: This check not in 630/301B */ + tempcx = 0x1920; + if(SiS_Pr->SiS_VGAHDE >= 1280) { + tempcx = 0x1420; + tempbx &= 0xDFFF; + } + } + } + } + } + + if(!(tempbx & 0x2000)){ + if(modeflag & HalfDCLK) { + tempcx = (tempcx & 0xFF00) | (((tempcx & 0x00FF) << 1) & 0xff); + } + push1 = tempbx; + tempeax = SiS_Pr->SiS_VGAHDE; + tempebx = (tempcx & 0xFF00) >> 8; + longtemp = tempeax * tempebx; + tempecx = tempcx & 0x00FF; + longtemp /= tempecx; + longtemp <<= 0x0d; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + longtemp <<= 3; + } + tempecx = SiS_Pr->SiS_HDE; + temp2 = longtemp % tempecx; + tempeax = longtemp / tempecx; + if(temp2 != 0) tempeax++; + tempax = (USHORT)tempeax; + tempbx = push1; + tempcx = (tempcx & 0xff00) | (((tempax & 0xFF00) >> 8) >> 5); + tempbx |= (tempax & 0x1F00); + tempax = ((tempax & 0x00FF) << 8) | (tempax & 0x00FF); + } + + temp = (tempax & 0xFF00) >> 8; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x44,temp); + temp = (tempbx & 0xFF00) >> 8; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,temp); + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + temp = tempcx & 0x00FF; + if(tempbx & 0x2000) temp = 0; + temp |= 0x18; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xE0,temp); + if(SiS_Pr->SiS_VBInfo & SetPALTV) { + tempbx = 0x0382; /* TW: BIOS; Was 0x0364; */ + tempcx = 0x007e; /* TW: BIOS; Was 0x009c; */ + } else { + tempbx = 0x0369; /* TW: BIOS; Was 0x0346; */ + tempcx = 0x0061; /* TW: BIOS; Was 0x0078; */ + } + temp = (tempbx & 0x00FF) ; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x4B,temp); + temp = (tempcx & 0x00FF) ; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x4C,temp); + tempbx &= 0x03FF; + temp = (tempcx & 0xFF00) >> 8; + temp = (temp & 0x0003) << 2; + temp |= (tempbx >> 8); + if(HwDeviceExtension->jChipType < SIS_315H) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x4D,temp); + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4D,0xF0,temp); + } + + temp = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x43); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x43,(USHORT)(temp - 3)); + } + + temp = 0; + if((HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730)) { + temp = 0x35; + } else if(HwDeviceExtension->jChipType >= SIS_315H) { + temp = 0x38; + } + if(temp) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x01) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,temp) & EnablePALM) { /* 0x40 */ + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF); + temp = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x01); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,temp - 1); + } + } + } + } + + +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) { + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x0B,0x00); + } + } +#endif + + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + SiS_Set300Part2Regs(SiS_Pr, HwDeviceExtension, ModeIdIndex, + RefreshRateTableIndex, BaseAddr, ModeNo); + return; + } + } else { + /* TW: !!! The following is a duplicate, done for LCDA as well (see above) */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* 650/301LV: (VB_SIS301LV | VB_SIS302LV)) */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + if((ModeNo == 0x4a) || (ModeNo == 0x38)) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1c,0xa7); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1d,0x07); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1e,0xf2); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1f,0x6e); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x20,0x17); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x21,0x8b); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x22,0x73); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x23,0x53); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x24,0x13); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x25,0x40); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x26,0x34); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x27,0xf4); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x28,0x63); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x29,0xbb); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2a,0xcc); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2b,0x7a); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2c,0x58); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2d,0xe4); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2e,0x73); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,0xda); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x30,0x13); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x43,0x72); + } + } + } + } + return; + } + } + + /* TW: From here: Part2 LCD setup */ + + tempbx = SiS_Pr->SiS_HDE; + /* TW: Inserted from 650/301LVx 1.10.6s */ + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) tempbx >>= 1; + } + tempbx--; /* RHACTE=HDE-1 */ + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2C,temp); + temp = (tempbx & 0xFF00) >> 8; + temp <<= 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,temp); + + temp = 0x01; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) { + if(SiS_Pr->SiS_ModeType == ModeEGA) { + if(SiS_Pr->SiS_VGAHDE >= 1024) { + temp = 0x02; + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_SetFlag & LCDVESATiming) { + temp = 0x01; + } + } + } + } + } + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x0B,temp); + + tempbx = SiS_Pr->SiS_VDE; /* RTVACTEO=(VDE-1)&0xFF */ + push1 = tempbx; + + tempbx--; + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x03,temp); + temp = ((tempbx & 0xFF00) >> 8) & 0x07; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,temp); + + tempcx = SiS_Pr->SiS_VT; + push2 = tempcx; + + tempcx--; + temp = tempcx & 0x00FF; /* RVTVT=VT-1 */ + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x19,temp); + + temp = (tempcx & 0xFF00) >> 8; + temp <<= 5; + if((HwDeviceExtension->jChipType == SIS_300) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) { + if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp |= 0x10; + } else if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp |= 0x10; + else { + if(SiS_Pr->SiS_LCDInfo & LCDSync) /* TW: 630/301 BIOS checks this */ + temp |= 0x10; + } + } else { + if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { + /* TW: Inserted from 630/301LVx 1.10.6s */ + if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) { + if(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x01) { + temp |= 0x10; + } + } + } else { + temp |= 0x10; + } + } + + /* 630/301 does not do all this */ + if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) { + if((HwDeviceExtension->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) { + /* TW: Inserted from 650/301LVx 1.10.6s */ + temp |= (SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37) >> 6); + temp |= 0x08; /* From 1.10.7w */ + if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) temp |= 0x04; /* From 1.10.7w */ + } else { + tempbx = (tempbx & 0xFF00) | (SiS_Pr->SiS_LCDInfo & 0x0FF); + if(tempbx & LCDSync) { + tempbx &= (0xFF00 | LCDSyncBit); + tempbx = (tempbx & 0xFF00) | ((tempbx & 0x00FF) >> LCDSyncShift); + temp |= (tempbx & 0x00FF); + } + } + } + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1A,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); + + /* 1280x960, 1280x1024 and 1600x1200 data invalid/missing in tables, use old calculation */ + if((HwDeviceExtension->jChipType >= SIS_315H) && + (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && + (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024) && + (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200) && + (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x960)) { + /* ------------- 310 series ------------ */ + + /* TW: Inserted this entire section from 650/301LV(x) BIOS */ + + SiS_GetCRT2Part2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + &CRT2Index,&resindex); + + switch(CRT2Index) { + case Panel_1024x768 : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1; break; /* "Normal" */ + case Panel_1280x1024 : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1280x1024_1; break; + case Panel_1400x1050 : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1400x1050_1; break; + case Panel_1600x1200 : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1600x1200_1; break; + case Panel_1024x768 + 16 : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2; break; /* Non-Expanding */ + case Panel_1280x1024 + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1280x1024_2; break; + case Panel_1400x1050 + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1400x1050_2; break; + case Panel_1600x1200 + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1600x1200_2; break; + case Panel_1024x768 + 32 : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3; break; /* VESA Timing */ + case Panel_1280x1024 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1280x1024_3; break; + case Panel_1400x1050 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1400x1050_3; break; + case Panel_1600x1200 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1600x1200_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_SetReg1(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]); + } + for(j = 0x1c; j <= 0x1d; i++, j++ ) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]); + } + for(j = 0x1f; j <= 0x21; i++, j++ ) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]); + } + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]); + + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) { + if(SiS_Pr->SiS_VGAVDE == 0x20d) { + temp = 0xc3; + if(SiS_Pr->SiS_ModeType <= ModeVGA) { + temp++; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2; + } + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,temp); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x30,0xb3); + } + if(SiS_Pr->SiS_VGAVDE == 0x1a4) { + temp = 0x4d; + if(SiS_Pr->SiS_ModeType <= ModeVGA) { + temp++; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++; + } + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,temp); + } + } + + /* TW: Inserted from 650/301LVx 1.10.6s: */ + /* !!! This is a duplicate, done for LCDA as well - see above */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xfc,0x03); /* Not done in 1.10.7w */ + temp = 1; + if(ModeNo <= 0x13) temp = 3; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x0b,temp); + } + } + + } else { /* ------------- 300 series (and other LCD resolutions) ----------- */ + + tempcx++; + tempbx = 768; + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1024x768) { + tempbx = 1024; + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024) { + tempbx = 1200; + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200) { + if(tempbx != SiS_Pr->SiS_VDE) { + tempbx = 960; + } + } + } + } + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) { + tempbx = SiS_Pr->SiS_VDE - 1; + tempcx--; + } + tempax = 1; + if(!(SiS_Pr->SiS_LCDInfo & LCDNonExpanding)) { + if(tempbx != SiS_Pr->SiS_VDE){ + tempax = tempbx; + if(tempax < SiS_Pr->SiS_VDE) { + tempax = 0; + tempcx = 0; + } else { + tempax -= SiS_Pr->SiS_VDE; + } + tempax >>= 1; + } + tempcx -= tempax; /* lcdvdes */ + tempbx -= tempax; /* lcdvdee */ + } else { + tempax >>= 1; + tempcx -= tempax; /* lcdvdes */ + tempbx -= tempax; /* lcdvdee */ + } + + temp = tempcx & 0x00FF; /* RVEQ1EQ=lcdvdes */ + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x05,temp); + temp = tempbx & 0x00FF; /* RVEQ2EQ=lcdvdee */ + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x06,temp); + + temp = ((tempbx & 0xFF00) >> 8 ) << 3; + temp |= ((tempcx & 0xFF00) >> 8); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,temp); + + tempbx = push2; + tempax = push1; + tempcx = tempbx; + tempcx -= tempax; + tempcx >>= 4; + tempbx += tempax; + tempbx >>= 1; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx -= 10; + + temp = tempbx & 0x00FF; /* RTVACTEE=lcdvrs */ + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x04,temp); + + temp = ((tempbx & 0xFF00) >> 8) << 4; + tempbx += (tempcx + 1); + temp |= (tempbx & 0x000F); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,temp); + + /* TW: Code from 630/301B (I+II) BIOS */ + + if( ( ( (HwDeviceExtension->jChipType == SIS_630) || + (HwDeviceExtension->jChipType == SIS_730) ) && + (HwDeviceExtension->jChipRevision > 2) ) && + (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) && + (!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) && + (!(SiS_Pr->SiS_LCDInfo & LCDNonExpanding)) ) { + if(ModeNo == 0x13) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x04,0xB9); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x05,0xCC); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x06,0xA6); + } else { + if((crt2crtc & 0x3F) == 4) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x2B); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x13); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x04,0xE5); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x05,0x08); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x06,0xE2); + } + } + } + + /* TW: Inserted missing code from 630/301B BIOS: (II: 3258) */ + + 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_SetReg1(SiS_Pr->SiS_Part2Port,0x06,0xff); + } + + if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) { + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(crt2crtc == 4) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x28); + } + } + } + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x18); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]); + } + + tempcx = (SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE) >> 2; /* (HT-HDE)>>2 */ + tempbx = SiS_Pr->SiS_HDE + 7; /* lcdhdee */ + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + tempbx += 2; + } + push1 = tempbx; + temp = tempbx & 0x00FF; /* RHEQPLE=lcdhdee */ + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x23,temp); + temp = (tempbx & 0xFF00) >> 8; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,temp); + + temp = 7; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + temp += 2; + } + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1F,temp); /* RHBLKE=lcdhdes */ + + SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x20,0x0F); + + tempbx += tempcx; + push2 = tempbx; + temp = tempbx & 0xFF; /* RHBURSTS=lcdhrs */ + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) { + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) { + if(SiS_Pr->SiS_HDE == 1280) temp = 0x47; + } + } + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1C,temp); + temp = ((tempbx & 0xFF00) >> 8) << 4; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,temp); + + tempbx = push2; + tempcx <<= 1; + tempbx += tempcx; + temp = tempbx & 0x00FF; /* RHSYEXP2S=lcdhre */ + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x21,temp); + + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) { + if(SiS_Pr->SiS_VGAVDE == 525) { + if(SiS_Pr->SiS_ModeType <= ModeVGA) + temp=0xC6; + else + temp=0xC3; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,temp); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x30,0xB3); + } else if(SiS_Pr->SiS_VGAVDE == 420) { + if(SiS_Pr->SiS_ModeType <= ModeVGA) + temp=0x4F; + else + temp=0x4D; /* 650: 4e */ + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,temp); + } + } + SiS_Set300Part2Regs(SiS_Pr, HwDeviceExtension, ModeIdIndex, + RefreshRateTableIndex, BaseAddr, ModeNo); + + } /* HwDeviceExtension */ +} + +USHORT +SiS_GetVGAHT2(SiS_Private *SiS_Pr) +{ + ULONG tempax,tempbx; + + tempbx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX) & 0xFFFF; + tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT; + tempax = (tempax * SiS_Pr->SiS_HT) / tempbx; + return((USHORT) tempax); +} + +/* TW: New from 300/301LV BIOS 1.16.51. Seems highly preliminary. */ +void +SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT ModeIdIndex, USHORT RefreshRateTableIndex, + USHORT BaseAddr, USHORT ModeNo) +{ + USHORT crt2crtc, resindex; + int i,j; + const SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL; + + if(HwDeviceExtension->jChipType != SIS_300) return; + if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) 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; + + /* TW: The BIOS code (1.16.51) 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_SetReg1(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]); + } + for(j = 0x1c; j <= 0x1d; i++, j++ ) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]); + } + for(j = 0x1f; j <= 0x21; i++, j++ ) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]); + } + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]); + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]); +} + +/* TW: Set 301 Macrovision(tm) registers */ +/* TW: Double-Checked against 650/301LV, 650/301LVx and 630/301B BIOS */ +void +SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + USHORT ModeIdIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT temp; +#ifdef oldHV + USHORT i; + const UCHAR *tempdi; +#endif + USHORT modeflag; + + /* TW: Inserted from 650/301LVx 1.10.6s, 1.10.7w */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return; + + if(ModeNo<=0x13) + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; + else + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + + SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x00,0x00); + + if(SiS_Pr->SiS_VBInfo & SetPALTV) { + SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x13,0xFA); + SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x14,0xC8); + } else { + if(HwDeviceExtension->jChipType >= SIS_315H) { + SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x13,0xF5); + SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x14,0xB7); + } else { + SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x13,0xF6); + SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x14,0xBf); + } + } + + temp = 0; + if((HwDeviceExtension->jChipType == SIS_630)|| + (HwDeviceExtension->jChipType == SIS_730)) { + temp = 0x35; + } else if(HwDeviceExtension->jChipType >= SIS_315H) { + temp = 0x38; + } + if(temp) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x01) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,temp) & EnablePALM){ /* 0x40 */ + SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x13,0xFA); + SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x14,0xC8); + SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x3D,0xA8); + } + } + } + } + +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) { + tempdi = SiS_Pr->SiS_HiTVGroup3Data; + if(SiS_Pr->SiS_SetFlag & TVSimuMode) { + tempdi = SiS_Pr->SiS_HiTVGroup3Simu; + if(!(modeflag & Charx8Dot)) { + tempdi = SiS_Pr->SiS_HiTVGroup3Text; + } + } + for(i=0; i<=0x3E; i++){ + SiS_SetReg1(SiS_Pr->SiS_Part3Port,i,tempdi[i]); + } + } +#endif + + return; +} + +/* TW: Set 301 VGA2 registers */ +/* TW: Double-Checked against 650/301LV(x) and 630/301B BIOS */ +void +SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + USHORT ModeIdIndex,USHORT RefreshRateTableIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT tempax,tempcx,tempbx,modeflag,temp,temp2,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 { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; + resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; + } + + /* TW: From 650/301LVx 1.10.6s BIOS */ + if(SiS_Pr->SiS_VBType & (VB_SIS30xLV | VB_SIS30xNEW)) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x24,0x0e); + } + } + + if(SiS_Pr->SiS_VBType & VB_SIS30xNEW) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f); + } + } + + /* TW: From 650/301LV BIOS (any, incl. 1.10.6s, 1.10.7w) */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + /* TW: This is a duplicate; done at the end, too */ + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c); + } + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x2a,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10); + return; + } + + temp = SiS_Pr->SiS_RVBHCFACT; + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x13,temp); + + tempbx = SiS_Pr->SiS_RVBHCMAX; + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x14,temp); + + temp2 = (((tempbx & 0xFF00) >> 8) << 7) & 0x00ff; + + tempcx = SiS_Pr->SiS_VGAHT - 1; + temp = tempcx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x16,temp); + + temp = (((tempcx & 0xFF00) >> 8) << 3) & 0x00ff; + temp2 |= temp; + + tempcx = SiS_Pr->SiS_VGAVT - 1; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5; + + temp = tempcx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x17,temp); + + temp = temp2 | ((tempcx & 0xFF00) >> 8); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x15,temp); + + tempcx = SiS_Pr->SiS_VBInfo; + tempbx = SiS_Pr->SiS_VGAHDE; + if(modeflag & HalfDCLK) tempbx >>= 1; + + /* TW: New for 650/301LV and 630/301B */ + temp = 0xA0; +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) { + temp = 0; + if(tempbx > 800) { + temp = 0xA0; + if(tempbx != 1024) { + temp = 0xC0; + if(tempbx != 1280) temp = 0; + } + } + } else +#endif + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(tempbx <= 800) { + temp = 0x80; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD){ + temp = 0; + if(tempbx > 800) temp = 0x60; + } + } + } else { + temp = 0x80; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD){ + temp = 0; + if(tempbx > 800) temp = 0x60; + } + } + if(SiS_Pr->SiS_HiVision & 0x03) { + temp = 0; + if(SiS_Pr->SiS_VGAHDE == 1024) temp = 0x20; + } + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) temp = 0; + } + + if(SiS_Pr->SiS_VBType & VB_SIS301) { + if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024) + temp |= 0x0A; + } + + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp); + + tempebx = SiS_Pr->SiS_VDE; + +#ifdef oldHV + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) { + if(!(temp & 0xE0)) tempebx >>=1; + } +#endif + + tempcx = SiS_Pr->SiS_RVBHRS; + temp = tempcx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x18,temp); + + tempeax = SiS_Pr->SiS_VGAVDE; + tempcx |= 0x4000; + if(tempeax <= tempebx){ + tempcx ^= 0x4000; + } else { + tempeax -= tempebx; + } + + templong = (tempeax * 256 * 1024) % tempebx; + tempeax = (tempeax * 256 * 1024) / tempebx; + tempebx = tempeax; + if(templong != 0) tempebx++; + + temp = (USHORT)(tempebx & 0x000000FF); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x1B,temp); + temp = (USHORT)((tempebx & 0x0000FF00) >> 8); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x1A,temp); + + tempbx = (USHORT)(tempebx >> 16); + temp = tempbx & 0x00FF; + temp <<= 4; + temp |= ((tempcx & 0xFF00) >> 8); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x19,temp); + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x1C,0x28); + tempbx = 0; + tempax = SiS_Pr->SiS_VGAHDE; + if(modeflag & HalfDCLK) tempax >>= 1; + if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) || (SiS_Pr->SiS_HiVision & 0x03)) { + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) tempax >>= 1; + else if(tempax > 800) tempax -= 800; + } else { + if(tempax > 800) tempax -= 800; + } + } + +/* if((SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetPALTV)) && (!(SiS_Pr->SiS_HiVision & 0x03))) { */ + if((SiS_Pr->SiS_VBInfo & (SetCRT2ToTV - SetCRT2ToHiVisionTV)) && (!(SiS_Pr->SiS_HiVision & 0x03))) { + if(tempax > 800) { + tempbx = 8; + if(tempax == 1024) + tempax *= 25; + else + tempax *= 20; + + temp = tempax % 32; + tempax /= 32; + tempax--; + if (temp!=0) tempax++; + } + } + tempax--; + temp = (tempax & 0xFF00) >> 8; + temp &= 0x03; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* From 1.10.7w */ + if(ModeNo > 0x13) { /* From 1.10.7w */ + if(resinfo == 8) tempax = 0x1f; /* From 1.10.7w */ + } /* From 1.10.7w */ + } /* From 1.10.7w */ + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x1D,tempax & 0x00FF); + temp <<= 4; + temp |= tempbx; + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x1E,temp); + + if(HwDeviceExtension->jChipType > SIS_315H) { + temp = 0x0026; /* From 1.10.7w; 1.10.6s: 0x0036 */ + } else { + temp = 0x0036; + } + if((SiS_Pr->SiS_VBInfo & (SetCRT2ToTV - SetCRT2ToHiVisionTV)) && + (!(SiS_Pr->SiS_HiVision & 0x03))) { + temp |= 0x01; + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { + if(!(SiS_Pr->SiS_SetFlag & TVSimuMode)) + temp &= 0xFE; + } + } + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0,temp); + + tempbx = SiS_Pr->SiS_HT; + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) tempbx >>= 1; + } + tempbx >>= 1; + tempbx -= 2; + temp = ((tempbx & 0x0700) >> 8) << 3; + SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp); + temp = tempbx & 0x00FF; + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x22,temp); + if( (SiS_Pr->SiS_VBType & (VB_SIS30xLV | VB_SIS30xNEW)) && + (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ) { + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x24,0x0e); + } + + /* TW: 650 BIOS does this for all bridge types - assumingly wrong */ + if(HwDeviceExtension->jChipType >= SIS_315H) { + /* TW: This is a duplicate; done for LCDA as well (see above) */ + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) { + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c); + } + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x2a,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10); + } else if(HwDeviceExtension->jChipType == SIS_300) { + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x2a,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10); + } + + } /* 301B */ + + SiS_SetCRT2VCLK(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); +} + +/* TW: Double-Checked against 650/301LV(x) and 630/301B BIOS */ +void +SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT vclkindex; + USHORT tempah; + + vclkindex = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + HwDeviceExtension); + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + tempah = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A; + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0A,tempah); + tempah = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B; + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0B,tempah); + /* TW: New from 650/301LV, LVx BIOS (300/301LV does not do this) */ + if(HwDeviceExtension->jChipType >= SIS_315H) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* 650/301LV: (VB_SIS301LV | VB_SIS302LV)) */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { + if((ModeNo == 0x4a) || (ModeNo == 0x38)) { + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0a,0x57); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0b,0x46); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x1f,0xf6); + } + } + } + } + } + } else { /* 650/301LVx does not do this anymore, jumps to SetRegs above - BUG? */ + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0A,0x01); + tempah = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B; + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0B,tempah); + tempah = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A; + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0A,tempah); + } + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x12,0x00); + tempah = 0x08; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { + tempah |= 0x20; + } + SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,tempah); +} + +/* TW: Double-checked against 650/LVDS (1.10.07), 630/301B/LVDS/LVDS+CH, 650/301LVx (1.10.6s) BIOS */ +USHORT +SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT tempbx; +#ifdef SIS300 + const USHORT LCDXlat1VCLK300[4] = {VCLK65, VCLK65, VCLK65, VCLK65}; + const USHORT LCDXlat2VCLK300[4] = {VCLK108_2,VCLK108_2,VCLK108_2,VCLK108_2}; + const USHORT LVDSXlat2VCLK300[4]= {VCLK65, VCLK65, VCLK65, VCLK65}; + const USHORT LVDSXlat3VCLK300[4]= {VCLK65, VCLK65, VCLK65, VCLK65}; +#endif +#ifdef SIS315H + const USHORT LCDXlat1VCLK310[4] = {VCLK65+2, VCLK65+2, VCLK65+2, VCLK65+2}; + const USHORT LCDXlat2VCLK310[4] = {VCLK108_2+5,VCLK108_2+5,VCLK108_2+5,VCLK108_2+5}; + const USHORT LVDSXlat2VCLK310[4]= {VCLK65+2, VCLK65+2, VCLK65+2, VCLK65+2}; + const USHORT LVDSXlat3VCLK310[4]= {VCLK108_2+5,VCLK108_2+5,VCLK108_2+5,VCLK108_2+5}; + /* {VCLK65+2, VCLK65+2, VCLK65+2, VCLK65+2}; - 650/LVDS 1.10.07 */ +#endif + const USHORT LCDXlat0VCLK[4] = {VCLK40, VCLK40, VCLK40, VCLK40}; + const USHORT LVDSXlat1VCLK[4] = {VCLK40, VCLK40, VCLK40, VCLK40}; + USHORT CRT2Index,VCLKIndex=0; + USHORT modeflag,resinfo; + const UCHAR *CHTVVCLKPtr=NULL; + const USHORT *LCDXlatVCLK1 = NULL; + const USHORT *LCDXlatVCLK2 = NULL; + const USHORT *LVDSXlatVCLK2 = NULL; + const USHORT *LVDSXlatVCLK3 = NULL; + + if(HwDeviceExtension->jChipType >= SIS_315H) { +#ifdef SIS315H + LCDXlatVCLK1 = LCDXlat1VCLK310; + LCDXlatVCLK2 = LCDXlat2VCLK310; + LVDSXlatVCLK2 = LVDSXlat2VCLK310; + LVDSXlatVCLK3 = LVDSXlat3VCLK310; +#endif + } else { +#ifdef SIS300 + LCDXlatVCLK1 = LCDXlat1VCLK300; + LCDXlatVCLK2 = LCDXlat2VCLK300; + LVDSXlatVCLK2 = LVDSXlat2VCLK300; + LVDSXlatVCLK3 = LVDSXlat3VCLK300; +#endif + } + + 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; + } 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; + } + + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { /* 301 */ + + if (SiS_Pr->SiS_SetFlag & ProgrammingCRT2) { + + CRT2Index >>= 6; + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)){ /* LCD */ + if(HwDeviceExtension->jChipType < SIS_315H) { + /* TW: Inserted from 630/301B BIOS */ + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) + VCLKIndex = LCDXlat0VCLK[CRT2Index]; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) + VCLKIndex = LCDXlatVCLK1[CRT2Index]; + else + VCLKIndex = LCDXlatVCLK2[CRT2Index]; + } else { + /* TW: 330, 650/301LV BIOS does not check expanding, 315 does */ + if( (HwDeviceExtension->jChipType > SIS_315PRO) || + (!(SiS_Pr->SiS_LCDInfo & LCDNonExpanding)) ) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) { + VCLKIndex = 0x19; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + VCLKIndex = 0x19; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) { + VCLKIndex = 0x21; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) { + VCLKIndex = LCDXlatVCLK1[CRT2Index]; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) { + VCLKIndex = 0x45; /* TW: TODO: This is certainly wrong */ + if(resinfo == 0x09) VCLKIndex++; + } else { + VCLKIndex = LCDXlatVCLK2[CRT2Index]; + } + } else { + VCLKIndex = (UCHAR)SiS_GetReg2((USHORT)(SiS_Pr->SiS_P3ca+0x02)); /* Port 3cch */ + VCLKIndex = ((VCLKIndex >> 2) & 0x03); + if(ModeNo > 0x13) { + VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + } + if(ModeNo <= 0x13) { /* TW: Inserted from 315 BIOS */ + if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42; + } + 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_IF_DEF_HiVision == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV)) { + if(SiS_Pr->SiS_SetFlag & RPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2; + else VCLKIndex = HiTVVCLK; + if(SiS_Pr->SiS_SetFlag & TVSimuMode) { + if(modeflag & Charx8Dot) VCLKIndex = HiTVSimuVCLK; + else VCLKIndex = HiTVTextVCLK; + } + } else { + if(SiS_Pr->SiS_SetFlag & RPLLDIV2XO) VCLKIndex = TVVCLKDIV2; + else VCLKIndex = TVVCLK; + } + if(HwDeviceExtension->jChipType >= SIS_315H) { + VCLKIndex += 25; + } + } else { /* RAMDAC2 */ + VCLKIndex = (UCHAR)SiS_GetReg2((USHORT)(SiS_Pr->SiS_P3ca+0x02)); + VCLKIndex = ((VCLKIndex >> 2) & 0x03); + if(ModeNo > 0x13) { + VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + if(HwDeviceExtension->jChipType < SIS_315H) { + VCLKIndex &= 0x3f; + if( (HwDeviceExtension->jChipType == SIS_630) && + (HwDeviceExtension->jChipRevision >= 0x30)) { + if(VCLKIndex == 0x14) VCLKIndex = 0x2e; + } + } + } + } + + } else { /* If not programming CRT2 */ + + VCLKIndex = (UCHAR)SiS_GetReg2((USHORT)(SiS_Pr->SiS_P3ca+0x02)); + VCLKIndex = ((VCLKIndex >> 2) & 0x03); + if(ModeNo > 0x13) { + VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + if(HwDeviceExtension->jChipType < SIS_315H) { + VCLKIndex &= 0x3f; + if( (HwDeviceExtension->jChipType != SIS_630) && + (HwDeviceExtension->jChipType != SIS_300) ) { + if(VCLKIndex == 0x1b) VCLKIndex = 0x35; + } + } + } + } + + } else { /* LVDS */ + + VCLKIndex = CRT2Index; + + if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) { /* programming CRT2 */ + + if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) { + + VCLKIndex &= 0x1f; + tempbx = 0; + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx += 1; + if(SiS_Pr->SiS_VBInfo & SetPALTV) { + tempbx += 2; + if(SiS_Pr->SiS_CHSOverScan) tempbx = 8; + if(SiS_Pr->SiS_CHPALM) { + tempbx = 4; + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx += 1; + } else if(SiS_Pr->SiS_CHPALN) { + tempbx = 6; + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) 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) { + + VCLKIndex >>= 6; + if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) || + (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480)) + VCLKIndex = LVDSXlat1VCLK[VCLKIndex]; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) + VCLKIndex = LVDSXlatVCLK2[VCLKIndex]; + else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) + VCLKIndex = LVDSXlatVCLK2[VCLKIndex]; + else VCLKIndex = LVDSXlatVCLK3[VCLKIndex]; + + } else { + + VCLKIndex = (UCHAR)SiS_GetReg2((USHORT)(SiS_Pr->SiS_P3ca+0x02)); + VCLKIndex = ((VCLKIndex >> 2) & 0x03); + if(ModeNo > 0x13) { + VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + if(HwDeviceExtension->jChipType < SIS_315H) { + VCLKIndex &= 0x3F; + } + if( (HwDeviceExtension->jChipType == SIS_630) && + (HwDeviceExtension->jChipRevision >= 0x30) ) { + if(VCLKIndex == 0x14) VCLKIndex = 0x2e; + } + } + } + + } else { /* if not programming CRT2 */ + + VCLKIndex = (UCHAR)SiS_GetReg2((USHORT)(SiS_Pr->SiS_P3ca+0x02)); + VCLKIndex = ((VCLKIndex >> 2) & 0x03); + if(ModeNo > 0x13) { + VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + if(HwDeviceExtension->jChipType < SIS_315H) { + VCLKIndex &= 0x3F; + if( (HwDeviceExtension->jChipType != SIS_630) && + (HwDeviceExtension->jChipType != SIS_300) ) { + if(VCLKIndex == 0x1b) VCLKIndex = 0x35; + } +#if 0 + if(HwDeviceExtension->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); +} + +/* TW: Set 301 Palette address port registers */ +/* TW: Checked against 650/301LV BIOS */ +void +SiS_SetGroup5(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr, + UCHAR *ROMAddr, USHORT ModeNo, USHORT ModeIdIndex) +{ + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return; + + if(SiS_Pr->SiS_ModeType == ModeVGA){ + if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))){ + SiS_EnableCRT2(SiS_Pr); + SiS_LoadDAC(SiS_Pr,HwDeviceExtension,ROMAddr,ModeNo,ModeIdIndex); + } + } + return; +} + +/* TW: Checked against 650/LVDS and 630/301B BIOS */ +void +SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT temp,tempah,i,modeflag,j; + USHORT ResInfo,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; + } + + temp = SiS_GetLVDSCRT1Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + &ResInfo,&DisplayType); + + if(temp == 0) return; + + /* TW: Inserted from 630/LVDS BIOS */ + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_Pr->SiS_SetFlag & CRT2IsVGA) return; + } + + switch(DisplayType) { + case 0 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1; break; + case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1; break; + case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1; break; + case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H; break; + case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H; break; + case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H; break; + case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2; break; + case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2; break; + case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2; break; + case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H; break; + case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H; 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 99: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL; break; + default: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1; break; + } + + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); /*unlock cr0-7 */ + + tempah = (LVDSCRT1Ptr+ResInfo)->CR[0]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x00,tempah); + + for(i=0x02,j=1;i<=0x05;i++,j++){ + tempah = (LVDSCRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x06,j=5;i<=0x07;i++,j++){ + tempah = (LVDSCRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x10,j=7;i<=0x11;i++,j++){ + tempah = (LVDSCRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x15,j=9;i<=0x16;i++,j++){ + tempah = (LVDSCRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x0A,j=11;i<=0x0C;i++,j++){ + tempah = (LVDSCRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3c4,i,tempah); + } + + tempah = (LVDSCRT1Ptr+ResInfo)->CR[14]; + tempah &= 0xE0; + SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah); /* TW: Modfied (650/LVDS); Was SetReg(tempah) */ + + tempah = (LVDSCRT1Ptr+ResInfo)->CR[14]; + tempah &= 0x01; + tempah <<= 5; + if(modeflag & DoubleScanMode){ + tempah |= 0x080; + } + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah); + + /* TW: Inserted from 650/LVDS BIOS */ + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + if(modeflag & HalfDCLK) + SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); + } + + return; +} + +#if 0 /* TW: Unused */ +/*301b*/ +void +SiS_CHACRT1CRTC(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex) +{ + USHORT temp,tempah,i,modeflag,j; + USHORT ResInfo,DisplayType; + SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr=NULL; + + if(ModeNo<=0x13) { + modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */ + } else { + modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */ + } + + temp=SiS_GetLVDSCRT1Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex, + &ResInfo,&DisplayType); + if(temp==0){ + return; + } + + switch(DisplayType) { + case 0 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1; break; + case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1; break; + case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1; break; + case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H; break; + case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H; break; + case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H; break; + case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2; break; + case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2; break; + case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2; break; + case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H; break; + case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H; 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 99: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL; break; + } + + tempah=(UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3d4,0x11); /*unlock cr0-7 */ + tempah=tempah&0x7F; + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x11,tempah); + tempah = (LVDSCRT1Ptr+ResInfo)->CR[0]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x0,tempah); + for(i=0x02,j=1;i<=0x05;i++,j++){ + tempah = (LVDSCRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x06,j=5;i<=0x07;i++,j++){ + tempah = (LVDSCRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x10,j=7;i<=0x11;i++,j++){ + tempah = (LVDSCRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); + } + for(i=0x15,j=9;i<=0x16;i++,j++){ + tempah = (LVDSCRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah); + } + + for(i=0x0A,j=11;i<=0x0C;i++,j++){ + tempah = (LVDSCRT1Ptr+ResInfo)->CR[j]; + SiS_SetReg1(SiS_Pr->SiS_P3c4,i,tempah); + } + + tempah = (LVDSCRT1Ptr+ResInfo)->CR[14]; + tempah=tempah&0x0E0; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x0E,tempah); + + tempah = (LVDSCRT1Ptr+ResInfo)->CR[14]; + tempah=tempah&0x01; + tempah=tempah<<5; + if(modeflag&DoubleScanMode){ + tempah=tempah|0x080; + } + SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah); + return; +} +#endif + +/* TW: Checked against 650/LVDS BIOS: modified for new panel resolutions */ +BOOLEAN +SiS_GetLVDSCRT1Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *ResInfo, + USHORT *DisplayType) + { + USHORT tempbx,modeflag=0; + USHORT Flag,CRT2CRTC; + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + /* TW: Inserted from 650/LVDS BIOS */ + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return 0; + } + } + + 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[RefreshRateTableIndex].Ext_CRT2CRTC; + } + + Flag = 1; + tempbx = 0; + if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) { + Flag = 0; + tempbx = 18; + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx++; + if(SiS_Pr->SiS_VBInfo & SetPALTV) { + tempbx += 2; + if(SiS_Pr->SiS_CHSOverScan) tempbx = 99; + if(SiS_Pr->SiS_CHPALM) { + tempbx = 18; /* PALM uses NTSC data */ + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx++; + } else if(SiS_Pr->SiS_CHPALN) { + tempbx = 20; /* PALN uses PAL data */ + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx++; + } + } + } + } + if(Flag) { + tempbx = SiS_Pr->SiS_LCDResInfo; + tempbx -= SiS_Pr->SiS_PanelMinLVDS; + if(SiS_Pr->SiS_LCDResInfo <= SiS_Pr->SiS_Panel1280x1024) { + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 6; + if(modeflag & HalfDCLK) tempbx += 3; + } else { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + tempbx = 14; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 2; + if(modeflag & HalfDCLK) tempbx++; + } else if(SiS_Pr->SiS_LCDInfo & LCDPass11) { + tempbx = 12; + if(modeflag & HalfDCLK) tempbx++; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) { + tempbx = 23; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 2; + if(modeflag & HalfDCLK) tempbx++; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) { + tempbx = 27; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 2; + if(modeflag & HalfDCLK) tempbx++; + } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) { + tempbx = 36; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 2; + if(modeflag & HalfDCLK) tempbx++; + } + } + } + if(SiS_Pr->SiS_IF_DEF_FSTN){ + if(SiS_Pr->SiS_LCDResInfo==SiS_Pr->SiS_Panel320x480){ + tempbx=22; + } + } + *ResInfo = CRT2CRTC & 0x3F; + *DisplayType = tempbx; + return 1; +} + +/* TW: Checked against 650/LVDS (1.10a, 1.10.07), 630/301B (I/II) and 630/LVDS BIOS */ +void +SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT tempah,tempal,pushax; + USHORT vclkindex=0; + + if(HwDeviceExtension->jChipType < SIS_315H) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) return; + } + } + + if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) || (SiS_Pr->SiS_IF_DEF_TRUMPION == 1)) { + SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2); + tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + tempal &= 0x3F; + if(tempal == 2) RefreshRateTableIndex--; + vclkindex = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; + } else { + vclkindex = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex, + RefreshRateTableIndex,HwDeviceExtension); + } + + tempal = 0x02B; + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) { + tempal += 3; + } + } + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86); + pushax = tempal; + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,0x20); + tempah = SiS_Pr->SiS_VCLKData[vclkindex].SR2B; + SiS_SetReg1(SiS_Pr->SiS_P3c4,tempal,tempah); + tempal++; + tempah = SiS_Pr->SiS_VCLKData[vclkindex].SR2C; + SiS_SetReg1(SiS_Pr->SiS_P3c4,tempal,tempah); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,0x10); + tempal = pushax; + tempah = SiS_Pr->SiS_VCLKData[vclkindex].SR2B; + SiS_SetReg1(SiS_Pr->SiS_P3c4,tempal,tempah); + tempal++; + tempah = SiS_Pr->SiS_VCLKData[vclkindex].SR2C; + SiS_SetReg1(SiS_Pr->SiS_P3c4,tempal,tempah); + SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,0x00); + tempal = pushax; + tempah = SiS_Pr->SiS_VCLKData[vclkindex].SR2B; + SiS_SetReg1(SiS_Pr->SiS_P3c4,tempal,tempah); + tempal++; + tempah = SiS_Pr->SiS_VCLKData[vclkindex].SR2C; + SiS_SetReg1(SiS_Pr->SiS_P3c4,tempal,tempah); + return; +} + +#if 0 /* TW: Not used */ +void +SiS_SetDefCRT2ExtRegs(SiS_Private *SiS_Pr, USHORT BaseAddr) +{ + USHORT temp; + + if(SiS_Pr->SiS_IF_DEF_LVDS==0) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x02,0x40); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x10,0x80); + temp=(UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16); + temp &= 0xC3; + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x35,temp); + } else { + SiS_SetReg1(SiS_Pr->SiS_P3d4,0x32,0x02); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x02,0x00); + } +} +#endif + +/* TW: Start of Chrontel 70xx functions ---------------------- */ + +/* Set-up the Chrontel Registers */ +void +SiS_SetCHTVReg(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex) +{ + USHORT temp, tempbx, 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_VBInfo & SetCHTVOverScan) TVType += 1; + if(SiS_Pr->SiS_VBInfo & SetPALTV) { + TVType += 2; + if(SiS_Pr->SiS_CHSOverScan) TVType = 8; + if(SiS_Pr->SiS_CHPALM) { + TVType = 4; + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) TVType += 1; + } else if(SiS_Pr->SiS_CHPALN) { + TVType = 6; + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) 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) { + + /* Chrontel 7005 */ + + /* TW: We don't support modes >800x600 */ + if (resindex > 5) return; + + if(SiS_Pr->SiS_VBInfo & SetPALTV) { + SiS_SetCH700x(SiS_Pr,0x4304); /* TW: 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/ + SiS_SetCH700x(SiS_Pr,0x6909); /* TW: Black level for PAL (105)*/ + } else { + SiS_SetCH700x(SiS_Pr,0x0304); /* TW: upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/ + SiS_SetCH700x(SiS_Pr,0x7109); /* TW: Black level for NTSC (113)*/ + } + + temp = CHTVRegData[resindex].Reg[0]; + tempbx=((temp&0x00FF)<<8)|0x00; /* TW: Mode register */ + SiS_SetCH700x(SiS_Pr,tempbx); + temp = CHTVRegData[resindex].Reg[1]; + tempbx=((temp&0x00FF)<<8)|0x07; /* TW: Start active video register */ + SiS_SetCH700x(SiS_Pr,tempbx); + temp = CHTVRegData[resindex].Reg[2]; + tempbx=((temp&0x00FF)<<8)|0x08; /* TW: Position overflow register */ + SiS_SetCH700x(SiS_Pr,tempbx); + temp = CHTVRegData[resindex].Reg[3]; + tempbx=((temp&0x00FF)<<8)|0x0A; /* TW: Horiz Position register */ + SiS_SetCH700x(SiS_Pr,tempbx); + temp = CHTVRegData[resindex].Reg[4]; + tempbx=((temp&0x00FF)<<8)|0x0B; /* TW: Vertical Position register */ + SiS_SetCH700x(SiS_Pr,tempbx); + + /* TW: 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); + + /* TW: 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 */ + + /* TW: Register 0x3D does not exist in non-macrovision register map + (Maybe this is a macrovision register?) + */ + /* SiS_SetCH70xx(SiS_Pr,0x003D); */ + + /* TW: Register 0x10 only contains 1 writable bit (S0) for sensing, + all other bits a read-only. Macrovision? + */ + SiS_SetCH70xxANDOR(SiS_Pr,0x0010,0x1F); + + /* TW: 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); + + /* TW: Clear DSEN + */ + SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xEF); + + if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) { /* ---- NTSC ---- */ + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) { + 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 */ + 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); + SiS_SetCH70xxANDOR(SiS_Pr,0x0b1B,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x031C,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x0a1D,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x061E,0xF0); + SiS_SetCH70xxANDOR(SiS_Pr,0x031F,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 */ + } + } + } + } else { /* ---- PAL ---- */ + /* TW: 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 */ + } + } + + } else { + + /* Chrontel 7019 */ + + /* TW: We don't support modes >1024x768 */ + if (resindex > 6) return; + + temp = CHTVRegData[resindex].Reg[0]; + 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]; + 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); + + } +} + +/* TW: Chrontel 701x functions ================================= */ + +void +SiS_SetCH701xForLCD(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr) +{ + UCHAR regtable[] = { 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71, + 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d }; + UCHAR table1024[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed, + 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02 }; + UCHAR table1400[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xef, + 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02 }; + UCHAR *tableptr = NULL; + USHORT tempbh; + int i; + + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + tableptr = table1400; + } else { + tableptr = table1024; + } + 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 != SiS_Pr->SiS_Panel1400x1050) return; + } else if(tempbh == 0xdb) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) return; + } + } + for(i=0; i<0x0c; i++) { + SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]); + } + SiS_ChrontelPowerSequencing(SiS_Pr); + tempbh = SiS_GetCH701x(SiS_Pr,0x1e); + tempbh |= 0xc0; + SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1e); +} + +void +SiS_ChrontelPowerSequencing(SiS_Private *SiS_Pr) +{ + UCHAR regtable[] = { 0x67, 0x68, 0x69, 0x6a, 0x6b }; + UCHAR table1024[] = { 0x01, 0x02, 0x01, 0x01, 0x02 }; + UCHAR table1400[] = { 0x01, 0x02, 0x01, 0x01, 0x02 }; + UCHAR *tableptr = NULL; + int i; + + /* Set up Power up/down timing */ + + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + tableptr = table1400; + } else { + tableptr = table1024; + } + + for(i=0; i<5; i++) { + SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]); + } +} + +void +SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr) +{ + USHORT temp; + + /* TW: Enable Chrontel 7019 LCD panel backlight */ + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + temp = SiS_GetCH701x(SiS_Pr,0x66); + temp |= 0x20; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66); + } +} + +void +SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr) +{ + USHORT temp; + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + if(SiS_IsYPbPr(SiS_Pr,HwDeviceExtension, BaseAddr)) { + temp = SiS_GetCH701x(SiS_Pr,0x01); + temp &= 0x3f; + temp |= 0x80; /* TW: Enable YPrPb (HDTV) */ + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01); + } + if(SiS_IsChScart(SiS_Pr,HwDeviceExtension, BaseAddr)) { + temp = SiS_GetCH701x(SiS_Pr,0x01); + temp &= 0x3f; + temp |= 0xc0; /* TW: Enable SCART + CVBS */ + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01); + } + SiS_SetCH701x(SiS_Pr,0x2049); /* TW: Enable TV path */ + temp = SiS_GetCH701x(SiS_Pr,0x49); + if(SiS_IsYPbPr(SiS_Pr,HwDeviceExtension, BaseAddr)) { + 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); + } +} + +void +SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr) +{ + USHORT temp; + + /* TW: 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); + } +} + +void +SiS_Chrontel701xOff(SiS_Private *SiS_Pr) +{ + USHORT temp; + + if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { + SiS_LongDelay(SiS_Pr,2); + /* TW: Complete power down of LVDS */ + temp = SiS_GetCH701x(SiS_Pr,0x76); + temp &= 0xfc; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76); + SiS_SetCH701x(SiS_Pr,0x0066); + } +} + +void +SiS_ChrontelResetDB(SiS_Private *SiS_Pr) +{ + /* TW: Reset Chrontel 7019 datapath */ + SiS_SetCH701x(SiS_Pr,0x1048); + SiS_LongDelay(SiS_Pr,1); + SiS_SetCH701x(SiS_Pr,0x1848); +} + +void +SiS_ChrontelDoSomething4(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr) +{ + USHORT temp; + + 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 */ + } +} + +void +SiS_ChrontelDoSomething3(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT BaseAddr) +{ + USHORT temp,temp1; + + 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,HwDeviceExtension, BaseAddr)) { + 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); +} + +void +SiS_ChrontelDoSomething2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr) +{ + USHORT temp,tempcl,tempch; + + SiS_LongDelay(SiS_Pr, 1); + tempcl = 3; + tempch = 0; + + do { + temp = SiS_GetCH701x(SiS_Pr,0x66); + temp &= 0x04; + if(temp == 0x04) break; + + SiS_SetCH701xForLCD(SiS_Pr,HwDeviceExtension,BaseAddr); + + if(tempcl == 0) { + if(tempch == 3) break; + SiS_ChrontelResetDB(SiS_Pr); + tempcl = 3; + tempch++; + } + tempcl--; + temp = SiS_GetCH701x(SiS_Pr,0x76); + temp &= 0xfb; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76); + SiS_LongDelay(SiS_Pr,2); + temp = SiS_GetCH701x(SiS_Pr,0x76); + temp |= 0x04; + SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76); + SiS_SetCH701x(SiS_Pr,0x6078); + SiS_LongDelay(SiS_Pr,2); + } while(0); + + SiS_SetCH701x(SiS_Pr,0x0077); +} + +void +SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT BaseAddr) +{ + 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); + + SiS_ChrontelResetDB(SiS_Pr); + + SiS_ChrontelDoSomething2(SiS_Pr,HwDeviceExtension,BaseAddr); + + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x34); + SiS_ChrontelDoSomething3(SiS_Pr,temp,HwDeviceExtension,BaseAddr); + + SiS_SetCH701x(SiS_Pr,0xaf76); +} + +/* TW: End of Chrontel 701x functions ==================================== */ + +/* TW: Generic Read/write routines for Chrontel ========================== */ + +/* TW: The Chrontel 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 + */ + +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); +} + +/* TW: Write to Chrontel 700x */ +/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */ +void +SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx) +{ + USHORT tempah,temp,i; + + if(!(SiS_Pr->SiS_ChrontelInit)) { + SiS_Pr->SiS_DDC_Index = 0x11; /* TW: 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_Pr->SiS_DDC_DataShift = 0x00; + SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* TW: DAB (Device Address Byte) */ + } + + for(i=0;i<10;i++) { /* TW: Do only 10 attempts to write */ + /* SiS_SetSwitchDDC2(SiS_Pr); */ + if(SiS_SetStart(SiS_Pr)) continue; /* TW: Set start condition */ + tempah = SiS_Pr->SiS_DDC_DeviceAddr; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write DAB (S0=0=write) */ + if(temp) continue; /* TW: (ERROR: no ack) */ + tempah = tempbx & 0x00FF; /* TW: Write RAB */ + tempah |= 0x80; /* TW: (set bit 7, see datasheet) */ + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); + if(temp) continue; /* TW: (ERROR: no ack) */ + tempah = (tempbx & 0xFF00) >> 8; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write data */ + if(temp) continue; /* TW: (ERROR: no ack) */ + if(SiS_SetStop(SiS_Pr)) continue; /* TW: Set stop condition */ + SiS_Pr->SiS_ChrontelInit = 1; + return; + } + + /* TW: For 630ST */ + if(!(SiS_Pr->SiS_ChrontelInit)) { + SiS_Pr->SiS_DDC_Index = 0x0a; /* TW: 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_Pr->SiS_DDC_DataShift = 0x00; + SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* TW: DAB (Device Address Byte) */ + + for(i=0;i<10;i++) { /* TW: Do only 10 attempts to write */ + /* SiS_SetSwitchDDC2(SiS_Pr); */ + if (SiS_SetStart(SiS_Pr)) continue; /* TW: Set start condition */ + tempah = SiS_Pr->SiS_DDC_DeviceAddr; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write DAB (S0=0=write) */ + if(temp) continue; /* TW: (ERROR: no ack) */ + tempah = tempbx & 0x00FF; /* TW: Write RAB */ + tempah |= 0x80; /* TW: (set bit 7, see datasheet) */ + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); + if(temp) continue; /* TW: (ERROR: no ack) */ + tempah = (tempbx & 0xFF00) >> 8; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write data */ + if(temp) continue; /* TW: (ERROR: no ack) */ + if(SiS_SetStop(SiS_Pr)) continue; /* TW: Set stop condition */ + SiS_Pr->SiS_ChrontelInit = 1; + return; + } + } +} + +/* TW: Write to Chrontel 701x */ +/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */ +void +SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx) +{ + USHORT tempah,temp,i; + + SiS_Pr->SiS_DDC_Index = 0x11; /* TW: 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_Pr->SiS_DDC_DataShift = 0x00; + SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* TW: DAB (Device Address Byte) */ + + for(i=0;i<10;i++) { /* TW: Do only 10 attempts to write */ + if (SiS_SetStart(SiS_Pr)) continue; /* TW: Set start condition */ + tempah = SiS_Pr->SiS_DDC_DeviceAddr; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write DAB (S0=0=write) */ + if(temp) continue; /* TW: (ERROR: no ack) */ + tempah = tempbx & 0x00FF; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write RAB */ + if(temp) continue; /* TW: (ERROR: no ack) */ + tempah = (tempbx & 0xFF00) >> 8; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write data */ + if(temp) continue; /* TW: (ERROR: no ack) */ + if(SiS_SetStop(SiS_Pr)) continue; /* TW: Set stop condition */ + return; + } +} + +/* TW: 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)); +} + +/* TW: Read from Chrontel 700x */ +/* Parameter is [Register no (S7-S0)] */ +USHORT +SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx) +{ + USHORT tempah,temp,i; + + if(!(SiS_Pr->SiS_ChrontelInit)) { + SiS_Pr->SiS_DDC_Index = 0x11; /* TW: 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_Pr->SiS_DDC_DataShift = 0x00; + SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* TW: DAB */ + } + + SiS_Pr->SiS_DDC_ReadAddr = tempbx; + + for(i=0;i<20;i++) { /* TW: Do only 20 attempts to read */ + /* SiS_SetSwitchDDC2(SiS_Pr); */ + if(SiS_SetStart(SiS_Pr)) continue; /* TW: Set start condition */ + tempah = SiS_Pr->SiS_DDC_DeviceAddr; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write DAB (S0=0=write) */ + if(temp) continue; /* TW: (ERROR: no ack) */ + tempah = SiS_Pr->SiS_DDC_ReadAddr | 0x80; /* TW: Write RAB | 0x80 */ + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); + if(temp) continue; /* TW: (ERROR: no ack) */ + if (SiS_SetStart(SiS_Pr)) continue; /* TW: Re-start */ + tempah = SiS_Pr->SiS_DDC_DeviceAddr | 0x01; /* DAB | 0x01 = Read */ + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: DAB (S0=1=read) */ + if(temp) continue; /* TW: (ERROR: no ack) */ + tempah = SiS_ReadDDC2Data(SiS_Pr,tempah); /* TW: Read byte */ + if (SiS_SetStop(SiS_Pr)) continue; /* TW: Stop condition */ + SiS_Pr->SiS_ChrontelInit = 1; + return(tempah); + } + + /* TW: For 630ST */ + if(!SiS_Pr->SiS_ChrontelInit) { + SiS_Pr->SiS_DDC_Index = 0x0a; /* TW: Bit 0 = SC; Bit 1 = SD */ + SiS_Pr->SiS_DDC_Data = 0x80; /* Bitmask in IndexReg for Data */ + SiS_Pr->SiS_DDC_Clk = 0x40; /* Bitmask in IndexReg for Clk */ + SiS_Pr->SiS_DDC_DataShift = 0x00; + SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* TW: DAB (Device Address Byte) */ + + for(i=0;i<20;i++) { /* TW: Do only 20 attempts to read */ + /* SiS_SetSwitchDDC2(SiS_Pr); */ + if(SiS_SetStart(SiS_Pr)) continue; /* TW: Set start condition */ + tempah = SiS_Pr->SiS_DDC_DeviceAddr; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write DAB (S0=0=write) */ + if(temp) continue; /* TW: (ERROR: no ack) */ + tempah = SiS_Pr->SiS_DDC_ReadAddr | 0x80; /* TW: Write RAB | 0x80 */ + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); + if(temp) continue; /* TW: (ERROR: no ack) */ + if (SiS_SetStart(SiS_Pr)) continue; /* TW: Re-start */ + tempah = SiS_Pr->SiS_DDC_DeviceAddr | 0x01; /* DAB | 0x01 = Read */ + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: DAB (S0=1=read) */ + if(temp) continue; /* TW: (ERROR: no ack) */ + tempah = SiS_ReadDDC2Data(SiS_Pr,tempah); /* TW: Read byte */ + if (SiS_SetStop(SiS_Pr)) continue; /* TW: Stop condition */ + SiS_Pr->SiS_ChrontelInit = 1; + return(tempah); + } + } + return(0xFFFF); +} + +/* TW: Read from Chrontel 701x */ +/* Parameter is [Register no (S7-S0)] */ +USHORT +SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx) +{ + USHORT tempah,temp,i; + + SiS_Pr->SiS_DDC_Index = 0x11; /* TW: 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_Pr->SiS_DDC_DataShift = 0x00; + SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* TW: DAB */ + SiS_Pr->SiS_DDC_ReadAddr = tempbx; + + for(i=0;i<20;i++) { /* TW: Do only 20 attempts to read */ + if(SiS_SetStart(SiS_Pr)) continue; /* TW: Set start condition */ + tempah = SiS_Pr->SiS_DDC_DeviceAddr; + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write DAB (S0=0=write) */ + if(temp) continue; /* TW: (ERROR: no ack) */ + tempah = SiS_Pr->SiS_DDC_ReadAddr; /* TW: Write RAB */ + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); + if(temp) continue; /* TW: (ERROR: no ack) */ + if (SiS_SetStart(SiS_Pr)) continue; /* TW: Re-start */ + tempah = SiS_Pr->SiS_DDC_DeviceAddr | 0x01; /* DAB | 0x01 = Read */ + temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: DAB (S0=1=read) */ + if(temp) continue; /* TW: (ERROR: no ack) */ + tempah = SiS_ReadDDC2Data(SiS_Pr,tempah); /* TW: Read byte */ + SiS_SetStop(SiS_Pr); /* TW: Stop condition */ + return(tempah); + } + return 0xFFFF; +} + +#ifdef LINUX_XF86 +/* TW: Our own DDC functions */ +USHORT +SiS_InitDDCRegs(SiS_Private *SiS_Pr, SISPtr pSiS, USHORT adaptnum, USHORT DDCdatatype) +{ + unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6}; + unsigned char flag, cr32; + USHORT temp = 0, myadaptnum = adaptnum; + + 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_GetReg1(SiS_Pr->SiS_P3d4,0x32); + + if(pSiS->VGAEngine == SIS_300_VGA) { /* 300 series */ + + if(pSiS->VBFlags & VB_SISBRIDGE) { + if(myadaptnum == 0) { + if(!(cr32 & 0x20)) { + myadaptnum = 2; + if(!(cr32 & 0x10)) { + myadaptnum = 1; + if(!(cr32 & 0x08)) { + myadaptnum = 0; + } + } + } + } + } + + if(myadaptnum != 0) { + flag = 0; + if(pSiS->VBFlags & VB_SISBRIDGE) { + SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port; + SiS_Pr->SiS_DDC_Index = 0x0f; + } + } + + if(cr32 & 0x80) { + if(myadaptnum >= 1) { + if(!(cr32 & 0x08)) { + myadaptnum = 1; + if(!(cr32 & 0x10)) return 0xFFFF; + } + } + } + + temp = 4 - (myadaptnum * 2); + if(flag) temp = 0; + + SiS_Pr->SiS_DDC_Data = 0x02 << temp; + SiS_Pr->SiS_DDC_Clk = 0x01 << temp; + + } else { /* 310/325 series */ + + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) myadaptnum = 0; + + if(pSiS->VBFlags & VB_SISBRIDGE) { + if(myadaptnum == 0) { + if(!(cr32 & 0x20)) { + myadaptnum = 2; + if(!(cr32 & 0x10)) { + myadaptnum = 1; + if(!(cr32 & 0x08)) { + myadaptnum = 0; + } + } + } + } + if(myadaptnum == 2) { + myadaptnum = 1; + } + } + + if(myadaptnum == 1) { + flag = 0; + if(pSiS->VBFlags & VB_SISBRIDGE) { + SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port; + SiS_Pr->SiS_DDC_Index = 0x0f; + } + } + + if(cr32 & 0x80) { + if(myadaptnum >= 1) { + if(!(cr32 & 0x08)) { + myadaptnum = 1; + if(!(cr32 & 0x10)) return 0xFFFF; + } + } + } + + temp = myadaptnum; + if(myadaptnum == 1) { + temp = 0; + if(pSiS->VBFlags & VB_LVDS) flag = 0xff; + } + + if(flag) temp = 0; + + SiS_Pr->SiS_DDC_Data = 0x02 << temp; + SiS_Pr->SiS_DDC_Clk = 0x01 << temp; + + } + return 0; +} + +USHORT +SiS_WriteDABDDC(SiS_Private *SiS_Pr) +{ + SiS_SetStart(SiS_Pr); + 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); +} + +USHORT +SiS_PrepareReadDDC(SiS_Private *SiS_Pr) +{ + SiS_SetStart(SiS_Pr); + if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) return 0xFFFF; + return(0); +} + +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); +} + +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_Data, SiS_Pr->SiS_DDC_Data); + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, + ~SiS_Pr->SiS_DDC_Data, 0); + } + SiS_SetSCLKHigh(SiS_Pr); +} + +USHORT +SiS_DoProbeDDC(SiS_Private *SiS_Pr) +{ + unsigned char mask, value; + USHORT temp, ret; + + SiS_SetSwitchDDC2(SiS_Pr); + if(SiS_PrepareDDC(SiS_Pr)) { + SiS_SetStop(SiS_Pr); + 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; + } + } + temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0); + SiS_SendACK(SiS_Pr, 1); + temp &= mask; + if(temp == value) ret = 0; + else { + ret = 0xFFFF; + if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) { + if(value == 0x30) ret = 0; + } + } + SiS_SetStop(SiS_Pr); + return(ret); +} + +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); +} + +USHORT +SiS_ReadDDC(SiS_Private *SiS_Pr, SISPtr pSiS, USHORT DDCdatatype, unsigned char *buffer) +{ + USHORT flag, length, i; + unsigned char chksum,gotcha; + + if(DDCdatatype > 3) return 0xFFFF; /* incomplete! */ + + 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); +} + +USHORT +SiS_ReadLCDDDC(SiS_Private *SiS_Pr, USHORT length, unsigned char *buffer) +{ + USHORT i=0, flag=0; + + length--; + + SiS_SetSwitchDDC2(SiS_Pr); + if(!(SiS_PrepareDDC(SiS_Pr))) { + for(i=0; i<length; i++) { + buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0); + SiS_SendACK(SiS_Pr, 0); + } + buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0); + SiS_SendACK(SiS_Pr, 1); + } else flag = 0xFFFF; + + SiS_SetStop(SiS_Pr); + return(0); +} + +/* TW: Our private DDC function + + 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, 1=CRT2 + CRT2 DDC is not supported in some cases. + DDCdatatype: 0=Probe, 1=EDID, 2=VDIF(not supported), 3=?, 4=?(not supported) + 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, SISPtr pSiS, USHORT adaptnum, + USHORT DDCdatatype, unsigned char *buffer) +{ + if(DDCdatatype == 2) return 0xFFFF; + if(adaptnum > 2) return 0xFFFF; + if(pSiS->VGAEngine == SIS_300_VGA) { + if((adaptnum != 0) && (DDCdatatype != 0)) return 0xFFFF; + } + if((!(pSiS->VBFlags & VB_VIDEOBRIDGE)) && (adaptnum > 0)) return 0xFFFF; + if(SiS_InitDDCRegs(SiS_Pr, pSiS, adaptnum, DDCdatatype) == 0xFFFF) return 0xFFFF; + if(DDCdatatype == 0) { + return(SiS_ProbeDDC(SiS_Pr)); + } else { + if(DDCdatatype > 4) return 0xFFFF; + return(SiS_ReadDDC(SiS_Pr, pSiS, DDCdatatype, buffer)); + } +} + +#if 0 /* for future use */ + +USHORT +SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS, unsigned char *buffer) +{ + USHORT flag, temp; + unsigned char buffer[8]; + unsigned char cr36=0, cr37=0; + unsigned chat tempal, tempah, tempbl, tempbh; + USHORT tempax, tempbx tempcx, push1, push2, push3; + unsigned char addresstable[] = { 0x00, 0x22, 0x30, 0x40 }; + + if(SiS_InitDDCRegs(SiS_Pr, pSiS, 1, 0) == 0xFFFF) return 0xFFFF; + flag = SiS_ProbeDDC(SiS_Pr); + + if(flag & 0x02) { + SiS_Pr->SiS_DDC_DeviceAddr = 0xa0; + SiS_Pr->SiS_DDC_SecAddr = 0x3a; + } else if(flag & 0x08) { + SiS_Pr->SiS_DDC_DeviceAddr = 0xa2; + SiS_Pr->SiS_DDC_SecAddr = 0x76; + } else if(flag & 0x10) { + SiS_Pr->SiS_DDC_DeviceAddr = 0xa6; + SiS_Pr->SiS_DDC_SecAddr = 0x76; + } else return 0xFFFF; + + SiS_ReadLCDDDC(SiS_Pr, 4, buffer); + tempbl = buffer[0]; + tempbh = buffer[1]; + if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) { + tempah = 0x02; + tempbl &= 0xf0; + if(tempbl != 0x40) { + tempah = 0x03; + if(tempbl == 0x50) { + if(!tempbh) { + tempbh = buffer[3] & 0xf0; + if(tempbh == 0x30) { + SiS_Pr->SiS_DDC_DeviceAddr = 0xa0; + SiS_Pr->SiS_DDC_SecAddr = 0x23; + SiS_ReadLCDDDC(SiS_Pr, 2, buffer); + tempbl = buffer[0]; + tempbh = buffer[1]; + if(tempbl) cr37 |= 0x10; + tempah = 0x0a; + } + if(tempbh == 0x40) { + SiS_Pr->SiS_DDC_DeviceAddr = 0xa0; + SiS_Pr->SiS_DDC_SecAddr = 0x23; + SiS_ReadLCDDDC(SiS_Pr, 2, buffer); + tempbl = buffer[0]; + tempbh = buffer[1]; + if(tempbl) cr37 |= 0x10; + tempah = 0x03; + } + tempbh = 0x00; + } + } + if(tempbh == 0x00) goto cr36ready; + tempah = 0x07; + if(tempbh == 0xc0) goto cr36ready; + } + SiS_Pr->SiS_DDC_DeviceAddr = 0xa0; + SiS_Pr->SiS_DDC_SecAddr = 0x18; + SiS_ReadLCDDDC(SiS_Pr, 2, buffer); + tempbl = buffer[0]; + tempbh = buffer[1]; + if(tempbl & 0x02) goto cr36ready; + SiS_Pr->SiS_DDC_DeviceAddr = 0xa0; + SiS_Pr->SiS_DDC_SecAddr = 0x23; + SiS_ReadLCDDDC(SiS_Pr, 2, buffer); + tempbl = buffer[0]; + tempbh = buffer[1]; + tempah = 0x03; + if(!tempbh & 0x01)) tempah = 0x02; + if(!tempbl) cr37 |= 0x10; + + } else { + + tempah = 0x02; + tempbx = tempbl | (tempbh << 8); + if(tempbx != 1024) tempah = 0x03; + + } + +cr36ready: + cr36 = tempah; + + if((SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) { + + SiS_Pr->SiS_DDC_SecAddr = 0x47; + SiS_ReadLCDDDC(SiS_Pr, 2, buffer); + tempah = buffer[0]; + tempah &= 0x06; + tempah ^= 0x06; + tempah <<= 5; + tempah |= 0x20; + cr37 &= 0x1f; + cr37 |= tempah; + if((cr36 & 0x07) == 0x07) cr37 &= 0x0e; + + } else { + + push1 = tempah; + SiS_Pr->SiS_DDC_SecAddr = 0x45; + SiS_ReadLCDDDC(SiS_Pr, 2, buffer); + tempah = 0x01; + if((buffer[0] != 0x20) && (buffer[0] != 0x34)) { + tempah = 0x00; + } + cr37 &= 0xfe; + cr37 |= tempah; + + SiS_Pr->SiS_DDC_SecAddr = 0x7e; + SiS_ReadLCDDDC(SiS_Pr, 2, buffer); + tempax = (USHORT)(buffer[0] | (buffer[1] << 8)); + push2 = tempax; + tempax &= 0x0003; + tempax *= 0x1b; + push3 = tempax; + tempax = (USHORT)buffer[0]; + tempax &= 0x001c; + tempax >>= 2; + tempax *= 8; + tempbx = push3; + tempbx += tempax; + if(buffer[0] & 0x20) { + SiS_Pr->SiS_DDC_SecAddr = 0x80; + SiS_ReadLCDDDC(SiS_Pr, 2, buffer); + tempax = buffer[0] | (buffer[1] << 8); + tempax &= 0x1f; + if(buffer[0] & 0x70) tempax <<= 1; + tempax++; + tempbx += tempax; + } + tempcx = push2; + tempax = push1 << 8; + tempbx = (tempbx & 0xff00) | (((tempbx & 0x00ff) + 0x80) & 0x00ff); + if(tempcx & 0xf800) { + tempal = addresstable[((tempax & 0xff00) >> 8)]; + tempcx &= 0xf8ff; + tempcx >>= 11; + for(i=0; i<tempcx; i++) { + SiS_Pr->SiS_DDC_SecAddr = (tempbx & 0x00ff); + SiS_ReadLCDDDC(SiS_Pr, 2, buffer); + tempbx += 0x04; + if(buffer[0] == tempal) break; + } + tempah = buffer[1]; + tempah &= 0x0c; + tempah ^= 0x0c; + tempah <<= 4; + tempah |= 0x20; + cr37 &= 0x1f; + cr37 |= tempah; + if((cr36 & 0x07) == 0x07) cr37 &= 0x0e; + } + } + xf86DrvMsg(0, X_INFO, "DDC: cr36 = 0x%02x, cr37 = 0x%02x\n", cr36, cr37); + +} + +#endif + +/* TW: Generic I2C functions (compliant to i2c library) */ + +#if 0 +USHORT +SiS_I2C_GetByte(SiS_Private *SiS_Pr) +{ + return(SiS_ReadDDC2Data(SiS_Pr,0)); +} + +Bool +SiS_I2C_PutByte(SiS_Private *SiS_Pr, USHORT data) +{ + if(SiS_WriteDDC2Data(SiS_Pr,data)) return FALSE; + return TRUE; +} + +Bool +SiS_I2C_Address(SiS_Private *SiS_Pr, USHORT addr) +{ + if(SiS_SetStart(SiS_Pr)) return FALSE; + if(SiS_WriteDDC2Data(SiS_Pr,addr)) return FALSE; + return TRUE; +} + +void +SiS_I2C_Stop(SiS_Private *SiS_Pr) +{ + SiS_SetStop(SiS_Pr); +} +#endif + +#endif + +void +SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh) +{ + USHORT tempal,tempah,tempbl; + + tempal = tempax & 0x00FF; + tempah =(tempax >> 8) & 0x00FF; + tempbl = SiS_GetCH70xx(SiS_Pr,tempal); + tempbl = (((tempbl & tempbh) | tempah) << 8 | tempal); + SiS_SetCH70xx(SiS_Pr,tempbl); +} + +/* TW: Generic I2C functions for Chrontel --------- */ + +void +SiS_SetSwitchDDC2(SiS_Private *SiS_Pr) +{ + SiS_SetSCLKHigh(SiS_Pr); + /* SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAY); */ + SiS_WaitRetraceDDC(SiS_Pr); + + SiS_SetSCLKLow(SiS_Pr); + /* SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAY); */ + SiS_WaitRetraceDDC(SiS_Pr); +} + +/* TW: Set I2C start condition */ +/* TW: This is done by a SD high-to-low transition while SC is high */ +USHORT +SiS_SetStart(SiS_Private *SiS_Pr) +{ + if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* TW: (SC->low) */ + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index, + ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data); /* TW: SD->high */ + if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* TW: SC->high */ + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index, + ~SiS_Pr->SiS_DDC_Data,0x00); /* TW: SD->low = start condition */ + if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* TW: (SC->low) */ + return 0; +} + +/* TW: Set I2C stop condition */ +/* TW: This is done by a SD low-to-high transition while SC is high */ +USHORT +SiS_SetStop(SiS_Private *SiS_Pr) +{ + if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* TW: (SC->low) */ + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index, + ~SiS_Pr->SiS_DDC_Data,0x00); /* TW: SD->low */ + if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* TW: SC->high */ + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index, + ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data); /* TW: SD->high = stop condition */ + if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* TW: (SC->high) */ + return 0; +} + +/* TW: Write 8 bits of data */ +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); /* TW: SC->low */ + if(tempax & flag) { + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index, + ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data); /* TW: Write bit (1) to SD */ + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index, + ~SiS_Pr->SiS_DDC_Data,0x00); /* TW: Write bit (0) to SD */ + } + SiS_SetSCLKHigh(SiS_Pr); /* TW: SC->high */ + flag >>= 1; + } + temp = SiS_CheckACK(SiS_Pr); /* TW: Check acknowledge */ + return(temp); +} + +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_Data,SiS_Pr->SiS_DDC_Data); + SiS_SetSCLKHigh(SiS_Pr); + temp = SiS_GetReg1(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); + if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01; + } + return(getdata); +} + +USHORT +SiS_SetSCLKLow(SiS_Private *SiS_Pr) +{ + USHORT temp, watchdog=50000; + + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index, + ~SiS_Pr->SiS_DDC_Clk,0x00); /* SetSCLKLow() */ + do { + temp = SiS_GetReg1(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); + } while((temp & SiS_Pr->SiS_DDC_Clk) && --watchdog); + if (!watchdog) return 0xFFFF; + SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT); + return 0; +} + +USHORT +SiS_SetSCLKHigh(SiS_Private *SiS_Pr) +{ + USHORT temp,watchdog=50000; + + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index, + ~SiS_Pr->SiS_DDC_Clk,SiS_Pr->SiS_DDC_Clk); /* SetSCLKHigh() */ + do { + temp = SiS_GetReg1(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); + } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog); + if (!watchdog) return 0xFFFF; + SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT); + return 0; +} + +void +SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime) +{ + USHORT i; + + for(i=0; i<delaytime; i++) { + SiS_GetReg1(SiS_Pr->SiS_P3c4,0x05); + } +} + +/* TW: Check I2C acknowledge */ +/* Returns 0 if ack ok, non-0 if ack not ok */ +USHORT +SiS_CheckACK(SiS_Private *SiS_Pr) +{ + USHORT tempah; + + SiS_SetSCLKLow(SiS_Pr); /* TW: (SC->low) */ + SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index, + ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data); /* TW: (SD->high) */ + SiS_SetSCLKHigh(SiS_Pr); /* TW: SC->high = clock impulse for ack */ + tempah = SiS_GetReg1(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);/* TW: Read SD */ + SiS_SetSCLKLow(SiS_Pr); /* TW: SC->low = end of clock impulse */ + if(tempah & SiS_Pr->SiS_DDC_Data) return(1); /* TW: Ack OK if bit = 0 */ + else return(0); +} + +/* TW: End of I2C functions ----------------------- */ + + +/* =============== SiS 310/325 O.E.M. ================= */ + +#ifdef SIS315H + +static USHORT +GetLCDPtrIndex(SiS_Private *SiS_Pr) +{ + USHORT index; + + index = SiS_Pr->SiS_LCDResInfo & 0x0F; + index--; + index *= 3; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) index += 2; + else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++; + + return index; +} + +/* +--------------------------------------------------------- + GetTVPtrIndex() + return 0 : NTSC Enhanced/Standard + 1 : NTSC Standard TVSimuMode + 2 : PAL Enhanced/Standard + 3 : PAL Standard TVSimuMode + 4 : HiVision Enhanced/Standard + 5 : HiVision Standard TVSimuMode +--------------------------------------------------------- +*/ +static USHORT +GetTVPtrIndex(SiS_Private *SiS_Pr) +{ + USHORT index; + + index = 0; + if(SiS_Pr->SiS_VBInfo & SetPALTV) index++; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) index++; /* Hivision TV use PAL */ + + index <<= 1; + + if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (SiS_Pr->SiS_SetFlag & TVSimuMode)) + index++; + + return index; +} + +/* TW: Checked against 650/LVDS (1.10.07) and 650/301LVx (1.10.6s) BIOS (including data) */ +static void +SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr, USHORT ModeNo) +{ + USHORT delay,index,temp,romptr=0; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { + if((ROMAddr) && SiS_Pr->SiS_UseROM) { + if(HwDeviceExtension->jChipType != SIS_330) { + romptr = ROMAddr[0x128] | (ROMAddr[0x129] << 8); /* 301, LVDS */ + if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS302B)) + romptr = ROMAddr[0x12a] | (ROMAddr[0x12b] << 8); + } else { + romptr = ROMAddr[0x1a8] | (ROMAddr[0x1a9] << 8); /* 301, LVDS */ + if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS302B)) + romptr = ROMAddr[0x1aa] | (ROMAddr[0x1ab] << 8); + } + } + if(romptr) delay = ROMAddr[romptr]; + else { + delay = SiS310_CRT2DelayCompensation1; + if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS302B)) + delay = SiS310_CRT2DelayCompensation2; + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) + delay = SiS310_CRT2DelayCompensation3; + } + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + index = GetLCDPtrIndex(SiS_Pr); + delay = SiS310_LCDDelayCompensation1[index]; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) + delay = SiS310_LCDDelayCompensation2[index]; + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) + delay = SiS310_LCDDelayCompensation3[index]; + if((IS_SIS650740) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) { + if(SiS_IsM650or651(SiS_Pr,HwDeviceExtension, BaseAddr)) { + delay = SiS310_LCDDelayCompensation4[index]; /* 652c */ + if(SiS_Pr->SiS_VBType & VB_SIS30xNEW) + delay = SiS310_LCDDelayCompensation5[index]; /* 6541 */ + } else { + delay = SiS310_LCDDelayCompensation6[index]; /* 6550 */ + if(SiS_Pr->SiS_VBType & VB_SIS30xNEW) + delay = SiS310_LCDDelayCompensation7[index]; /* 655f */ + } + } + } else { + index = GetTVPtrIndex(SiS_Pr); + if((ROMAddr) && SiS_Pr->SiS_UseROM) { + if(HwDeviceExtension->jChipType != SIS_330) { + romptr = ROMAddr[0x114] | (ROMAddr[0x115] << 8); + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) + romptr = ROMAddr[0x11a] | (ROMAddr[0x11b] << 8); + } else { + romptr = ROMAddr[0x194] | (ROMAddr[0x195] << 8); + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) + romptr = ROMAddr[0x19a] | (ROMAddr[0x19b] << 8); + } + } + if(romptr) delay = ROMAddr[romptr + index]; + else { + delay = SiS310_TVDelayCompensation1[index]; + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) + delay = SiS310_TVDelayCompensation2[index]; + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) + delay = SiS310_TVDelayCompensation3[index]; + } + if((IS_SIS650740) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) { + romptr = 0; + if(SiS_IsM650or651(SiS_Pr,HwDeviceExtension, BaseAddr)) { + if((ROMAddr) && SiS_Pr->SiS_UseROM) { + romptr = ROMAddr[0x114] | (ROMAddr[0x115] << 8); + if(SiS_Pr->SiS_VBType & VB_SIS30xNEW) + romptr = ROMAddr[0x11a] | (ROMAddr[0x11b] << 8); + } + if(romptr) delay = ROMAddr[romptr + index]; + else { + delay = SiS310_TVDelayCompensation4[index]; /* 656e @ 0x114 */ + if(SiS_Pr->SiS_VBType & VB_SIS30xNEW) + delay = SiS310_TVDelayCompensation5[index]; /* 6574 @ 0x11a */ + } + } else { + delay = SiS310_TVDelayCompensation6[index]; /* 657a */ + if(SiS_Pr->SiS_VBType & VB_SIS30xNEW) + delay = SiS310_TVDelayCompensation7[index]; /* 6580 */ + } + } + } + + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay); + } else { + if(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); + } + } + } else { + if((IS_SIS650740) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) { + temp = (SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4; + if(temp == 8) { + delay &= 0x0f; + delay |= 0xb0; + } else if(temp == 6) { + delay &= 0x0f; + delay |= 0xc0; + } + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2D,delay); /* index 2D D[3:0] */ + } else { + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay); + } + } +} + +/* TW: Checked against 650/301LVx 1.10.6s BIOS (including data) */ +static void +SetAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT index,temp,romptr=0; + + temp = GetTVPtrIndex(SiS_Pr); + temp >>= 1; /* 0: NTSC, 1: PAL, 2: HiTV */ + + if(ModeNo<=0x13) + index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex; + else + index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex; + + if(ROMAddr && SiS_Pr->SiS_UseROM) { + romptr = ROMAddr[0x112] | (ROMAddr[0x113] << 8); + if(HwDeviceExtension->jChipType == SIS_330) { + romptr = ROMAddr[0x192] | (ROMAddr[0x193] << 8); + } + } + + if(romptr) { + temp <<= 1; + temp = ROMAddr[romptr + temp + index]; + } else { + temp = SiS310_TVAntiFlick1[temp][index]; + } + temp <<= 4; + + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp); /* index 0A D[6:4] */ +} + +/* TW: Checked against 650/301LVx 1.10.6s BIOS (including data) */ +static void +SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT index,temp,romptr=0; + + temp = GetTVPtrIndex(SiS_Pr); + temp >>= 1; /* 0: NTSC, 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(ROMAddr && SiS_Pr->SiS_UseROM) { + romptr = ROMAddr[0x124] | (ROMAddr[0x125] << 8); + if(HwDeviceExtension->jChipType == SIS_330) { + romptr = ROMAddr[0x1a4] | (ROMAddr[0x1a5] << 8); + } + } + + if(romptr) { + temp <<= 1; + temp = ROMAddr[romptr + temp + index]; + } else { + temp = SiS310_TVEdge1[temp][index]; + } + temp <<= 5; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp); /* index 0A D[7:5] */ +} + +/* TW: Checked against 650/301LVx 1.10.6s BIOS (incl data) */ +static void +SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT index, temp, i, j; + UCHAR OutputSelect = *SiS_Pr->pSiS_OutputSelect; + + temp = GetTVPtrIndex(SiS_Pr); + temp >>= 1; /* 0: NTSC, 1: PAL, 2: HiTV */ + + if (ModeNo<=0x13) { + index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex; + } else { + index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex; + } + + if(SiS_Pr->SiS_VBInfo&SetCRT2ToHiVisionTV) temp = 1; /* Hivision TV uses PAL */ + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + for(i=0x35, j=0; i<=0x38; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]); + } + for(i=0x48; i<=0x4A; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]); + } + } else { + for(i=0x35, j=0; i<=0x38; i++, j++){ + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]); + } + } + + if(ROMAddr && SiS_Pr->SiS_UseROM) { + OutputSelect = ROMAddr[0xf3]; + if(HwDeviceExtension->jChipType == SIS_330) { + OutputSelect = ROMAddr[0x11b]; + } + } + if(OutputSelect & EnablePALMN) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x01) { + temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); + temp &= (EnablePALM | EnablePALN); + if(temp == EnablePALM) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + for(i=0x35, j=0; i<=0x38; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS310_PALMFilter2[index][j]); + } + for(i=0x48; i<=0x4A; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS310_PALMFilter2[index][j]); + } + } else { + for(i=0x35, j=0; i<=0x38; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS310_PALMFilter[index][j]); + } + } + } + if(temp == EnablePALN) { + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + for(i=0x35, j=0; i<=0x38; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS310_PALNFilter2[index][j]); + } + for(i=0x48, j=0; i<=0x4A; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS310_PALNFilter2[index][j]); + } + } else { + for(i=0x35, j=0; i<=0x38; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS310_PALNFilter[index][j]); + } + } + } + } + } +} + +/* TW: Checked against 650/301LVx 1.10.6s BIOS (including data) */ +static void +SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT index,temp,temp1,i,j,resinfo,romptr=0; + + if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return; + + temp1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); /* if PALM/N not set */ + temp1 &= (EnablePALM | EnablePALN); + if(temp1) 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((ROMAddr) && SiS_Pr->SiS_UseROM) { + romptr = ROMAddr[0x116] | (ROMAddr[0x117] << 8); + if(HwDeviceExtension->jChipType == SIS_330) { + romptr = ROMAddr[0x196] | (ROMAddr[0x197] << 8); + } + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + romptr = ROMAddr[0x11c] | (ROMAddr[0x11d] << 8); + if(HwDeviceExtension->jChipType == SIS_330) { + romptr = ROMAddr[0x19c] | (ROMAddr[0x19d] << 8); + } + if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_SetFlag & TVSimuMode))) { + romptr = ROMAddr[0x116] | (ROMAddr[0x117] << 8); + if(HwDeviceExtension->jChipType == SIS_330) { + romptr = ROMAddr[0x196] | (ROMAddr[0x197] << 8); + } + } + } + } + if(romptr) { + romptr += (temp << 2); + for(j=0, i=0x31; i<=0x34; i++, j++) { + SiS_SetReg1(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_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]); + else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_SetFlag & TVSimuMode)) + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]); + else + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]); + } + } + + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* TW: 650/301LV: (VB_SIS301LV | VB_SIS302LV)) */ + if((!(SiS_Pr->SiS_VBInfo & SetPALTV)) && (ModeNo > 0x13)) { + if(resinfo == 6) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x31,0x21); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x32,0xf0); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x33,0xf5); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x34,0x7f); + } else if (resinfo == 7) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x31,0x21); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x32,0xf0); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x33,0xf5); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x34,0x7f); + } else if (resinfo == 8) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x31,0x1e); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x32,0x8b); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x33,0xfb); + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x34,0x7b); + } + } + } +} + +void +SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + SetDelayComp(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo); + /* TW: The TV functions are not for LVDS */ + if( (SiS_Pr->SiS_IF_DEF_LVDS == 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) { + SetAntiFlicker(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex); + SetPhaseIncr(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex); + SetYFilter(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex); + if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) { + SetEdgeEnhance(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex); + } + } +} + +/* TW: New from 650/301LVx 1.10.6s, 1.10.7w - clashes with OEMLCD() */ +void +SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + USHORT ModeIdIndex, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + USHORT tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp; + USHORT resinfo,modeflag; + + if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) 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(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) { + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x2a,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10); + } + tempch = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36); + tempch &= 0xf0; + tempch >>= 4; + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1f,0x76); + } + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) { /* From 1.10.8w */ + if(!(SiS_Pr->SiS_LCDInfo & LCDNonExpanding)) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x14,0x90); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,0x01); + if((ModeNo > 0x13) && (resinfo == 8)) { + tempbx = 806; /* 0x326 */ + tempbx--; + temp = tempbx & 0xff; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1b,temp); + temp = (tempbx >> 8) & 0x03; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp); + } + } else { + if(ModeNo <= 0x13) { + if(ModeNo <= 1) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,0x70); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x19,0xff); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1b,0x48); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1d,0x12); + } + if(!(modeflag & HalfDCLK)) { + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x14,0x20); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x15,0x1a); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x16,0x28); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x17,0x00); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,0x4c); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x19,0xdc); + if(ModeNo == 0x12) { + switch(tempch) { + case 0: + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,0x95); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x19,0xdc); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1a,0x10); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1b,0x95); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1c,0x48); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1d,0x12); + break; + case 2: + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,0x95); + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1b,0x48); + break; + case 3: + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1b,0x95); + break; + } + } + } + } + } + } + } else { + tempcl = tempbh = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x01); + tempcl &= 0x0f; + tempbh &= 0x70; + tempbh >>= 4; + tempbl = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x04); + tempbx = (tempbh << 8) | tempbl; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) { + if((resinfo == 8) || (!(SiS_Pr->SiS_LCDInfo & LCDNonExpanding))) { + 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; /* From 1.10.7w; 1.10.6s: 3; */ + if(SiS_Pr->SiS_VGAVDE <= 480) tempax >>= 4; /* From 1.10.7w; 1.10.6s: < 480; >>=1; */ + tempbx -= tempax; + } + } + } else return; + } +#if 0 + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { + } +#endif + temp = tempbx & 0xff; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x04,temp); + temp = (tempbx & 0xff00) >> 8; + temp <<= 4; + temp |= tempcl; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp); + } + } +} + +/* TW: New and checked from 650/301LV BIOS */ +/* This might clash with newer "FinalizeLCD()" function */ +void +SiS_OEMLCD(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT tempbx,tempah,tempbl,tempbh,tempcl; + + if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { + SiS_UnLockCRT2(SiS_Pr,HwDeviceExtension,BaseAddr); + tempbh = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x1a); + tempbh &= 0x38; + tempbh >>= 3; + tempbl = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x18); + tempbx = (tempbh << 8) | tempbl; + if(SiS_Pr->SiS_LCDTypeInfo == 1) tempbx -= 0x12; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,tempbx & 0x00ff); + tempah = (tempbx & 0xff00) >> 8; + tempah &= 0x07; + tempah <<= 3; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0xc7,tempah); + tempah = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x19); + tempah &= 0x0f; + if(SiS_Pr->SiS_LCDTypeInfo == 1) tempah -= 2; + tempah &= 0x0f; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,tempah); + tempah = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x14); + if(SiS_Pr->SiS_LCDTypeInfo == 1) tempah++; + tempah -= 8; + SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x14,tempah); + } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + tempcl = tempbh = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x01); + tempbh &= 0x70; + tempbh >>= 4; + tempbl = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x04); + tempbx = (tempbh << 8) | tempbl; + if(SiS_Pr->SiS_LCDTypeInfo == 1) { + tempbx -= 0x1e; + tempcl &= 0x0f; + tempcl -= 4; + tempcl &= 0x0f; + } + tempbl = tempbx & 0x00ff; + tempbh = (tempbx >> 8) & 0x00ff; + SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x04,tempbl); + tempbh <<= 4; + tempbh |= tempcl; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,tempbh); + } +} +#endif + + +/* ================= SiS 300 O.E.M. ================== */ + +#ifdef SIS300 + +#if 0 /* Not used */ +static USHORT +GetRevisionID(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension) +{ + ULONG temp1; +#ifndef LINUX_XF86 + ULONG base; +#endif + USHORT temp2 = 0; + + if((HwDeviceExtension->jChipType==SIS_540)|| + (HwDeviceExtension->jChipType==SIS_630)|| + (HwDeviceExtension->jChipType==SIS_730)) { +#ifndef LINUX_XF86 + base = 0x80000008; + OutPortLong(base,0xcf8); + temp1 = InPortLong(0xcfc); +#else + temp1=pciReadLong(0x00000000, 0x08); +#endif + temp1 &= 0x000000FF; + temp2 = (USHORT)(temp1); + return temp2; + } + return 0; +} +#endif + +/* TW: Checked against 630/301B BIOS (incl data) */ +static USHORT +GetOEMLCDPtr(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, UCHAR *ROMAddr, int Flag) +{ + 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(HwDeviceExtension->jChipType == SIS_300) { + + tempbx = SiS_Pr->SiS_LCDResInfo - 2; + if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4; + if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) { + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx += 3; + } + if((ROMAddr) && SiS_Pr->SiS_UseROM) { + if(ROMAddr[0x235] & 0x80) { + tempbx = SiS_Pr->SiS_LCDTypeInfo; + if(Flag) { + romptr = ROMAddr[0x255] | (ROMAddr[0x256] << 8); + 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((ROMAddr) && SiS_Pr->SiS_UseROM) { + romptr = ROMAddr[0x255] | (ROMAddr[0x256] << 8); + 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 & LCDNonExpanding) tempbx++; + return tempbx; + } + tempbx = SiS_Pr->SiS_LCDTypeInfo << 2; + if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2; + if(SiS_Pr->SiS_LCDInfo & LCDNonExpanding) tempbx++; + } + return tempbx; +} + +/* TW: Checked against 630/301B and 630/LVDS BIOS (incl data) */ +static void +SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT index,temp,romptr=0; + + if((ROMAddr) && SiS_Pr->SiS_UseROM) { + if(!(ROMAddr[0x237] & 0x01)) return; + if(!(ROMAddr[0x237] & 0x02)) return; + romptr = ROMAddr[0x24b] | (ROMAddr[0x24c] << 8); + } + + /* TW: 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(HwDeviceExtension->pdc) return; + + temp = GetOEMLCDPtr(SiS_Pr,HwDeviceExtension, ROMAddr, 0); + + index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex; + + if(HwDeviceExtension->jChipType != SIS_300) { + if(romptr) { + romptr += (temp * 2); + romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8); + romptr += index; + temp = ROMAddr[romptr]; + } else { + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + temp = SiS300_OEMLCDDelay2[temp][index]; + } else { + temp = SiS300_OEMLCDDelay3[temp][index]; + } + } + } else { + if((ROMAddr) && SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) { + if(romptr) { + romptr += (temp * 2); + romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8); + romptr += index; + temp = ROMAddr[romptr]; + } else { + temp = SiS300_OEMLCDDelay5[temp][index]; + } + } else { + if((ROMAddr) && SiS_Pr->SiS_UseROM) { + romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8); + if(romptr) { + romptr += (temp * 2); + romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8); + 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_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ +#if 0 /* TW: Unfinished; VData table missing */ + USHORT index,temp; + + if((ROMAddr) && SiS_Pr->SiS_UseROM) { + if(!(ROMAddr[0x237] & 0x01)) return; + if(!(ROMAddr[0x237] & 0x04)) return; + /* No rom pointer in BIOS header! */ + } + + temp = GetOEMLCDPtr(SiS_Pr,HwDeviceExtension, ROMAddr, 1); + if(temp = 0xFFFF) return; + + index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex; + for(i=0x14, j=0; i<=0x17; i++, j++) { + SiS_SetReg1(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_SetReg1(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_SetReg1(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]); + } +#endif +} + +/* TW: Checked against 630/301B 2.04.50 and 630/LVDS BIOS */ +static USHORT +GetOEMTVPtr(SiS_Private *SiS_Pr) +{ + USHORT index; + + index = 0; + if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) index += 4; + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) index += 2; + else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) index += 3; + else if(SiS_Pr->SiS_VBInfo & SetPALTV) index += 1; + } else { + if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) index += 2; + if(SiS_Pr->SiS_VBInfo & SetPALTV) index += 1; + } + return index; +} + +/* TW: Checked against 630/301B 2.04.50 and 630/LVDS BIOS (incl data) */ +static void +SetOEMTVDelay(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT index,temp,romptr=0; + + if((ROMAddr) && SiS_Pr->SiS_UseROM) { + if(!(ROMAddr[0x238] & 0x01)) return; + if(!(ROMAddr[0x238] & 0x02)) return; + romptr = ROMAddr[0x241] | (ROMAddr[0x242] << 8); + } + + temp = GetOEMTVPtr(SiS_Pr); + + index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex; + + if(romptr) { + romptr += (temp * 2); + romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8); + romptr += index; + temp = ROMAddr[romptr]; + } else { + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + temp = SiS300_OEMTVDelay301[temp][index]; + } else { + temp = SiS300_OEMTVDelayLVDS[temp][index]; + } + } + temp &= 0x3c; + SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* index 0A D[6:4] */ +} + +/* TW: Checked against 630/301B 2.04.50 BIOS (incl data) */ +static void +SetOEMAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + USHORT ModeIdIndex) +{ + USHORT index,temp,romptr=0; + + if((ROMAddr) && SiS_Pr->SiS_UseROM) { + if(!(ROMAddr[0x238] & 0x01)) return; + if(!(ROMAddr[0x238] & 0x04)) return; + romptr = ROMAddr[0x243] | (ROMAddr[0x244] << 8); + } + + temp = GetOEMTVPtr(SiS_Pr); + + index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex; + + if(romptr) { + romptr += (temp * 2); + romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8); + romptr += index; + temp = ROMAddr[romptr]; + } else { + temp = SiS300_OEMTVFlicker[temp][index]; + } + temp &= 0x70; + SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp); /* index 0A D[6:4] */ +} + +/* TW: Checked against 630/301B 2.04.50 BIOS (incl data) */ +static void +SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT index,i,j,temp,romptr=0; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) return; + + if((ROMAddr) && SiS_Pr->SiS_UseROM) { + if(!(ROMAddr[0x238] & 0x01)) return; + if(!(ROMAddr[0x238] & 0x08)) return; + romptr = ROMAddr[0x245] | (ROMAddr[0x246] << 8); + } + + 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_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]); + } + } else { + if(romptr) { + romptr += (temp * 2); + romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8); + romptr += (index * 4); + for(i=0x31, j=0; i<=0x34; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]); + } + } else { + for(i=0x31, j=0; i<=0x34; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]); + } + } + } +} + +/* TW: Checked against 630/301B 2.04.50 BIOS (incl data) */ +static void +SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex) +{ + USHORT index,temp,temp1,i,j,romptr=0; + + if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVisionTV)) return; + + if((ROMAddr) && SiS_Pr->SiS_UseROM) { + if(!(ROMAddr[0x238] & 0x01)) return; + if(!(ROMAddr[0x238] & 0x10)) return; + romptr = ROMAddr[0x247] | (ROMAddr[0x248] << 8); + } + + temp = GetOEMTVPtr(SiS_Pr); + + index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex; + + if(HwDeviceExtension->jChipType > SIS_300) { + if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x01) { + temp1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x35); + if(temp1 & (EnablePALM | EnablePALN)) { + temp = 8; + if(!(temp1 & EnablePALM)) temp = 9; + } + } + } + if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { + for(i=0x35, j=0; i<=0x38; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]); + } + for(i=0x48; i<=0x4A; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]); + } + } else { + if(romptr) { + romptr += (temp * 2); + romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8); + romptr += (index * 4); + for(i=0x35, j=0; i<=0x38; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]); + } + } else { + for(i=0x35, j=0; i<=0x38; i++, j++) { + SiS_SetReg1(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]); + } + } + } +} + +void +SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo) +{ + USHORT ModeIdIndex; + + ModeIdIndex = SiS_SearchVBModeID(SiS_Pr,ROMAddr,&ModeNo); + if(!(ModeIdIndex)) return; + + if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { + SetOEMLCDDelay(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex); + if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { + SetOEMLCDData(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex); + } + } + if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { + SetOEMTVDelay(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex); + if(SiS_Pr->SiS_IF_DEF_LVDS == 0) { + SetOEMAntiFlicker(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex); + SetOEMPhaseIncr(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex); + SetOEMYFilter(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex); + } + } +} +#endif + + diff --git a/src/init301.h b/src/init301.h new file mode 100644 index 0000000..2cbb39d --- /dev/null +++ b/src/init301.h @@ -0,0 +1,285 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/init301.h,v 1.9 2003/02/04 02:44:28 dawes Exp $ */ +#ifndef _INIT301_ +#define _INIT301_ + +#include "osdef.h" +#include "initdef.h" +#include "vgatypes.h" +#include "vstruct.h" + +#ifdef TC +#include <stdio.h> +#include <string.h> +#include <conio.h> +#include <dos.h> +#include <stdlib.h> +#endif + +#ifdef LINUX_XF86 +#include "xf86.h" +#include "xf86Pci.h" +#include "xf86PciInfo.h" +#include "sis.h" +#include "sis_regs.h" +#endif + +#ifdef LINUX_KERNEL +#include <asm/io.h> +#include <linux/types.h> +#include <linux/sisfb.h> +#endif + +#ifdef WIN2000 +#include <stdio.h> +#include <string.h> +#include <miniport.h> +#include "dderror.h" +#include "devioctl.h" +#include "miniport.h" +#include "ntddvdeo.h" +#include "video.h" +#include "sisv.h" +#endif + +#if 0 +extern const USHORT SiS_MDA_DAC[]; +extern const USHORT SiS_CGA_DAC[]; +extern const USHORT SiS_EGA_DAC[]; +extern const USHORT SiS_VGA_DAC[]; +#endif + +extern BOOLEAN SiS_SearchVBModeID(SiS_Private *SiS_Pr, UCHAR *RomAddr, USHORT *); + +BOOLEAN SiS_Is301B(SiS_Private *SiS_Pr, USHORT BaseAddr); +BOOLEAN SiS_IsM650or651(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +BOOLEAN SiS_IsDisableCRT2(SiS_Private *SiS_Pr, USHORT BaseAddr); +BOOLEAN SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +BOOLEAN SiS_IsDualEdge(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +BOOLEAN SiS_CRT2IsLCD(SiS_Private *SiS_Pr, USHORT BaseAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetDefCRT2ExtRegs(SiS_Private *SiS_Pr, USHORT BaseAddr); +USHORT SiS_GetRatePtrCRT2(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +BOOLEAN SiS_AdjustCRT2Rate(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT MODEIdIndex, + USHORT RefreshRateTableIndex,USHORT *i,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SaveCRT2Info(SiS_Private *SiS_Pr, USHORT ModeNo); +void SiS_GetCRT2Data(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_GetCRT2PtrA(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *CRT2Index,USHORT *ResIndex); +void SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *CRT2Index, USHORT *ResIndex); +void SiS_GetCRT2Data301(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +USHORT SiS_GetResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex); +void SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_GetCRT2Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *CRT2Index,USHORT *ResIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT BaseAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO ); +void SiS_SetHiVision(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_GetLVDSDesData(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetCRT2Offset(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +USHORT SiS_GetOffset(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +USHORT SiS_GetColorDepth(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex); +USHORT SiS_GetMCLK(SiS_Private *SiS_Pr, UCHAR *ROMAddr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +USHORT SiS_CalcDelayVB(SiS_Private *SiS_Pr); +USHORT SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetRegANDOR(USHORT Port,USHORT Index,USHORT DataAND,USHORT DataOR); +void SiS_SetRegOR(USHORT Port,USHORT Index,USHORT DataOR); +void SiS_SetRegAND(USHORT Port,USHORT Index,USHORT DataAND); +USHORT SiS_GetVGAHT2(SiS_Private *SiS_Pr); +void SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT ModeIdIndex, USHORT RefreshRateTableIndex, + USHORT BaseAddr, USHORT ModeNo); +void SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetGroup5(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + USHORT ModeIdIndex); +void SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_EnableCRT2(SiS_Private *SiS_Pr); +void SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension, int checkcrt2mode); +BOOLEAN SiS_BridgeIsOn(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO); +BOOLEAN SiS_BridgeIsEnable(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO); +BOOLEAN SiS_BridgeInSlave(SiS_Private *SiS_Pr); +void SiS_PresetScratchregister(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetTVSystem(SiS_Private *SiS_Pr); +void SiS_LongWait(SiS_Private *SiS_Pr); +USHORT SiS_GetQueueConfig(SiS_Private *SiS_Pr); +void SiS_VBLongWait(SiS_Private *SiS_Pr); +USHORT SiS_GetVCLKLen(SiS_Private *SiS_Pr, UCHAR *ROMAddr); +void SiS_WaitVBRetrace(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_WaitRetrace1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_WaitRetrace2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_WaitRetraceDDC(SiS_Private *SiS_Pr); +void SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_GetLVDSDesPtr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *PanelIndex,USHORT *ResIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_GetLVDSDesPtrA(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *PanelIndex,USHORT *ResIndex); +void SiS_SetTPData(SiS_Private *SiS_Pr); +void SiS_WhatIsThis(SiS_Private *SiS_Pr, USHORT myvbinfo); +void SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetCHTVReg(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex); +void SiS_GetCHTVRegPtr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex); +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); +#ifdef LINUX_XF86 +USHORT SiS_I2C_GetByte(SiS_Private *SiS_Pr); +Bool SiS_I2C_PutByte(SiS_Private *SiS_Pr, USHORT data); +Bool SiS_I2C_Address(SiS_Private *SiS_Pr, USHORT addr); +void SiS_I2C_Stop(SiS_Private *SiS_Pr); +#endif +void SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh); +void SiS_SetSwitchDDC2(SiS_Private *SiS_Pr); +USHORT SiS_SetStart(SiS_Private *SiS_Pr); +USHORT SiS_SetStop(SiS_Private *SiS_Pr); +void SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime); +USHORT SiS_SetSCLKLow(SiS_Private *SiS_Pr); +USHORT SiS_SetSCLKHigh(SiS_Private *SiS_Pr); +USHORT SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax); +USHORT SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax); +USHORT SiS_CheckACK(SiS_Private *SiS_Pr); +USHORT SiS_ReadLCDDDC(SiS_Private *SiS_Pr, USHORT length, unsigned char *buffer); +#ifdef SIS315H +void SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex); +void SiS_OEMLCD(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex); +#endif +#ifdef SIS300 +void SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr, + UCHAR *ROMAddr,USHORT ModeNo); +#endif +BOOLEAN SiS_LowModeStuff(SiS_Private *SiS_Pr, USHORT ModeNo,PSIS_HW_DEVICE_INFO HwDeviceExtension); + +BOOLEAN SiS_GetLCDResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo, USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +/* void SiS_CHACRT1CRTC(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex); */ + +BOOLEAN SiS_SetCRT2Group301(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex); +void SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex); +void SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex); +void SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex); +#ifdef SIS300 +void SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +#endif +#ifdef SIS315H +void SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo, + PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_CRT2AutoThreshold(SiS_Private *SiS_Pr, USHORT BaseAddr); +#endif +BOOLEAN SiS_GetLCDDDCInfo(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO,USHORT BaseAddr); +void SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO,USHORT BaseAddr); +void SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO,USHORT BaseAddr); +void SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO,USHORT BaseAddr); +void SiS_SetPanelDelay(SiS_Private *SiS_Pr, UCHAR* ROMAddr,PSIS_HW_DEVICE_INFO,USHORT DelayTime); +void SiS_ShortDelay(SiS_Private *SiS_Pr, USHORT delay); +void SiS_LongDelay(SiS_Private *SiS_Pr, USHORT delay); +void SiS_GenericDelay(SiS_Private *SiS_Pr, USHORT delay); +void SiS_VBWait(SiS_Private *SiS_Pr); + +void SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +void SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); + +/* TW: New functions (with mostly temporary names) */ +void SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr); +void SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + USHORT BaseAddr); +void SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr); +void SiS_Chrontel701xOff(SiS_Private *SiS_Pr); +void SiS_ChrontelResetDB(SiS_Private *SiS_Pr); +void SiS_ChrontelDoSomething4(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +void SiS_ChrontelDoSomething3(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +void SiS_ChrontelDoSomething2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +void SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +BOOLEAN SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +#if 0 +BOOLEAN SiS_IsSomethingCR5F(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +#endif +BOOLEAN SiS_IsYPbPr(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +BOOLEAN SiS_IsChScart(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +BOOLEAN SiS_IsTVOrYPbPrOrScart(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +BOOLEAN SiS_IsLCDOrLCDA(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +void SiS_SetCH701xForLCD(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr); +void SiS_ChrontelPowerSequencing(SiS_Private *SiS_Pr); +BOOLEAN SiS_CR36BIOSWord23b(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +BOOLEAN SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +BOOLEAN SiS_IsSR13_CR30(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +/* TW end */ + +extern void SiS_SetReg1(USHORT, USHORT, USHORT); +extern void SiS_SetReg3(USHORT, USHORT); +extern UCHAR SiS_GetReg1(USHORT, USHORT); +extern UCHAR SiS_GetReg2(USHORT); +extern BOOLEAN SiS_SearchModeID(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT *ModeNo,USHORT *ModeIdIndex); +extern BOOLEAN SiS_GetRatePtr(SiS_Private *SiS_Pr, ULONG, USHORT); +extern void SiS_SetReg4(USHORT, ULONG); +extern ULONG SiS_GetReg3(USHORT); +extern void SiS_SetReg5(USHORT, USHORT); +extern USHORT SiS_GetReg4(USHORT); +extern void SiS_DisplayOff(SiS_Private *SiS_Pr); +extern void SiS_DisplayOn(SiS_Private *SiS_Pr); +extern UCHAR SiS_GetModePtr(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT ModeNo,USHORT ModeIdIndex); +extern BOOLEAN SiS_GetLCDACRT1Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *ResInfo,USHORT *DisplayType); +extern BOOLEAN SiS_GetLVDSCRT1Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, + USHORT RefreshRateTableIndex,USHORT *ResInfo,USHORT *DisplayType); +extern void SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO, UCHAR *ROMAddr,USHORT ModeNo, + USHORT ModeIdIndex); +#ifdef SIS315H +extern UCHAR SiS_Get310DRAMType(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension); +#endif + +#ifdef LINUX_XF86 +/* DDC functions */ +USHORT SiS_InitDDCRegs(SiS_Private *SiS_Pr, SISPtr pSiS, USHORT adaptnum, USHORT DDCdatatype); +USHORT SiS_WriteDABDDC(SiS_Private *SiS_Pr); +USHORT SiS_PrepareReadDDC(SiS_Private *SiS_Pr); +USHORT SiS_PrepareDDC(SiS_Private *SiS_Pr); +void SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno); +USHORT SiS_DoProbeDDC(SiS_Private *SiS_Pr); +USHORT SiS_ProbeDDC(SiS_Private *SiS_Pr); +USHORT SiS_ReadDDC(SiS_Private *SiS_Pr, SISPtr pSiS, USHORT DDCdatatype, unsigned char *buffer); +USHORT SiS_HandleDDC(SiS_Private *SiS_Pr, SISPtr pSiS, USHORT adaptnum, + USHORT DDCdatatype, unsigned char *buffer); +#endif + +#endif diff --git a/src/initdef.h b/src/initdef.h new file mode 100644 index 0000000..a2d796b --- /dev/null +++ b/src/initdef.h @@ -0,0 +1,434 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/initdef.h,v 1.9 2003/02/04 02:44:28 dawes Exp $ */ + + +#ifndef _INITDEF_ +#define _INITDEF_ + +#define SiS300 0x0300 +#define SiS540 0x5300 +#define SiS630 0x6300 +#define SiS730 0x6300 + +/* SiS_VBType */ +#define VB_SIS301 0x0001 +#define VB_SIS301B 0x0002 +#define VB_SIS302B 0x0004 +#define VB_SIS30xLV 0x0008 +#define VB_SIS30xNEW 0x0010 +#define VB_NoLCD 0x8000 +#define VB_SIS301BLV302BLV (VB_SIS301B|VB_SIS302B|VB_SIS30xLV|VB_SIS30xNEW) +#define VB_SIS301B302B (VB_SIS301B|VB_SIS302B) +#define VB_SIS301LV302LV (VB_SIS30xLV|VB_SIS30xNEW) + +#define IS_SIS650740 ((HwDeviceExtension->jChipType >= SIS_650) && (HwDeviceExtension->jChipType < SIS_330)) + +#define CRT1Len 17 +#define LVDSCRT1Len 15 +#define CHTVRegDataLen 5 + +/* 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 ModeInfoFlag 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 DoubleScanMode 0x8000 + +/* Infoflag */ +#define SupportAllCRT2 0x0078 +#define SupportTV 0x0008 +#define SupportHiVisionTV 0x0010 +#define SupportLCD 0x0020 +#define SupportRAMDAC2 0x0040 +#define NoSupportTV 0x0070 +#define NoSupportHiVisionTV 0x0060 +#define NoSupportLCD 0x0058 +#define SupportCHTV 0x0800 +#define SupportTV1024 0x0800 +#define InterlaceMode 0x0080 +#define SyncPP 0x0000 +#define SyncPN 0x4000 +#define SyncNP 0x8000 +#define SyncNN 0xc000 +#define ECLKindex0 0x0000 +#define ECLKindex1 0x0100 +#define ECLKindex2 0x0200 +#define ECLKindex3 0x0300 +#define ECLKindex4 0x0400 + +/* VBInfo */ +#define SetSimuScanMode 0x0001 /* CR 30 */ +#define SwitchToCRT2 0x0002 +#define SetCRT2ToAVIDEO 0x0004 +#define SetCRT2ToSVIDEO 0x0008 +#define SetCRT2ToSCART 0x0010 +#define SetCRT2ToLCD 0x0020 +#define SetCRT2ToRAMDAC 0x0040 +#define SetCRT2ToHiVisionTV 0x0080 +#define SetCRT2ToTV 0x009C /* alias */ +#define SetNTSCTV 0x0000 /* CR 31 */ +#define SetPALTV 0x0100 +#define SetInSlaveMode 0x0200 +#define SetNotSimuMode 0x0400 +#define SetNotSimuTVMode 0x0400 +#define SetDispDevSwitch 0x0800 +#define LoadDACFlag 0x1000 +#define SetCHTVOverScan 0x1000 /* TW: Re-defined (from 0x8000) */ +#define DisableCRT2Display 0x2000 +#define CRT2DisplayFlag 0x2000 +#define DriverMode 0x4000 +#define HotKeySwitch 0x8000 /* TW: ? */ +#define SetCRT2ToLCDA 0x8000 + +#define PanelRGB18Bit 0x0100 +#define PanelRGB24Bit 0x0000 + +#define TVOverScan 0x10 /* Bit in CR35 (300 series only) */ +#define TVOverScanShift 4 +#define ClearBufferFlag 0x20 + +/* CR32 (Newer 630, and 310/325 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] VB connected with DVI combo connector + + + 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 + 310/325 series + 001 SiS30x (never seen) + 010 LVDS + 011 LVDS + Chrontel 7019 + All other combinations reserved + [4] LVDS: Expanding(0)/Non-expanding(1) LCD display + 30x: SiS30x(0)/LCD monitor(1) scaling display + [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 +*/ + +/* CR38 (310/325 series) */ +#define EnableDualEdge 0x01 +#define SetToLCDA 0x02 /* LCD channel A (302B/LV and 650+LVDS only) */ +#define EnableSiSHiVision 0x04 /* HiVision (HDTV) on SiS bridge */ +#define EnableLVDSScart 0x04 /* Scart on Ch7019 (unofficial definition - TW) */ +#define EnableLVDSHiVision 0x08 /* YPbPr color format (480i HDTV); only on 650/Ch7019 systems */ +#define SiSHiVision1 0x10 /* See SetHiVision() */ +#define SiSHiVision2 0x20 +#define EnablePALM 0x40 /* 1 = Set PALM */ +#define EnablePALN 0x80 /* 1 = Set PALN */ + +#define SetSCARTOutput 0x01 +#define BoardTVType 0x02 + +#define EnablePALMN 0x40 /* Romflag: 1 = Allow PALM/PALN */ + +/* CR39 (650) */ +#define LCDPass1_1 0x01 /* LVDS only; set by driver to pass 1:1 data to LVDS output */ +#define SomeThingTV_LVNEW 0x04 /* 30xNEW only; set by mode switching function */ + + +/* CR79 (310/325 series only) + [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) + [5] PAL/NTSC (set by BIOS) + [6] Expansion On/Off (set by BIOS; copied to CR32[4]) + [7] TV UnderScan/OverScan (set by BIOS) +*/ + +/* SetFlag */ +#define ProgrammingCRT2 0x01 +#define TVSimuMode 0x02 +#define RPLLDIV2XO 0x04 +#define LCDVESATiming 0x08 +#define EnableLVDSDDA 0x10 +#define SetDispDevSwitchFlag 0x20 +#define CheckWinDos 0x40 +#define SetJDOSMode 0x80 +#define CRT2IsVGA 0x80 /* TW: Not sure about this name... */ + +/* 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_320x480 0x08 /* fstn - TW: This is fake, can be any */ + +#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 /* LVDS only */ +#define Panel310_1600x1200 0x0b +#define Panel310_320x480 0x0c /* fstn - TW: This is fake, can be any */ + +#define Panel_800x600 0x01 /* Unified values */ +#define Panel_1024x768 0x02 +#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 /* LVDS only */ +#define Panel_1600x1200 0x0b +#define Panel_320x480 0x0c /* fstn - TW: This is fake, can be any */ + +#define ExtChipType 0x0e +#define ExtChip301 0x02 +#define ExtChipLVDS 0x04 +#define ExtChipTrumpion 0x06 +#define ExtChipCH7005 0x08 +#define ExtChipMitacTV 0x0a /* TW: Incorrect, 0x0a = Chrontel 7005 only */ + +#define IsM650 0x80 /* TW: CR5F */ + +/* LCDInfo */ +#define LCDRGB18Bit 0x01 +#define LCDNonExpanding 0x10 +#define LCDNonExpandingShift 4 +#define LCDSync 0x20 +#define LCDPass11 0x100 +#define LCDSyncBit 0xe0 +#define LCDSyncShift 6 + +#define LCDDataLen 8 +#define HiTVDataLen 12 +#define TVDataLen 16 +#define SetPALTV 0x0100 +#define HalfDCLK 0x1000 /* modeflag */ +#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 + +#define VCLKStartFreq 25 +#define SoftDramType 0x80 + +#define VCLK40 0x04 /* Index in VCLKData array */ +#define VCLK65 0x09 /* Index in VCLKData array */ +#define VCLK108_2 0x14 /* Index in VCLKData array */ +#define TVVCLKDIV2 0x21 /* Indices in (VB)VCLKData arrays */ +#define TVVCLK 0x22 +#define HiTVVCLKDIV2 0x23 +#define HiTVVCLK 0x24 +#define HiTVSimuVCLK 0x25 +#define HiTVTextVCLK 0x26 + +#define LoadDACFlag 0x1000 +#define AfterLockCRT2 0x4000 +#define SetCRT2ToAVIDEO 0x0004 +#define SetCRT2ToSCART 0x0010 +#define Ext2StructSize 5 + +#define SetSCARTOutput 0x01 +#define AVIDEOSense 0x01 +#define SVIDEOSense 0x02 +#define SCARTSense 0x04 +#define LCDSense 0x08 +#define Monitor1Sense 0x20 +#define Monitor2Sense 0x10 +#define HiTVSense 0x40 +#define BoardTVType 0x02 +#define HotPlugFunction 0x08 +#define StStructSize 0x06 + +#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 LVDSDataLen 6 +#define EnableLVDSDDA 0x10 +#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 SelectCRT1Rate 0x4 + +#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 /* TW: 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 310/325 series + ============================================================= +*/ +#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/src/oem300.h b/src/oem300.h new file mode 100644 index 0000000..8f7e524 --- /dev/null +++ b/src/oem300.h @@ -0,0 +1,1005 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/oem300.h,v 1.3 2003/02/10 01:14:16 tsi Exp $ */ + +/* OEM Data for 300 series */ + +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} +}; + +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} +}; + +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 */ +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 + +/* TW: From 630/301B BIOS */ +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} +}; + +/* TW: From 300/301LV BIOS */ +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} +}; + +/* TW: From 300/301LV BIOS */ +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}, +}; + +/* TW: Added for LVDS */ +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} +}; + +const UCHAR SiS300_Phase1[8][6][4] = +{ + { + {0x21,0xed,0x00,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0xff,0xff,0xff,0xff} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0xff,0xff,0xff,0xff} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0xff,0xff,0xff,0xff} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0xff,0xff,0xff,0xff} + }, + { + {0x21,0xed,0x00,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0xff,0xff,0xff,0xff} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0xff,0xff,0xff,0xff} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0xff,0xff,0xff,0xff} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0xff,0xff,0xff,0xff} + } +}; + + +const UCHAR SiS300_Phase2[8][6][4] = +{ + { + {0x21,0xed,0x00,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0xff,0xff,0xff,0xff} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0xff,0xff,0xff,0xff} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0xff,0xff,0xff,0xff} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0xff,0xff,0xff,0xff} + }, + { + {0x21,0xed,0x00,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0x21,0xed,0x8a,0x08}, + {0xff,0xff,0xff,0xff} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0xff,0xff,0xff,0xff} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0xff,0xff,0xff,0xff} + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00}, + {0xff,0xff,0xff,0xff} + } +}; + +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} + }, +}; + +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} + } +}; + +const UCHAR SiS300_LCDHData[24][11][5] = { + { + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x65,0xef,0x83,0x5c,0x00}, + {0x65,0xef,0x83,0x5c,0x00}, + {0x8a,0x14,0x00,0x80,0x00}, + {0x8a,0x14,0x00,0x80,0x00} + }, + { + {0x4e,0x18,0x90,0x38,0x00}, + {0x4e,0x18,0x90,0x38,0x00}, + {0x8e,0x18,0x28,0x78,0x00}, + {0x8e,0x18,0x28,0x78,0x00}, + {0x8e,0x18,0x28,0x78,0x00}, + {0x4e,0x18,0x90,0x38,0x00}, + {0x4e,0x18,0x90,0x38,0x00}, + {0x67,0x11,0x9a,0x56,0x00}, + {0x67,0x11,0x9a,0x56,0x00}, + {0x8a,0x14,0x00,0x80,0x00}, + {0x8a,0x14,0x00,0x80,0x00} + }, + { + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x65,0xef,0x83,0x5c,0x00}, + {0x65,0xef,0x83,0x5c,0x00}, + {0x8a,0x14,0x00,0x80,0x00}, + {0x8a,0x14,0x00,0x80,0x00} + }, + { + {0x4e,0x18,0x90,0x38,0x00}, + {0x4e,0x18,0x90,0x38,0x00}, + {0x8e,0x18,0x28,0x78,0x00}, + {0x8e,0x18,0x28,0x78,0x00}, + {0x8e,0x18,0x28,0x78,0x00}, + {0x4e,0x18,0x90,0x38,0x00}, + {0x4e,0x18,0x90,0x38,0x00}, + {0x67,0x11,0x9a,0x56,0x00}, + {0x67,0x11,0x9a,0x56,0x00}, + {0x8a,0x14,0x00,0x80,0x00}, + {0x8a,0x14,0x00,0x80,0x00} + }, + { + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x67,0x91,0x84,0x5e,0x00}, + {0x65,0xef,0x83,0x5c,0x00}, + {0x65,0xef,0x83,0x5c,0x00}, + {0x8a,0x14,0x00,0x80,0x00}, + {0x8a,0x14,0x00,0x80,0x00} + }, + { + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x67,0x91,0x84,0x5E,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x65,0xEF,0x83,0x5C,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + }, + { + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x8E,0x18,0x28,0x78,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x4E,0x18,0x90,0x38,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x67,0x11,0x9A,0x56,0x00}, + {0x8A,0x14,0x00,0x80,0x00}, + {0x8A,0x14,0x00,0x80,0x00} + } +}; + +#if 0 +const UCHAR SiS300_LCDVData[24][11][6] = { + { + { + }, +}; +#endif diff --git a/src/oem310.h b/src/oem310.h new file mode 100644 index 0000000..c4415aa --- /dev/null +++ b/src/oem310.h @@ -0,0 +1,377 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/oem310.h,v 1.4 2003/02/10 01:14:16 tsi Exp $ */ + +/* OEM Data for 310/325 series */ + +const UCHAR SiS310_CRT2DelayCompensation1 = 0x04; /* 301 */ + +const UCHAR SiS310_CRT2DelayCompensation2 = 0x00; /* 301B */ + +const UCHAR SiS310_CRT2DelayCompensation3 = 0x00; /* LVDS */ + +const UCHAR SiS310_LCDDelayCompensation1[] = /* 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 +}; + +UCHAR SiS310_LCDDelayCompensation2[] = /* 30xB,LV,LVX */ +{ + 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 +}; + +const UCHAR SiS310_LCDDelayCompensation3[] = /* LVDS */ +{ + 0x00,0x00,0x00, /* 800x600 */ + 0x00,0x00,0x00, /* 1024x768 */ + 0x00,0x00,0x00, /* 1280x1024 */ + 0x00,0x00,0x00, /* 640x480 (unknown) */ + 0x00,0x00,0x00, /* 1024x600 (unknown) */ + 0x00,0x00,0x00, /* 1152x864 (unknown) */ + 0x00,0x00,0x00, /* 1280x960 (guessed) */ + 0x00,0x00,0x00, /* 1152x768 (unknown) */ + 0x00,0x00,0x00, /* 1400x1050 */ + 0x00,0x00,0x00, /* 1280x768 (guessed) */ + 0x00,0x00,0x00, /* 1600x1200 */ + 0x00,0x00,0x00, + 0x00,0x00,0x00, + 0x00,0x00,0x00, + 0x00,0x00,0x00 +}; + +const UCHAR SiS310_LCDDelayCompensation4[] = /* 650 */ +{ + 0x01,0x01,0x01, /* 800x600 (guessed)*/ + 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 */ + 0x01,0x01,0x01, + 0x01,0x01,0x01, + 0x01,0x01,0x01, + 0x01,0x01,0x01 +}; + +const UCHAR SiS310_LCDDelayCompensation5[] = /* 650 LVX */ +{ + 0x01,0x01,0x01, /* 800x600 (guessed) */ + 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 */ + 0x01,0x01,0x01, + 0x01,0x01,0x01, + 0x01,0x01,0x01, + 0x01,0x01,0x01 +}; + +const UCHAR SiS310_LCDDelayCompensation6[] = /* M650/651 */ +{ + 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 +}; + +const UCHAR SiS310_LCDDelayCompensation7[] = /* M650/651 301LVX */ +{ + 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 +}; + +const UCHAR SiS310_TVDelayCompensation1[] = /* 301 */ +{ + 0x02,0x02, /* NTSC Enhanced, Standard */ + 0x02,0x02, /* PAL */ + 0x08,0x0b /* HiVision */ +}; + +const UCHAR SiS310_TVDelayCompensation2[] = /* 301B;LV */ +{ + 0x03,0x03, + 0x03,0x03, + 0x03,0x03 +}; + +const UCHAR SiS310_TVDelayCompensation3[] = /* LVDS */ +{ + 0x0a,0x0a, + 0x0a,0x0a, + 0x0a,0x0a +}; + +const UCHAR SiS310_TVDelayCompensation4[] = /* 650 */ +{ + 0x03,0x03, + 0x03,0x03, + 0x03,0x03 +}; + +const UCHAR SiS310_TVDelayCompensation5[] = /* 650 LVX */ +{ + 0x03,0x03, + 0x03,0x03, + 0x03,0x03 +}; + +const UCHAR SiS310_TVDelayCompensation6[] = /* M650, 651 */ +{ + 0x33,0x33, + 0x33,0x33, + 0x33,0x33 +}; + +const UCHAR SiS310_TVDelayCompensation7[] = /* M650, 651, LVX */ +{ + 0x33,0x33, + 0x33,0x33, + 0x33,0x33 +}; + +const UCHAR SiS310_TVAntiFlick1[3][2] = +{ + {0x4,0x0}, + {0x4,0x8}, + {0x0,0x0} +}; + +const UCHAR SiS310_TVEdge1[3][2] = +{ + {0x0,0x4}, + {0x0,0x4}, + {0x0,0x0} +}; + +const UCHAR SiS310_TVYFilter1[3][8][4] = +{ + { + {0x00,0xf4,0x10,0x38}, + {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}, + {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}, + {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} + } +}; + +const UCHAR SiS310_TVYFilter2[3][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} + }, + { + {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} + } +}; + +const UCHAR SiS310_PALMFilter[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} +}; + +const UCHAR SiS310_PALNFilter[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} +}; + + +const UCHAR SiS310_PALMFilter2[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} +}; + +const UCHAR SiS310_PALNFilter2[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} +}; + +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} + } +}; + +const UCHAR SiS310_TVPhaseIncr2[3][2][4] = +{ + { + {0x21,0xf0,0x7b,0xd6}, /* 1.10.7w; 1.10.6s: {0x1e,0x8b,0xda,0xa7}, old: {0x21,0xF1,0x37,0x56} */ + {0x21,0xf0,0x7b,0xd6} /* 1.10.7w; 1.10.6s: {0x1e,0x8b,0xda,0xa7} old: {0x21,0xF1,0x37,0x56} */ + }, + { + {0x2a,0x0a,0x41,0xe9}, /* 1.10.7w, 1.10.6s. old: {0x2a,0x09,0x86,0xe9}, */ + {0x2a,0x0a,0x41,0xe9} /* 1.10.7w, 1.10.6s. old: {0x2a,0x09,0x86,0xe9} */ + }, + { + {0x2a,0x05,0xd3,0x00}, + {0x2a,0x05,0xd3,0x00} + } +}; + + + diff --git a/src/osdef.h b/src/osdef.h new file mode 100644 index 0000000..039d968 --- /dev/null +++ b/src/osdef.h @@ -0,0 +1,169 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/osdef.h,v 1.2 2003/02/10 01:14:16 tsi Exp $ */ + +/* OS depending defines */ + +/* The choices are: */ +/* #define WINCE_HEADER */ /* Incomplete! */ +/* #define WIN2000 */ /* Incomplete! */ +/* #define TC */ /* Incomplete! */ +/* #define LINUX_KERNEL */ /* Kernel framebuffer */ +#define LINUX_XF86 /* XFree86 */ + +/**********************************************************************/ +#ifdef LINUX_KERNEL /* ----------------------------*/ + +#include <linux/config.h> +#ifdef CONFIG_FB_SIS_300 +#define SIS300 +#endif + +#ifdef CONFIG_FB_SIS_315 +#define SIS315H +#endif + +#else /* if not LINUX_KERNEL --------------------- */ +/* #define SIS300*/ +#define SIS315H + +#endif /* if LINUX_KERNEL ------------------------ */ + +#ifdef LINUX_XF86 /* Linux Xfree86 ---------------- */ + +#define SIS300 +/* #define SIS315H */ /* TW: done above */ +#endif + +/**********************************************************************/ +#ifdef TC +#endif +#ifdef WIN2000 +#endif +#ifdef WINCE_HEADER +#endif +#ifdef LINUX_XF86 +#endif +#ifdef LINUX_KERNEL +#endif +/**********************************************************************/ +#ifdef TC +#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize); +#endif +#ifdef WIN2000 +#define SiS_SetMemory(MemoryAddress,MemorySize,value) MemFill((PVOID) MemoryAddress,(ULONG) MemorySize,(UCHAR) value); +#endif +#ifdef WINCE_HEADER +#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize); +#endif +#ifdef LINUX_XF86 +#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize) +#endif +#ifdef LINUX_KERNEL +#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize) +#endif +/**********************************************************************/ + +/**********************************************************************/ + +#ifdef TC +#define SiS_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length); +#endif +#ifdef WIN2000 +#define SiS_MemoryCopy(Destination,Soruce,Length) /*VideoPortMoveMemory((PUCHAR)Destination , Soruce,length);*/ +#endif +#ifdef WINCE_HEADER +#define SiS_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length); +#endif +#ifdef LINUX_XF86 +#define SiS_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length) +#endif +#ifdef LINUX_KERNEL +#define SiS_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length) +#endif + +/**********************************************************************/ + +#ifdef OutPortByte +#undef OutPortByte +#endif /* OutPortByte */ + +#ifdef OutPortWord +#undef OutPortWord +#endif /* OutPortWord */ + +#ifdef OutPortLong +#undef OutPortLong +#endif /* OutPortLong */ + +#ifdef InPortByte +#undef InPortByte +#endif /* InPortByte */ + +#ifdef InPortWord +#undef InPortWord +#endif /* InPortWord */ + +#ifdef InPortLong +#undef InPortLong +#endif /* InPortLong */ + +/**********************************************************************/ +/* TC */ +/**********************************************************************/ + +#ifdef TC +#define OutPortByte(p,v) outp((unsigned short)(p),(unsigned char)(v)) +#define OutPortWord(p,v) outp((unsigned short)(p),(unsigned short)(v)) +#define OutPortLong(p,v) outp((unsigned short)(p),(unsigned long)(v)) +#define InPortByte(p) inp((unsigned short)(p)) +#define InPortWord(p) inp((unsigned short)(p)) +#define InPortLong(p) ((inp((unsigned short)(p+2))<<16) | inp((unsigned short)(p))) +#endif + +/**********************************************************************/ +/* LINUX XF86 */ +/**********************************************************************/ + +#ifdef LINUX_XF86 +#define OutPortByte(p,v) outb((CARD16)(p),(CARD8)(v)) +#define OutPortWord(p,v) outw((CARD16)(p),(CARD16)(v)) +#define OutPortLong(p,v) outl((CARD16)(p),(CARD32)(v)) +#define InPortByte(p) inb((CARD16)(p)) +#define InPortWord(p) inw((CARD16)(p)) +#define InPortLong(p) inl((CARD16)(p)) +#endif + +#ifdef LINUX_KERNEL +#define OutPortByte(p,v) outb((u8)(v),(u16)(p)) +#define OutPortWord(p,v) outw((u16)(v),(u16)(p)) +#define OutPortLong(p,v) outl((u32)(v),(u16)(p)) +#define InPortByte(p) inb((u16)(p)) +#define InPortWord(p) inw((u16)(p)) +#define InPortLong(p) inl((u16)(p)) +#endif + +/**********************************************************************/ +/* WIN 2000 */ +/**********************************************************************/ + +#ifdef WIN2000 +#define OutPortByte(p,v) VideoPortWritePortUchar ((PUCHAR) (p), (UCHAR) (v)) +#define OutPortWord(p,v) VideoPortWritePortUshort((PUSHORT) (p), (USHORT) (v)) +#define OutPortLong(p,v) VideoPortWritePortUlong ((PULONG) (p), (ULONG) (v)) +#define InPortByte(p) VideoPortReadPortUchar ((PUCHAR) (p)) +#define InPortWord(p) VideoPortReadPortUshort ((PUSHORT) (p)) +#define InPortLong(p) VideoPortReadPortUlong ((PULONG) (p)) +#endif + + +/**********************************************************************/ +/* WIN CE */ +/**********************************************************************/ + +#ifdef WINCE_HEADER +#define OutPortByte(p,v) WRITE_PORT_UCHAR ((PUCHAR) (p), (UCHAR) (v)) +#define OutPortWord(p,v) WRITE_PORT_USHORT((PUSHORT) (p), (USHORT) (v)) +#define OutPortLong(p,v) WRITE_PORT_ULONG ((PULONG) (p), (ULONG) (v)) +#define InPortByte(p) READ_PORT_UCHAR ((PUCHAR) (p)) +#define InPortWord(p) READ_PORT_USHORT ((PUSHORT) (p)) +#define InPortLong(p) READ_PORT_ULONG ((PULONG) (p)) +#endif diff --git a/src/sis.h b/src/sis.h new file mode 100644 index 0000000..7278674 --- /dev/null +++ b/src/sis.h @@ -0,0 +1,710 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis.h,v 1.29 2003/01/29 15:42:16 eich Exp $ */ +/* + * Copyright 1998,1999 by Alan Hourihane, Wigan, England. + * Parts Copyright 2001, 2002 by Thomas Winischhofer, Vienna, Austria + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holder not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The copyright holder makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk + * Mike Chapman <mike@paranoia.com>, + * Juanjo Santamarta <santamarta@ctv.es>, + * Mitani Hiroshi <hmitani@drl.mei.co.jp> + * David Thomas <davtom@dream.org.uk>. + * + * Thomas Winischhofer <thomas@winischhofer.net>: + * - 310/325 series (315/550/650/651/740/M650) support + * - (possibly incomplete) Xabre (SiS330) support + * - new mode switching code for 300, 310/325 and 330 series + * - many fixes for 300/540/630/730 chipsets, + * - many fixes for 5597/5598, 6326 and 530/620 chipsets, + * - VESA mode switching (deprecated), + * - extended CRT2/video bridge handling support, + * - dual head support on 300, 310/325 and 330 series + * - 650/LVDS (up to 1400x1050), 650/Chrontel 701x support + * - 30xB/30xLV/30xLVX video bridge support (300, 310/325, 330 series) + * - Xv support for 5597/5598, 6326, 530/620 and 310/325 series + * - video overlay enhancements for 300 series + * - TV and hi-res support for the 6326 + * - Color hardware cursor support for 300/310/325/330 series + * - etc. + */ + + +#ifndef _SIS_H +#define _SIS_H_ + +/* Always unlock the registers (should be set!) */ +#define UNLOCK_ALWAYS + +#if 0 +#define TWDEBUG /* for debugging */ +#endif + +#include "xf86Pci.h" +#include "xf86Cursor.h" +#include "xf86_ansic.h" +#include "xf86xv.h" +#include "compiler.h" +#include "xaa.h" +#include "vgaHW.h" +#include "vbe.h" +#include "osdef.h" +#include "vgatypes.h" +#include "vstruct.h" + +#ifdef XF86DRI +#include "xf86drm.h" +#include "sarea.h" +#define _XF86DRI_SERVER_ +#include "xf86dri.h" +#include "dri.h" +#include "GL/glxint.h" +#include "sis_dri.h" +#endif + +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0) +typedef unsigned long IOADDRESS; +#endif + +#if 1 +#define SISDUALHEAD /* TW: Include Dual Head code */ +#endif + +#if 1 +#define USE6326VIDEO /* TW: Include 6326/530/620 Xv code */ +#endif + +#if 1 /* TW: Include code for 330 - highly preliminary */ +#define INCL_SIS330 +#endif + +#if 1 /* TW: Include code for cycling CRT2 type via keyboard */ +#define CYCLECRT2 /* (not functional yet) */ +#endif + +#if 1 +#define SISGAMMA /* TW: Include code for gamma correction */ +#endif + +#if 1 /* TW: Include code for color hardware cursors */ +#define SIS_ARGB_CURSOR +#endif + +/* TW: new for SiS315/550/650/740/330 - these should be moved elsewhere! */ +#ifndef PCI_CHIP_SIS315H +#define PCI_CHIP_SIS315H 0x0310 +#endif +#ifndef PCI_CHIP_SIS315 +#define PCI_CHIP_SIS315 0x0315 +#endif +#ifndef PCI_CHIP_SIS315PRO +#define PCI_CHIP_SIS315PRO 0x0325 +#endif +#ifndef PCI_CHIP_SIS550 +#define PCI_CHIP_SIS550 0x5315 /* This is 550_VGA */ +#endif +#ifndef PCI_CHIP_SIS650 +#define PCI_CHIP_SIS650 0x6325 /* This is 650_VGA and 740_VGA */ +#endif +#ifndef PCI_CHIP_SIS330 +#define PCI_CHIP_SIS330 0x0330 +#endif + +#define SIS_NAME "SIS" +#define SIS_DRIVER_NAME "sis" +#define SIS_MAJOR_VERSION 0 +#define SIS_MINOR_VERSION 6 +#define SIS_PATCHLEVEL 0 +#define SIS_CURRENT_VERSION ((SIS_MAJOR_VERSION << 16) | \ + (SIS_MINOR_VERSION << 8) | SIS_PATCHLEVEL ) + +/* pSiS->Flags (old series only) */ +#define SYNCDRAM 0x00000001 +#define RAMFLAG 0x00000002 +#define ESS137xPRESENT 0x00000004 +#define SECRETFLAG 0x00000008 +#define A6326REVAB 0x00000010 +#define MMIOMODE 0x00010000 +#define LFBQMODE 0x00020000 +#define AGPQMODE 0x00040000 +#define UMA 0x80000000 + +#define BIOS_BASE 0xC0000 +#define BIOS_SIZE 0x10000 + +/* TW: New mode switching code */ +#define SR_BUFFER_SIZE 5 +#define CR_BUFFER_SIZE 5 + +/* TW: VBFlags */ +#define CRT2_DEFAULT 0x00000001 +#define CRT2_LCD 0x00000002 /* TW: Never change the order of the CRT2_XXX entries */ +#define CRT2_TV 0x00000004 /* (see SISCycleCRT2Type()) */ +#define CRT2_VGA 0x00000008 +#define CRT2_ENABLE (CRT2_LCD | CRT2_TV | CRT2_VGA) +#define DISPTYPE_DISP2 CRT2_ENABLE +#define TV_NTSC 0x00000010 +#define TV_PAL 0x00000020 +#define TV_HIVISION 0x00000040 +#define TV_TYPE (TV_NTSC | TV_PAL | TV_HIVISION) +#define TV_AVIDEO 0x00000100 +#define TV_SVIDEO 0x00000200 +#define TV_SCART 0x00000400 +#define TV_INTERFACE (TV_AVIDEO | TV_SVIDEO | TV_SCART | TV_CHSCART | TV_CHHDTV) +#define TV_PALM 0x00001000 +#define TV_PALN 0x00002000 +#define TV_CHSCART 0x00008000 +#define TV_CHHDTV 0x00010000 +#define VGA2_CONNECTED 0x00040000 +#define DISPTYPE_CRT1 0x00080000 /* TW: CRT1 connected and used */ +#define DISPTYPE_DISP1 DISPTYPE_CRT1 +#define VB_301 0x00100000 /* Video bridge type */ +#define VB_301B 0x00200000 +#define VB_302B 0x00400000 +#define VB_303 0x00800000 +#define VB_LVDS 0x01000000 +#define VB_CHRONTEL 0x02000000 +#define VB_30xLV 0x04000000 +#define VB_30xLVX 0x08000000 +#define VB_TRUMPION 0x10000000 +#define VB_VIDEOBRIDGE (VB_301|VB_301B|VB_302B|VB_303|VB_30xLV|VB_30xLVX| \ + VB_LVDS|VB_CHRONTEL|VB_TRUMPION) /* TW */ +#define VB_SISBRIDGE (VB_301|VB_301B|VB_302B|VB_303|VB_30xLV|VB_30xLVX) +#define SINGLE_MODE 0x20000000 /* TW: CRT1 or CRT2; determined by DISPTYPE_CRTx */ +#define VB_DISPMODE_SINGLE SINGLE_MODE /* TW: alias */ +#define MIRROR_MODE 0x40000000 /* TW: CRT1 + CRT2 identical (mirror mode) */ +#define VB_DISPMODE_MIRROR MIRROR_MODE /* TW: alias */ +#define DUALVIEW_MODE 0x80000000 /* TW: CRT1 + CRT2 independent (dual head mode) */ +#define VB_DISPMODE_DUAL DUALVIEW_MODE /* TW: alias */ +#define DISPLAY_MODE (SINGLE_MODE | MIRROR_MODE | DUALVIEW_MODE) /* TW */ + +/* TW: pSiS->VBLCDFlags */ +#define VB_LCD_320x480 0x00000001 /* TW: DSTN/FSTN for 550 */ +#define VB_LCD_640x480 0x00000002 +#define VB_LCD_800x600 0x00000004 +#define VB_LCD_1024x768 0x00000008 +#define VB_LCD_1280x1024 0x00000010 +#define VB_LCD_1280x960 0x00000020 +#define VB_LCD_1600x1200 0x00000040 +#define VB_LCD_2048x1536 0x00000080 +#define VB_LCD_1400x1050 0x00000100 +#define VB_LCD_1152x864 0x00000200 +#define VB_LCD_1152x768 0x00000400 +#define VB_LCD_1280x768 0x00000800 +#define VB_LCD_1024x600 0x00001000 + +/* TW: More or less useful macros (although we often use pSiS->VGAEngine instead) */ +#define SIS_IS_300_CHIPSET (pSiS->Chipset == PCI_CHIP_SIS300) || \ + (pSiS->Chipset == PCI_CHIP_SIS630) || \ + (pSiS->Chipset == PCI_CHIP_SIS540) || \ + (pSiS->Chipset == PCI_CHIP_SIS730) + +/* This preliminaryly also contains SIS330 */ +#define SIS_IS_315_CHIPSET (pSiS->Chipset == PCI_CHIP_SIS315) || \ + (pSiS->Chipset == PCI_CHIP_SIS315H) || \ + (pSiS->Chipset == PCI_CHIP_SIS315PRO) || \ + (pSiS->Chipset == PCI_CHIP_SIS550) || \ + (pSiS->Chipset == PCI_CHIP_SIS650) || \ + (pSiS->Chipset == PCI_CHIP_SIS330) + +/* SiS6326Flags */ +#define SIS6326_HASTV 0x00000001 +#define SIS6326_TVSVIDEO 0x00000002 +#define SIS6326_TVCVBS 0x00000004 +#define SIS6326_TVPAL 0x00000008 +#define SIS6326_TVDETECTED 0x00000010 +#define SIS6326_TVON 0x80000000 + +#define HW_DEVICE_EXTENSION SIS_HW_DEVICE_INFO + +#ifdef DEBUG +#define PDEBUG(p) p +#else +#define PDEBUG(p) +#endif + +typedef unsigned long ULong; +typedef unsigned short UShort; +typedef unsigned char UChar; + +/* TW: VGA engine types */ +#define UNKNOWN_VGA 0 +#define SIS_530_VGA 1 +#define SIS_OLD_VGA 2 +#define SIS_300_VGA 3 +#define SIS_315_VGA 4 + +/* TW: oldChipset */ +#define OC_UNKNOWN 0 +#define OC_SIS6205A 3 +#define OC_SIS6205B 4 +#define OC_SIS82204 5 +#define OC_SIS6205C 6 +#define OC_SIS6225 7 +#define OC_SIS5597 8 +#define OC_SIS6326 9 +#define OC_SIS530A 11 +#define OC_SIS530B 12 + +/* TW: Chrontel type */ +#define CHRONTEL_700x 0 +#define CHRONTEL_701x 1 + +/* Flags650 */ +#define SiS650_LARGEOVERLAY 0x00000001 + +/* TW: For backup of register contents */ +typedef struct { + unsigned char sisRegs3C4[0x50]; + unsigned char sisRegs3D4[0x90]; + unsigned char sisRegs3C2; + unsigned char VBPart1[0x50]; + unsigned char VBPart2[0x50]; + unsigned char VBPart3[0x50]; + unsigned char VBPart4[0x50]; + unsigned short ch70xx[64]; + unsigned long sisMMIO85C0; /* TW: Queue location for 310/325 series */ + unsigned char sis6326tv[0x46]; + unsigned long sisRegsPCI50, sisRegsPCIA0; +} SISRegRec, *SISRegPtr; + +typedef struct _sisModeInfoPtr { + int width; + int height; + int bpp; + int n; + struct _sisModeInfoPtr *next; +} sisModeInfoRec, *sisModeInfoPtr; + +/* TW: SISFBLayout is mainly there because of DGA. It holds the + current layout parameters needed for acceleration and other + stuff. When switching mode using DGA, these are set up + accordingly and not necessarily match pScrn's. Therefore, + driver modules should read these values instead of pScrn's. + */ +typedef struct { + int bitsPerPixel; /* TW: Copy from pScrn->bitsPerPixel */ + int depth; /* TW: Copy from pScrn->depth */ + int displayWidth; /* TW: Copy from pScrn->displayWidth */ + DisplayModePtr mode; /* TW: Copy from pScrn->currentMode */ +} SISFBLayout; + +/* TW: Dual head private entity structure */ +#ifdef SISDUALHEAD +typedef struct { + ScrnInfoPtr pScrn_1; + ScrnInfoPtr pScrn_2; + unsigned char * BIOS; + SiS_Private * SiS_Pr; /* TW: For new mode switching code */ + int CRT1ModeNo; /* Current display mode for CRT1 */ + DisplayModePtr CRT1DMode; /* Current display mode for CRT1 */ + int CRT2ModeNo; /* Current display mode for CRT2 */ + DisplayModePtr CRT2DMode; /* Current display mode for CRT2 */ + int refCount; + int lastInstance; /* number of entities */ + Bool DisableDual; /* Emergency flag */ + Bool ErrorAfterFirst; /* Emergency flag: Error after first init -> Abort second */ + Bool HWCursor; /* Backup master settings for use on slave */ + Bool TurboQueue; + int ForceCRT2Type; + int OptTVStand; + int OptTVOver; + int OptTVSOver; + int OptROMUsage; + int PDC; + Bool NoAccel; + Bool NoXvideo; + int forceCRT1; + int DSTN; + Bool XvOnCRT2; + int maxUsedClock; /* Max used pixelclock on master head */ + unsigned long masterFbAddress; /* Framebuffer addresses and sizes */ + unsigned long masterFbSize; + unsigned long slaveFbAddress; + unsigned long slaveFbSize; + unsigned char * FbBase; /* VRAM linear address */ + unsigned char * IOBase; /* MMIO linear address */ + unsigned short MapCountIOBase; /* map/unmap queue counter */ + unsigned short MapCountFbBase; /* map/unmap queue counter */ + Bool forceUnmapIOBase; /* ignore counter and unmap */ + Bool forceUnmapFbBase; /* ignore counter and unmap */ +#ifdef __alpha__ + unsigned char * IOBaseDense; /* MMIO for Alpha platform */ + unsigned short MapCountIOBaseDense; + Bool forceUnmapIOBaseDense; /* ignore counter and unmap */ +#endif + int chtvlumabandwidthcvbs; /* TW: TV settings for Chrontel TV encoder */ + int chtvlumabandwidthsvideo; + int chtvlumaflickerfilter; + int chtvchromabandwidth; + int chtvchromaflickerfilter; + int chtvcvbscolor; + int chtvtextenhance; + int chtvcontrast; + int sistvedgeenhance; /* TW: TV settings for SiS bridge */ + int sistvantiflicker; + int sistvsaturation; + int tvxpos; + int tvypos; + int ForceTVType; + int chtvtype; + int NonDefaultPAL; + unsigned short tvx, tvy; + unsigned char p2_01, p2_02, p2_2d; + unsigned short cursorBufferNum; + BOOLEAN restorebyset; +} SISEntRec, *SISEntPtr; +#endif + +#define SISPTR(p) ((SISPtr)((p)->driverPrivate)) +#define XAAPTR(p) ((XAAInfoRecPtr)(SISPTR(p)->AccelInfoPtr)) + +typedef struct { + ScrnInfoPtr pScrn; /* -------------- DON'T INSERT ANYTHING HERE --------------- */ + pciVideoPtr PciInfo; /* -------- OTHERWISE sis_dri.so MUST BE RECOMPILED -------- */ + PCITAG PciTag; + EntityInfoPtr pEnt; + int Chipset; + int ChipRev; + int VGAEngine; /* TW: see above */ + int hasTwoOverlays; /* TW: Chipset supports two video overlays? */ + HW_DEVICE_EXTENSION sishw_ext; /* TW: For new mode switching code */ + SiS_Private * SiS_Pr; /* TW: For new mode switching code */ + int DSTN; /* TW: For 550 FSTN/DSTN; set by option, no detection */ + unsigned long FbAddress; /* VRAM physical address (in DHM: for each Fb!) */ + unsigned long realFbAddress; /* For DHM/PCI mem mapping: store global FBAddress */ + unsigned char * FbBase; /* VRAM virtual linear address */ + CARD32 IOAddress; /* MMIO physical address */ + unsigned char * IOBase; /* MMIO linear address */ + IOADDRESS IODBase; /* Base of PIO memory area */ +#ifdef __alpha__ + unsigned char * IOBaseDense; /* MMIO for Alpha platform */ +#endif + CARD16 RelIO; /* Relocated IO Ports baseaddress */ + unsigned char * BIOS; + int MemClock; + int BusWidth; + int MinClock; + int MaxClock; + int Flags; /* HW config flags */ + long FbMapSize; /* Used for Mem Mapping - DON'T CHANGE THIS */ + long availMem; /* Really available Fb mem (minus TQ, HWCursor) */ + unsigned long maxxfbmem; /* limit fb memory X is to use to this (KB) */ + unsigned long sisfbMem; /* heapstart of sisfb (if running) */ +#ifdef SISDUALHEAD + unsigned long dhmOffset; /* Offset to memory for each head (0 or ..) */ +#endif + DGAModePtr DGAModes; + int numDGAModes; + Bool DGAactive; + int DGAViewportStatus; + int OldMode; /* TW: Back old modeNo (if available) */ + Bool NoAccel; + Bool NoXvideo; + Bool XvOnCRT2; /* TW: see sis_opt.c */ + Bool HWCursor; + Bool UsePCIRetry; + Bool TurboQueue; + int VESA; + int ForceCRT2Type; + int OptTVStand; + int OptTVOver; + int OptROMUsage; + int UseCHOverScan; + Bool ValidWidth; + Bool FastVram; /* TW: now unused */ + int forceCRT1; + Bool CRT1changed; + unsigned char oldCR17; + unsigned char oldCR32; + unsigned char newCR32; + int VBFlags; /* TW: Video bridge configuration */ + int VBFlags_backup; /* TW: Backup for SlaveMode-modes */ + int VBLCDFlags; /* TW: Moved LCD panel size bits here */ + int ChrontelType; /* TW: CHRONTEL_700x or CHRONTEL_701x */ + int PDC; /* TW: PanelDelayCompensation */ + short scrnOffset; /* TW: Screen pitch (data) */ + short scrnPitch; /* TW: Screen pitch (display; regarding interlace) */ + short DstColor; + int xcurrent; /* for temp use in accel */ + int ycurrent; /* for temp use in accel */ + long SiS310_AccelDepth; /* used in accel for 310/325 series */ + int Xdirection; /* for temp use in accel */ + int Ydirection; /* for temp use in accel */ + int sisPatternReg[4]; + int ROPReg; + int CommandReg; + int MaxCMDQueueLen; + int CurCMDQueueLen; + int MinCMDQueueLen; + CARD16 CursorSize; /* TW: Size of HWCursor area (bytes) */ + CARD32 cursorOffset; /* TW: see sis_driver.c and sis_cursor.c */ + int DstX; + int DstY; + unsigned char * XAAScanlineColorExpandBuffers[2]; + CARD32 AccelFlags; + Bool ClipEnabled; + Bool DoColorExpand; + SISRegRec SavedReg; + SISRegRec ModeReg; + xf86CursorInfoPtr CursorInfoPtr; + XAAInfoRecPtr AccelInfoPtr; + CloseScreenProcPtr CloseScreen; + unsigned int (*ddc1Read)(ScrnInfoPtr); + Bool (*ModeInit)(ScrnInfoPtr pScrn, DisplayModePtr mode); + void (*SiSSave)(ScrnInfoPtr pScrn, SISRegPtr sisreg); + void (*SiSSave2)(ScrnInfoPtr pScrn, SISRegPtr sisreg); + void (*SiSSave3)(ScrnInfoPtr pScrn, SISRegPtr sisreg); + void (*SiSSaveLVDSChrontel)(ScrnInfoPtr pScrn, SISRegPtr sisreg); + void (*SiSRestore)(ScrnInfoPtr pScrn, SISRegPtr sisreg); + void (*SiSRestore2)(ScrnInfoPtr pScrn, SISRegPtr sisreg); + void (*SiSRestore3)(ScrnInfoPtr pScrn, SISRegPtr sisreg); + void (*SiSRestoreLVDSChrontel)(ScrnInfoPtr pScrn, SISRegPtr sisreg); + void (*SetThreshold)(ScrnInfoPtr pScrn, DisplayModePtr mode, + unsigned short *Low, unsigned short *High); + void (*LoadCRT2Palette)(ScrnInfoPtr pScrn, int numColors, + int *indicies, LOCO *colors, VisualPtr pVisual); + + int cmdQueueLen; /* TW: Current cmdQueueLength (for 2D and 3D) */ + int *cmdQueueLenPtr; + unsigned long agpHandle; + CARD32 agpAddr; + unsigned char *agpBase; + unsigned int agpSize; + CARD32 agpCmdBufAddr; + unsigned char *agpCmdBufBase; + unsigned int agpCmdBufSize; + unsigned int agpCmdBufFree; + Bool irqEnabled; + int irq; + + int ColorExpandRingHead; + int ColorExpandRingTail; + int PerColorExpandBufferSize; + int ColorExpandBufferNumber; + int ColorExpandBufferCountMask; + unsigned char *ColorExpandBufferAddr[32]; + int ColorExpandBufferScreenOffset[32]; + int ImageWriteBufferSize; + unsigned char *ImageWriteBufferAddr; + + int Rotate; + void (*PointerMoved)(int index, int x, int y); + + /* ShadowFB support */ + Bool ShadowFB; + unsigned char *ShadowPtr; + int ShadowPitch; + +#ifdef XF86DRI + Bool directRenderingEnabled; + DRIInfoPtr pDRIInfo; + int drmSubFD; + int numVisualConfigs; + __GLXvisualConfig* pVisualConfigs; + SISConfigPrivPtr pVisualConfigsPriv; + SISRegRec DRContextRegs; +#endif + + XF86VideoAdaptorPtr adaptor; + ScreenBlockHandlerProcPtr BlockHandler; + void (*VideoTimerCallback)(ScrnInfoPtr, Time); + + OptionInfoPtr Options; + unsigned char LCDon; +#ifdef SISDUALHEAD + Bool BlankCRT1, BlankCRT2; +#endif + Bool Blank; + unsigned char BIOSModeSave; + int CRT1off; /* TW: 1=CRT1 off, 0=CRT1 on */ + CARD16 LCDheight; /* TW: Vertical resolution of LCD panel */ + CARD16 LCDwidth; /* TW: Horizontal resolution of LCD panel */ + vbeInfoPtr pVbe; /* TW: For VESA mode switching */ + CARD16 vesamajor; + CARD16 vesaminor; + VbeInfoBlock *vbeInfo; + int UseVESA; + sisModeInfoPtr SISVESAModeList; + xf86MonPtr monitor; + CARD16 maxBytesPerScanline; + CARD32 *pal, *savedPal; + int mapPhys, mapOff, mapSize; + int statePage, stateSize, stateMode; + CARD8 *fonts; + CARD8 *state, *pstate; + void *base, *VGAbase; +#ifdef SISDUALHEAD + BOOL DualHeadMode; /* TW: TRUE if we use dual head mode */ + BOOL SecondHead; /* TW: TRUE is this is the second head */ + SISEntPtr entityPrivate; /* TW: Ptr to private entity (see above) */ + BOOL SiSXinerama; /* TW: Do we use Xinerama mode? */ +#endif + SISFBLayout CurrentLayout; /* TW: Current framebuffer layout */ + Bool (*i2cInit)(ScrnInfoPtr);/* I2C stuff */ + I2CBusPtr I2C; + USHORT SiS_DDC2_Index; + USHORT SiS_DDC2_Data; + USHORT SiS_DDC2_Clk; + BOOL Primary; /* TW: Display adapter is primary */ + xf86Int10InfoPtr pInt; /* TW: Our int10 */ + int oldChipset; /* TW: Type of old chipset */ + CARD32 RealVideoRam; /* TW: 6326 can only address 4MB, but TQ can be above */ + CARD32 CmdQueLenMask; /* TW: Mask of queue length in MMIO register */ + CARD32 CmdQueLenFix; /* TW: Fix value to subtract from QueLen (530/620) */ + CARD32 CmdQueMaxLen; /* TW: (6326/5597/5598) Amount of cmds the queue can hold */ + CARD32 TurboQueueLen; /* TW: For future use */ + CARD32 detectedCRT2Devices; /* TW: detected CRT2 devices before mask-out */ + Bool NoHostBus; /* TW: Enable/disable 5597/5598 host bus */ + Bool noInternalModes; /* TW: Use our own default modes? */ + char * sbiosn; /* TW: For debug */ + int OptUseOEM; /* TW: Use internal OEM data? */ + int chtvlumabandwidthcvbs; /* TW: TV settings for Chrontel TV encoder */ + int chtvlumabandwidthsvideo; + int chtvlumaflickerfilter; + int chtvchromabandwidth; + int chtvchromaflickerfilter; + int chtvcvbscolor; + int chtvtextenhance; + int chtvcontrast; + int sistvedgeenhance; /* TW: TV settings for SiS bridges */ + int sistvantiflicker; + int sistvsaturation; + int OptTVSOver; /* TW: Chrontel 7005: Superoverscan */ + int tvxpos; + int tvypos; + int SiS6326Flags; /* TW: SiS6326 TV settings */ + int sis6326antiflicker; + int sis6326enableyfilter; + int sis6326yfilterstrong; + BOOL donttrustpdc; /* TW: Don't trust the detected PDC */ + unsigned char sisfbpdc; + int NoYV12; /* TW: Disable Xv YV12 support (old series) */ + unsigned char postVBCR32; + int newFastVram; /* TW: Replaces FastVram */ + int ForceTVType; + int NonDefaultPAL; + unsigned long lockcalls; /* TW: Count unlock calls for debug */ + unsigned short tvx, tvy; /* TW: Backup TV position registers */ + unsigned char p2_01, p2_02, p2_2d; /* TW: Backup TV position registers */ + unsigned short tvx1, tvx2, tvx3, tvy1; /* TW: Backup TV position registers */ + BOOLEAN ForceCursorOff; + BOOLEAN HaveCustomModes; + BOOLEAN IsCustom; + DisplayModePtr backupmodelist; + int chtvtype; + Atom xvBrightness, xvContrast, xvColorKey, xvHue, xvSaturation; + Atom xvAutopaintColorKey, xvSetDefaults; + unsigned long Flags650; + BOOLEAN UseHWARGBCursor; + int OptUseColorCursor; + int OptUseColorCursorBlend; + CARD32 OptColorCursorBlendThreshold; + unsigned short cursorBufferNum; + BOOLEAN restorebyset; +} SISRec, *SISPtr; + +typedef struct _ModeInfoData { + int mode; + VbeModeInfoBlock *data; + VbeCRTCInfoBlock *block; +} ModeInfoData; + +typedef struct _myhddctiming { + int whichone; + unsigned char mask; + float rate; +} myhddctiming; + +typedef struct _myvddctiming { + int whichone; + unsigned char mask; + int rate; +} myvddctiming; + +typedef struct _myddcstdmodes { + int hsize; + int vsize; + int refresh; + float hsync; +} myddcstdmodes; + +typedef struct _pdctable { + int subsysVendor; + int subsysCard; + int pdc; + char *vendorName; + char *cardName; +} pdctable; + +typedef struct _chswtable { + int subsysVendor; + int subsysCard; + char *vendorName; + char *cardName; +} chswtable; + +extern void sisSaveUnlockExtRegisterLock(SISPtr pSiS, unsigned char *reg1, unsigned char *reg2); +extern void sisRestoreExtRegisterLock(SISPtr pSiS, unsigned char reg1, unsigned char reg2); +extern void SiSOptions(ScrnInfoPtr pScrn); +extern const OptionInfoRec * SISAvailableOptions(int chipid, int busid); +extern void SiSSetup(ScrnInfoPtr pScrn); +extern void SISVGAPreInit(ScrnInfoPtr pScrn); +extern Bool SiSAccelInit(ScreenPtr pScreen); +extern Bool SiS300AccelInit(ScreenPtr pScreen); +extern Bool SiS310AccelInit(ScreenPtr pScreen); +extern Bool SiS530AccelInit(ScreenPtr pScreen); +extern Bool SiSHWCursorInit(ScreenPtr pScreen); +extern Bool SISDGAInit(ScreenPtr pScreen); +extern void SISInitVideo(ScreenPtr pScreen); +extern void SIS6326InitVideo(ScreenPtr pScreen); + +extern void SiS_SetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn, int val); +extern void SiS_SetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn, int val); +extern void SiS_SetCHTVlumaflickerfilter(ScrnInfoPtr pScrn, int val); +extern void SiS_SetCHTVchromabandwidth(ScrnInfoPtr pScrn, int val); +extern void SiS_SetCHTVchromaflickerfilter(ScrnInfoPtr pScrn, int val); +extern void SiS_SetCHTVcvbscolor(ScrnInfoPtr pScrn, int val); +extern void SiS_SetCHTVtextenhance(ScrnInfoPtr pScrn, int val); +extern void SiS_SetCHTVcontrast(ScrnInfoPtr pScrn, int val); +extern void SiS_SetSISTVedgeenhance(ScrnInfoPtr pScrn, int val); +extern void SiS_SetSISTVantiflicker(ScrnInfoPtr pScrn, int val); +extern void SiS_SetSISTVsaturation(ScrnInfoPtr pScrn, int val); +extern void SiS_SetSIS6326TVantiflicker(ScrnInfoPtr pScrn, int val); +extern void SiS_SetSIS6326TVenableyfilter(ScrnInfoPtr pScrn, int val); +extern void SiS_SetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn, int val); +extern void SiS_SetTVxposoffset(ScrnInfoPtr pScrn, int val); +extern void SiS_SetTVyposoffset(ScrnInfoPtr pScrn, int val); +extern int SiS_GetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn); +extern int SiS_GetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn); +extern int SiS_GetCHTVlumaflickerfilter(ScrnInfoPtr pScrn); +extern int SiS_GetCHTVchromabandwidth(ScrnInfoPtr pScrn); +extern int SiS_GetCHTVchromaflickerfilter(ScrnInfoPtr pScrn); +extern int SiS_GetCHTVcvbscolor(ScrnInfoPtr pScrn); +extern int SiS_GetCHTVtextenhance(ScrnInfoPtr pScrn); +extern int SiS_GetCHTVcontrast(ScrnInfoPtr pScrn); +extern int SiS_GetSISTVedgeenhance(ScrnInfoPtr pScrn); +extern int SiS_GetSISTVantiflicker(ScrnInfoPtr pScrn); +extern int SiS_GetSISTVsaturation(ScrnInfoPtr pScrn); +extern int SiS_GetSIS6326TVantiflicker(ScrnInfoPtr pScrn); +extern int SiS_GetSIS6326TVenableyfilter(ScrnInfoPtr pScrn); +extern int SiS_GetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn); +extern int SiS_GetTVxposoffset(ScrnInfoPtr pScrn); +extern int SiS_GetTVyposoffset(ScrnInfoPtr pScrn); +#endif diff --git a/src/sis300_accel.c b/src/sis300_accel.c new file mode 100644 index 0000000..8db9d49 --- /dev/null +++ b/src/sis300_accel.c @@ -0,0 +1,1397 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis300_accel.c,v 1.14 2003/01/29 15:42:16 eich Exp $ */ +/* + * 2D Acceleration for SiS300, SiS540, SiS630, SiS730, SiS530, SiS620 + * + * Copyright Xavier Ducoin <x.ducoin@lectra.com> + * Copyright 2002 by Thomas Winischhofer, Vienna, Austria + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * + * Xavier Ducoin <x.ducoin@lectra.com> + * Thomas Winischhofer <thomas@winischhofer.net> + * + */ +#if 0 +#define DEBUG +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "compiler.h" +#include "xaa.h" + +#include "sis.h" +#include "sis300_accel.h" + +#ifdef SISDUALHEAD +/* TW: This is the offset to the memory for each head */ +#define HEADOFFSET (pSiS->dhmOffset) +#endif + +#undef STSCE /* TW: Use/Don't use ScreenToScreenColorExpand - does not work */ + +#undef TRAP /* TW: Use/Don't use Trapezoid Fills - does not work - XAA provides + * illegal trapezoid data (left and right edges cross each other + * sometimes) which causes drawing errors. Further, I have not found + * out how to draw polygones with a height greater than 127... + */ + +static void SiSInitializeAccelerator(ScrnInfoPtr pScrn); +static void SiSSync(ScrnInfoPtr pScrn); +static void SiSSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, int trans_color); +static void SiSSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, + int width, int height); +static void SiSSetupForSolidFill(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void SiSSubsequentSolidFillRect(ScrnInfoPtr pScrn, + int x, int y, int w, int h); +#ifdef TRAP +static void SiSSubsequentSolidFillTrap(ScrnInfoPtr pScrn, int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR); +#endif +static void SiSSetupForSolidLine(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void SiSSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, + int y1, int x2, int y2, int flags); +static void SiSSubsequentSolidHorzVertLine(ScrnInfoPtr pScrn, + int x, int y, int len, int dir); +static void SiSSetupForDashedLine(ScrnInfoPtr pScrn, + int fg, int bg, int rop, unsigned int planemask, + int length, unsigned char *pattern); +static void SiSSubsequentDashedTwoPointLine(ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, + int flags, int phase); +static void SiSSetupForMonoPatternFill(ScrnInfoPtr pScrn, + int patx, int paty, int fg, int bg, + int rop, unsigned int planemask); +static void SiSSubsequentMonoPatternFill(ScrnInfoPtr pScrn, + int patx, int paty, + int x, int y, int w, int h); +#ifdef TRAP +static void SiSSubsequentMonoPatternFillTrap(ScrnInfoPtr pScrn, + int patx, int paty, + int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR ); +#endif +#if 0 +static void SiSSetupForColorPatternFill(ScrnInfoPtr pScrn, + int patx, int paty, int rop, + unsigned int planemask, + int trans_color); +static void SiSSubsequentColorPatternFill(ScrnInfoPtr pScrn, + int patx, int paty, + int x, int y, int w, int h); +#endif +#if 0 +static void SiSSetupForCPUToScreenColorExpand(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, unsigned int planemask); +static void SiSSubsequentCPUToScreenColorExpand(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft); +#endif +#ifdef STSCE +static void SiSSetupForScreenToScreenColorExpand(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, unsigned int planemask); +static void SiSSubsequentScreenToScreenColorExpand(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int srcx, int srcy, int skipleft); +#endif +static void SiSSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); +static void SiSSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft); +static void SiSSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); + +#ifdef SISDUALHEAD +static void SiSRestoreAccelState(ScrnInfoPtr pScrn); +#endif + +static void +SiSInitializeAccelerator(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + + pSiS->DoColorExpand = FALSE; +} + +Bool +SiS300AccelInit(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + int topFB; + int reservedFbSize; + int UsableFbSize; + unsigned char *AvailBufBase; + BoxRec Avail; + int i; + + pSiS->AccelInfoPtr = infoPtr = XAACreateInfoRec(); + if (!infoPtr) return FALSE; + + SiSInitializeAccelerator(pScrn); + + infoPtr->Flags = LINEAR_FRAMEBUFFER | + OFFSCREEN_PIXMAPS | + PIXMAP_CACHE; + + /* sync */ + infoPtr->Sync = SiSSync; + + /* Acceleration only supported at 8, 16 and 32 bpp */ + if((pScrn->bitsPerPixel != 8) && (pScrn->bitsPerPixel != 16) && + (pScrn->bitsPerPixel != 32)) + return FALSE; + + /* screen to screen copy - TW: We now support transparent copies */ + infoPtr->SetupForScreenToScreenCopy = SiSSetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = SiSSubsequentScreenToScreenCopy; + infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK | + TRANSPARENCY_GXCOPY_ONLY; + + /* solid fills */ + infoPtr->SetupForSolidFill = SiSSetupForSolidFill; + infoPtr->SubsequentSolidFillRect = SiSSubsequentSolidFillRect; +#ifdef TRAP + infoPtr->SubsequentSolidFillTrap = SiSSubsequentSolidFillTrap; +#endif + infoPtr->SolidFillFlags = NO_PLANEMASK; + + /* solid line */ + infoPtr->SetupForSolidLine = SiSSetupForSolidLine; + infoPtr->SubsequentSolidTwoPointLine = SiSSubsequentSolidTwoPointLine; + infoPtr->SubsequentSolidHorVertLine = SiSSubsequentSolidHorzVertLine; + infoPtr->SolidLineFlags = NO_PLANEMASK; + + /* dashed line */ + infoPtr->SetupForDashedLine = SiSSetupForDashedLine; + infoPtr->SubsequentDashedTwoPointLine = SiSSubsequentDashedTwoPointLine; + infoPtr->DashPatternMaxLength = 64; + infoPtr->DashedLineFlags = NO_PLANEMASK | + LINE_PATTERN_MSBFIRST_LSBJUSTIFIED; + + /* 8x8 mono pattern fill */ + infoPtr->SetupForMono8x8PatternFill = SiSSetupForMonoPatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = SiSSubsequentMonoPatternFill; +#ifdef TRAP + infoPtr->SubsequentMono8x8PatternFillTrap = SiSSubsequentMonoPatternFillTrap; +#endif + infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK | + HARDWARE_PATTERN_SCREEN_ORIGIN | + HARDWARE_PATTERN_PROGRAMMED_BITS | + NO_TRANSPARENCY | + BIT_ORDER_IN_BYTE_MSBFIRST ; + +#ifdef STSCE + /* Screen To Screen Color Expand */ + /* TW: The hardware does support this the way we need it */ + infoPtr->SetupForScreenToScreenColorExpandFill = + SiSSetupForScreenToScreenColorExpand; + infoPtr->SubsequentScreenToScreenColorExpandFill = + SiSSubsequentScreenToScreenColorExpand; + infoPtr->ScreenToScreenColorExpandFillFlags = NO_PLANEMASK | + BIT_ORDER_IN_BYTE_MSBFIRST ; +#endif + +#if 0 + /* CPU To Screen Color Expand --- implement another instead of this one! */ + infoPtr->SetupForCPUToScreenColorExpandFill = + SiSSetupForCPUToScreenColorExpand; + infoPtr->SubsequentCPUToScreenColorExpandFill = + SiSSubsequentCPUToScreenColorExpand; + infoPtr->ColorExpandRange = PATREGSIZE; + infoPtr->ColorExpandBase = pSiS->IOBase+PBR(0); + infoPtr->CPUToScreenColorExpandFillFlags = NO_PLANEMASK | + BIT_ORDER_IN_BYTE_MSBFIRST | + NO_TRANSPARENCY | + SYNC_AFTER_COLOR_EXPAND | + HARDWARE_PATTERN_SCREEN_ORIGIN | + HARDWARE_PATTERN_PROGRAMMED_BITS ; +#endif + + /* per-scanline color expansion (using indirect method) */ + if(pSiS->VGAEngine == SIS_530_VGA) { + pSiS->ColorExpandBufferNumber = 4; + pSiS->ColorExpandBufferCountMask = 0x03; + } else { + pSiS->ColorExpandBufferNumber = 16; + pSiS->ColorExpandBufferCountMask = 0x0F; + } + pSiS->PerColorExpandBufferSize = ((pScrn->virtualX + 31)/32) * 4; + infoPtr->NumScanlineColorExpandBuffers = pSiS->ColorExpandBufferNumber; + infoPtr->ScanlineColorExpandBuffers = (unsigned char **)&pSiS->ColorExpandBufferAddr[0]; + + infoPtr->SetupForScanlineCPUToScreenColorExpandFill = + SiSSetupForScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = + SiSSubsequentScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentColorExpandScanline = + SiSSubsequentColorExpandScanline; + infoPtr->ScanlineCPUToScreenColorExpandFillFlags = + NO_PLANEMASK | + CPU_TRANSFER_PAD_DWORD | + SCANLINE_PAD_DWORD | + BIT_ORDER_IN_BYTE_MSBFIRST | + LEFT_EDGE_CLIPPING; + +#ifdef SISDUALHEAD + if (pSiS->DualHeadMode) { + infoPtr->RestoreAccelState = SiSRestoreAccelState; + } +#endif + + /* init Frame Buffer Manager */ + topFB = pSiS->maxxfbmem; + + reservedFbSize = pSiS->ColorExpandBufferNumber * pSiS->PerColorExpandBufferSize; + + UsableFbSize = topFB - reservedFbSize; + + /* Layout: (Sizes do not reflect correct proportions) + * |--------------++++++++++++++++++++^************==========~~~~~~~~~~~~| + * UsableFbSize ColorExpandBuffers | DRI-Heap | HWCursor TurboQueue 300/310/325 series + * |--------------++++++++++++++++++++| ====================~~~~~~~~~~~~| + * UsableFbSize ColorExpandBuffers | TurboQueue HWCursor 530/620 + * topFB + */ + + AvailBufBase = pSiS->FbBase + UsableFbSize; + for (i = 0; i < pSiS->ColorExpandBufferNumber; i++) { + pSiS->ColorExpandBufferAddr[i] = AvailBufBase + + i * pSiS->PerColorExpandBufferSize; + pSiS->ColorExpandBufferScreenOffset[i] = UsableFbSize + + i * pSiS->PerColorExpandBufferSize; + } + Avail.x1 = 0; + Avail.y1 = 0; + Avail.x2 = pScrn->displayWidth; + Avail.y2 = (UsableFbSize / (pScrn->displayWidth * pScrn->bitsPerPixel/8)) - 1; + + if(Avail.y2 < 0) Avail.y2 = 32767; + + if(Avail.y2 < pScrn->currentMode->VDisplay) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Not enough video RAM for accelerator. At least " + "%dKB needed, %dKB available\n", + ((((pScrn->displayWidth * pScrn->bitsPerPixel/8) /* TW: +8 for make it sure */ + * pScrn->currentMode->VDisplay) + reservedFbSize) / 1024) + 8, + pSiS->maxxfbmem/1024); + pSiS->NoAccel = TRUE; + pSiS->NoXvideo = TRUE; + XAADestroyInfoRec(pSiS->AccelInfoPtr); + pSiS->AccelInfoPtr = NULL; + return FALSE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Frame Buffer From (%d,%d) To (%d,%d)\n", + Avail.x1, Avail.y1, Avail.x2, Avail.y2); + + xf86InitFBManager(pScreen, &Avail); + + return(XAAInit(pScreen, infoPtr)); +} + + +static void +SiSSync(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("SiSSync()\n")); + + pSiS->DoColorExpand = FALSE; + SiSIdle +} + +#ifdef SISDUALHEAD +static void +SiSRestoreAccelState(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + + /* TW: We don't need to do anything special here; forcing the + * other head to re-read the CmdQueLen is not necessary: + * After the Sync in RestoreAccelState(), the real queue + * length is always larger than (or at least equal to) + * the amount stored in CmdQueueLen of the other head, + * so the only thing that might happen is one unnecessary + * Sync on the other head. I think we can live with that. + */ + pSiS->DoColorExpand = FALSE; + SiSIdle +} +#endif + +static const int 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 int 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 */ +}; + +static void SiSSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, int trans_color) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("Setup ScreenCopy(%d, %d, 0x%x, 0x%x, 0x%x)\n", + xdir, ydir, rop, planemask, trans_color)); + + SiSSetupDSTColorDepth(pSiS->DstColor); + SiSSetupSRCPitch(pSiS->scrnOffset) + SiSSetupDSTRect(pSiS->scrnOffset, -1) + + if(trans_color != -1) { + SiSSetupROP(0x0A) + SiSSetupSRCTrans(trans_color) + SiSSetupCMDFlag(TRANSPARENT_BITBLT) + } else { + SiSSetupROP(sisALUConv[rop]) + } + if(xdir > 0) { + SiSSetupCMDFlag(X_INC) + } + if(ydir > 0) { + SiSSetupCMDFlag(Y_INC) + } +} + +static void SiSSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int src_x, int src_y, int dst_x, int dst_y, + int width, int height) +{ + SISPtr pSiS = SISPTR(pScrn); + long srcbase, dstbase; + + PDEBUG(ErrorF("Subsequent ScreenCopy(%d,%d, %d,%d, %d,%d)\n", + src_x, src_y, dst_x, dst_y, width, height)); + + srcbase = dstbase = 0; + if(src_y >= 2048) { + srcbase = pSiS->scrnOffset * src_y; + src_y = 0; + } + if( (dst_y >= pScrn->virtualY) || (dst_y >= 2048) ) { + dstbase = pSiS->scrnOffset * dst_y; + dst_y = 0; + } +#ifdef SISDUALHEAD + if(pSiS->VGAEngine != SIS_530_VGA) { + srcbase += HEADOFFSET; + dstbase += HEADOFFSET; + } +#endif + SiSSetupSRCBase(srcbase); + SiSSetupDSTBase(dstbase); + + if(!(pSiS->CommandReg & X_INC)) { + src_x += width-1; + dst_x += width-1; + } + if(!(pSiS->CommandReg & Y_INC)) { + src_y += height-1; + dst_y += height-1; + } + SiSSetupRect(width, height) + SiSSetupSRCXY(src_x, src_y) + SiSSetupDSTXY(dst_x, dst_y) + + SiSDoCMD +} + +static void +SiSSetupForSolidFill(ScrnInfoPtr pScrn, + int color, int rop, unsigned int planemask) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("Setup SolidFill(0x%x, 0x%x, 0x%x)\n", + color, rop, planemask)); + + SiSSetupPATFG(color) + SiSSetupDSTRect(pSiS->scrnOffset, -1) + SiSSetupDSTColorDepth(pSiS->DstColor); + SiSSetupROP(sisPatALUConv[rop]) + /* SiSSetupCMDFlag(PATFG) - is zero */ +} + +static void +SiSSubsequentSolidFillRect(ScrnInfoPtr pScrn, + int x, int y, int w, int h) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase; + + PDEBUG(ErrorF("Subsequent SolidFillRect(%d, %d, %d, %d)\n", + x, y, w, h)); + dstbase = 0; + + if (y >= 2048) { + dstbase = pSiS->scrnOffset * y; + y = 0; + } +#ifdef SISDUALHEAD + if(pSiS->VGAEngine != SIS_530_VGA) { + dstbase += HEADOFFSET; + } +#endif + SiSSetupDSTBase(dstbase) + SiSSetupDSTXY(x,y) + SiSSetupRect(w,h) + /* Clear commandReg because Setup can be used for Rect and Trap */ + pSiS->CommandReg &= ~(T_XISMAJORL | T_XISMAJORR | + T_L_X_INC | T_L_Y_INC | + T_R_X_INC | T_R_Y_INC | + TRAPAZOID_FILL); + SiSSetupCMDFlag(X_INC | Y_INC | BITBLT) + + SiSDoCMD +} + +/* TW: Trapezoid */ +/* This would work better if XAA would provide us with valid trapezoids. + * In fact, with small trapezoids the left and the right edge often cross + * each other or result in a line length of 0 which causes drawing errors + * (filling over whole scanline). + * Furthermore, I have not found out how to draw trapezoids with a height + * greater than 127. + */ +#ifdef TRAP +static void +SiSSubsequentSolidFillTrap(ScrnInfoPtr pScrn, int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR ) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase; +#if 0 + float kL, kR; +#endif + + dstbase = 0; + if (y >= 2048) { + dstbase=pSiS->scrnOffset*y; + y = 0; + } +#ifdef SISDUALHEAD + if(pSiS->VGAEngine != SIS_530_VGA) { + dstbase += HEADOFFSET; + } +#endif + SiSSetupDSTBase(dstbase) + /* SiSSetupRect(w,h) */ + +#if 1 + SiSSetupPATFG(0xff0000) /* FOR TESTING */ +#endif + + /* Clear CommandReg because SetUp can be used for Rect and Trap */ + pSiS->CommandReg &= ~(T_L_X_INC | T_L_Y_INC | + T_R_X_INC | T_R_Y_INC | + T_XISMAJORL | T_XISMAJORR | + BITBLT); + + xf86DrvMsg(0, X_INFO, "Trap (%d %d %d %d) dxL %d dyL %d eL %d dxR %d dyR %d eR %d\n", + left, right, y, h, dxL, dyL, eL, dxR, dyR, eR); + + /* Unfortunately, we must check if the right and the left edge + * cross each other... INCOMPLETE (line equation wrong) + */ +#if 0 + if (dxL == 0) kL = 0; + else kL = (float)dyL / (float)dxL; + if (dxR == 0) kR = 0; + else kR = (float)dyR / (float)dxR; + xf86DrvMsg(0, X_INFO, "kL %f kR %f!\n", kL, kR); + if ( (kR != kL) && + (!(kR == 0 && kL == 0)) && + (!(kR < 0 && kL > 0)) ) { + xf86DrvMsg(0, X_INFO, "Inside if (%f - %d)\n", ( kL * ( ( ((float)right - (float)left) / (kL - kR) ) - left) + y), h+y); + if ( ( ( kL * ( ( ((float)right - (float)left) / (kL - kR) ) - (float)left) + (float)y) < (h + y) ) ) { + xf86DrvMsg(0, X_INFO, "Cross detected!\n"); + } + } +#endif + + /* Determine egde angles */ + if (dxL < 0) { dxL = -dxL; } + else { SiSSetupCMDFlag(T_L_X_INC) } + if (dxR < 0) { dxR = -dxR; } + else { SiSSetupCMDFlag(T_R_X_INC) } + + /* (Y direction always positive - do this anyway) */ + if (dyL < 0) { dyL = -dyL; } + else { SiSSetupCMDFlag(T_L_Y_INC) } + if (dyR < 0) { dyR = -dyR; } + else { SiSSetupCMDFlag(T_R_Y_INC) } + + /* Determine major axis */ + if (dxL >= dyL) { /* X is major axis */ + SiSSetupCMDFlag(T_XISMAJORL) + } + if (dxR >= dyR) { /* X is major axis */ + SiSSetupCMDFlag(T_XISMAJORR) + } + + /* Set up deltas */ + SiSSetupdL(dxL, dyL) + SiSSetupdR(dxR, dyR) + +#if 0 /* Could it be that this crappy engine can only draw trapezoids up to 127 pixels high? */ + h &= 0x7F; + if (h == 0) h = 10; +#endif + + /* Set up y, h, left, right */ + SiSSetupYH(y,h) + SiSSetupLR(left,right) + + /* Set up initial error term */ + SiSSetupEL(eL) + SiSSetupER(eR) + + SiSSetupCMDFlag(TRAPAZOID_FILL); + + SiSDoCMD +} +#endif + +static void +SiSSetupForSolidLine(ScrnInfoPtr pScrn, + int color, int rop, unsigned int planemask) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("Setup SolidLine(0x%x, 0x%x, 0x%x)\n", + color, rop, planemask)); + + SiSSetupLineCount(1) + SiSSetupPATFG(color) + SiSSetupDSTRect(pSiS->scrnOffset, -1) + SiSSetupDSTColorDepth(pSiS->DstColor); + SiSSetupROP(sisPatALUConv[rop]) + SiSSetupCMDFlag(PATFG | LINE) +} + +static void +SiSSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, int flags) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase,miny,maxy; + + PDEBUG(ErrorF("Subsequent SolidLine(%d, %d, %d, %d, 0x%x)\n", + x1, y1, x2, y2, flags)); + + dstbase = 0; + miny = (y1 > y2) ? y2 : y1; + maxy = (y1 > y2) ? y1 : y2; + if(maxy >= 2048) { + dstbase = pSiS->scrnOffset * miny; + y1 -= miny; + y2 -= miny; + } +#ifdef SISDUALHEAD + if(pSiS->VGAEngine != SIS_530_VGA) { + dstbase += HEADOFFSET; + } +#endif + SiSSetupDSTBase(dstbase) + + SiSSetupX0Y0(x1,y1) + SiSSetupX1Y1(x2,y2) + if (flags & OMIT_LAST) { + SiSSetupCMDFlag(NO_LAST_PIXEL) + } else { + pSiS->CommandReg &= ~(NO_LAST_PIXEL); + } + + SiSDoCMD +} + +static void +SiSSubsequentSolidHorzVertLine(ScrnInfoPtr pScrn, + int x, int y, int len, int dir) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase; + + PDEBUG(ErrorF("Subsequent SolidHorzVertLine(%d, %d, %d, %d)\n", + x, y, len, dir)); + len--; /* starting point is included! */ + + dstbase = 0; + if((y >= 2048) || ((y + len) >= 2048)) { + dstbase = pSiS->scrnOffset * y; + y = 0; + } +#ifdef SISDUALHEAD + if(pSiS->VGAEngine != SIS_530_VGA) { + dstbase += HEADOFFSET; + } +#endif + SiSSetupDSTBase(dstbase) + + SiSSetupX0Y0(x,y) + if (dir == DEGREES_0) { + SiSSetupX1Y1(x + len, y); + } else { + SiSSetupX1Y1(x, y + len); + } + + SiSDoCMD +} + +static void +SiSSetupForDashedLine(ScrnInfoPtr pScrn, + int fg, int bg, int rop, unsigned int planemask, + int length, unsigned char *pattern) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("Setup DashedLine(0x%x, 0x%x, 0x%x, 0x%x, %d, 0x%x:%x)\n", + fg, bg, rop, planemask, length, *(pattern+4), *pattern)); + + SiSSetupLineCount(1) + SiSSetupDSTRect(pSiS->scrnOffset, -1) + SiSSetupDSTColorDepth(pSiS->DstColor); + SiSSetupStyleLow(*pattern) + SiSSetupStyleHigh(*(pattern+4)) + SiSSetupStylePeriod(length-1); /* TW: This was missing!!! */ + SiSSetupROP(sisPatALUConv[rop]) + SiSSetupPATFG(fg) + SiSSetupCMDFlag(LINE | LINE_STYLE) /* TW: This was missing!!! */ + if(bg != -1) { + SiSSetupPATBG(bg) + } else { + SiSSetupCMDFlag(TRANSPARENT); /* TW: This was missing!!! */ + } +} + +static void +SiSSubsequentDashedTwoPointLine(ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, + int flags, int phase) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase,miny,maxy; + + PDEBUG(ErrorF("Subsequent DashedLine(%d,%d, %d,%d, 0x%x,0x%x)\n", + x1, y1, x2, y2, flags, phase)); + + dstbase = 0; + miny = (y1 > y2) ? y2 : y1; + maxy = (y1 > y2) ? y1 : y2; + if(maxy >= 2048) { + dstbase = pSiS->scrnOffset * miny; + y1 -= miny; + y2 -= miny; + } +#ifdef SISDUALHEAD + if(pSiS->VGAEngine != SIS_530_VGA) { + dstbase += HEADOFFSET; + } +#endif + SiSSetupDSTBase(dstbase) + + SiSSetupX0Y0(x1,y1) + SiSSetupX1Y1(x2,y2) + if(flags & OMIT_LAST) { + SiSSetupCMDFlag(NO_LAST_PIXEL) + } else { + pSiS->CommandReg &= ~(NO_LAST_PIXEL); + } + + SiSDoCMD +} + +static void +SiSSetupForMonoPatternFill(ScrnInfoPtr pScrn, + int patx, int paty, int fg, int bg, + int rop, unsigned int planemask) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("Setup MonoPatFill(0x%x,0x%x, 0x%x,0x%x, 0x%x, 0x%x)\n", + patx, paty, fg, bg, rop, planemask)); + SiSSetupDSTRect(pSiS->scrnOffset, -1) + SiSSetupDSTColorDepth(pSiS->DstColor); + SiSSetupMONOPAT(patx,paty) + SiSSetupPATFG(fg) + SiSSetupROP(sisPatALUConv[rop]) + SiSSetupCMDFlag(PATMONO) + SiSSetupPATBG(bg) +} + +static void +SiSSubsequentMonoPatternFill(ScrnInfoPtr pScrn, + int patx, int paty, + int x, int y, int w, int h) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase; + + PDEBUG(ErrorF("Subsequent MonoPatFill(0x%x,0x%x, %d,%d, %d,%d)\n", + patx, paty, x, y, w, h)); + dstbase = 0; + + if (y >= 2048) { + dstbase = pSiS->scrnOffset * y; + y = 0; + } +#ifdef SISDUALHEAD + if(pSiS->VGAEngine != SIS_530_VGA) { + dstbase += HEADOFFSET; + } +#endif + SiSSetupDSTBase(dstbase) + SiSSetupDSTXY(x, y) + SiSSetupRect(w, h) + /* Clear commandReg because Setup can be used for Rect and Trap */ + pSiS->CommandReg &= ~(T_XISMAJORL | T_XISMAJORR | + T_L_X_INC | T_L_Y_INC | + T_R_X_INC | T_R_Y_INC | + TRAPAZOID_FILL); + SiSSetupCMDFlag(X_INC | Y_INC) + + SiSDoCMD +} + +/* Trapezoid */ +#ifdef TRAP +static void +SiSSubsequentMonoPatternFillTrap(ScrnInfoPtr pScrn, + int patx, int paty, + int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR ) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase; + + PDEBUG(ErrorF("Subsequent Mono8x8PatternFillTrap(%d, %d, %d - %d %d/%d %d/%d)\n", + y, h, left, right, dxL, dxR, eL, eR)); + + dstbase = 0; + if (y >= 2048) { + dstbase=pSiS->scrnOffset*y; + y = 0; + } +#ifdef SISDUALHEAD + if(pSiS->VGAEngine != SIS_530_VGA) { + dstbase += HEADOFFSET; + } +#endif + SiSSetupDSTBase(dstbase) + + /* Clear CommandReg because SetUp can be used for Rect and Trap */ + pSiS->CommandReg &= ~(T_XISMAJORL | T_XISMAJORR | + T_L_X_INC | T_L_Y_INC | + T_R_X_INC | T_R_Y_INC | + BITBLT); + + if (dxL < 0) { dxL = -dxL; } + else { SiSSetupCMDFlag(T_L_X_INC) } + if (dxR < 0) { dxR = -dxR; } + else { SiSSetupCMDFlag(T_R_X_INC) } + + if (dyL < 0) { dyL = -dyL; } + else { SiSSetupCMDFlag(T_L_Y_INC) } + if (dyR < 0) { dyR = -dyR; } + else { SiSSetupCMDFlag(T_R_Y_INC) } + + /* Determine major axis */ + if (dxL >= dyL) { /* X is major axis */ + SiSSetupCMDFlag(T_XISMAJORL) + } + if (dxR >= dyR) { /* X is major axis */ + SiSSetupCMDFlag(T_XISMAJORR) + } + + SiSSetupYH(y,h) + SiSSetupLR(left,right) + + SiSSetupdL(dxL, dyL) + SiSSetupdR(dxR, dyR) + + SiSSetupEL(eL) + SiSSetupER(eR) + + SiSSetupCMDFlag(TRAPAZOID_FILL); + + SiSDoCMD +} +#endif + + +#if 0 + +/* TW: The following (already commented) functions have NOT been adapted for dual-head mode */ + + +/* ------- Color Pattern Fill --- is not useful for XAA -------------- */ + +static void +SiSSetupForColorPatternFill(ScrnInfoPtr pScrn, + int patx, int paty, int rop, + unsigned int planemask, + int trans_color) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("Setup ColorPatFill(0x%x,0x%x, 0x%x,0x%x, 0x%x)\n", + patx, paty, rop, planemask, trans_color)); + +/* SiSSetupDSTRect(pSiS->scrnOffset, pScrn->virtualY)*/ + SiSSetupDSTRect(pSiS->scrnOffset, -1) + SiSSetupDSTColorDepth(pSiS->DstColor); + SiSSetupROP(sisPatALUConv[rop]) + SiSSetupCMDFlag(PATPATREG | X_INC | Y_INC) +} + +static void +SiSSubsequentColorPatternFill(ScrnInfoPtr pScrn, + int patx, int paty, + int x, int y, int w, int h) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase; + + PDEBUG(ErrorF("Subsequent ColorPatFill(0x%x,0x%x, %d,%d, %d,%d)\n", + patx, paty, x, y, w, h)); + + dstbase = 0; + if (y >= 2048) { + dstbase = pSiS->scrnOffset * y; + y = 0; + } + SiSSetupDSTBase(dstbase) + SiSSetupDSTXY(x,y) + SiSSetupRect(w,h) + SiSDoCMD +} + +/* ----- CPU To Screen Color Expand (single task) ------------------------- */ + +/* This does not work. Assumingly for the same + * reason why STSColorExpand does not work either. + */ +static void +SiSSetupForCPUToScreenColorExpand(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, unsigned int planemask) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("Setup CPUToScreen ColorExpand(0x%x,0x%x, 0x%x,0x%x)\n", + fg, bg, rop, planemask)); + +/* SiSSetupDSTRect(pSiS->scrnOffset, pScrn->virtualY)*/ + SiSSetupDSTRect(pSiS->scrnOffset, -1) + SiSSetupDSTColorDepth(pSiS->DstColor); + SiSSetupSRCXY(0,0) + SiSSetupSRCFG(fg) + SiSSetupROP(sisPatALUConv[rop]) + SiSSetupCMDFlag(X_INC | Y_INC | COLOREXP) + if (bg == -1) { + SiSSetupCMDFlag(TRANSPARENT) + } + else { + SiSSetupSRCBG(bg) + } +} + +static void +SiSSubsequentCPUToScreenColorExpand(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase; + + PDEBUG(ErrorF("Subsequent CPUToScreen ColorExpand(%d,%d, %d,%d, %d)\n", + x, y, w, h, skipleft)); + + dstbase = 0; + if (y >= 2048) { + dstbase = pSiS->scrnOffset * y; + y = 0; + } + SiSSetupDSTBase(dstbase) + +/* SiSSetupSRCPitch(((w+31)&0xFFE0)/8)*/ + SiSSetupSRCPitch((w+7)/8) + SiSSetupDSTXY(x,y) + SiSSetupRect(w,h) +/* SiSDoCMD*/ + pSiS->DoColorExpand = TRUE; +} +#endif + +/* ------ Screen To Screen Color Expand ------------------------------- */ + +/* TW: The hareware does not seem to support this the way we need it */ + +#ifdef STSCE +static void +SiSSetupForScreenToScreenColorExpand(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, unsigned int planemask) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("Setup ScreenToScreen ColorExp(0x%x,0x%x, 0x%x)\n", + fg, bg, rop)); + + SiSSetupDSTColorDepth(pSiS->DstColor) + SiSSetupDSTRect(pSiS->scrnOffset, -1) + SiSSetupROP(sisALUConv[rop]) + SiSSetupSRCFG(fg) + /* SiSSetupSRCXY(0,0) */ + + if(bg == -1) { + SiSSetupCMDFlag(TRANSPARENT | ENCOLOREXP | X_INC | + Y_INC | SRCVIDEO); + } else { + SiSSetupSRCBG(bg); + SiSSetupCMDFlag(ENCOLOREXP | X_INC | Y_INC | + SRCVIDEO); + }; +} +#endif + +/* TW. This method blits in a single task; this does not seem to work + * because the hardware does not use the source pitch as scanline + * offset but only to calculate pattern address from source X and Y. + * XAA provides the pattern bitmap with scrnOffset (displayWidth * bpp/8) + * offset, but this does not seem to be supported by the hardware. + */ +#ifdef STSCE + +/* For testing, these are the methods: (use only one at a time!) */ + +#undef npitch /* Normal: Use srcx/y as srcx/y, use scrnOffset as source pitch + * This would work if the hareware used the source pitch for + * incrementing the source address after each scanline - but + * it doesn't do this! The first line of the area is correctly + * color expanded, but since the source pitch is ignored and + * the source address not incremented correctly, the following + * lines are color expanded with any bit pattern that is left + * in the unused space of the source bitmap (which is organized + * with the depth of the screen framebuffer hence with a pitch + * of scrnOffset). + */ + +#undef pitchdw /* Use source pitch "displayWidth / 8" instead + * of scrnOffset (=displayWidth * bpp / 8) + * This can't work, because the pitch of the source + * bitmap is scrnoffset! + */ + +#define nopitch /* Calculate srcbase with srcx and srcy, set the + * pitch to scrnOffset (which IS the correct pitch + * for the source bitmap) and set srcx and srcy both + * to 0. + * This would work if the hareware used the source pitch for + * incrementing the source address after each scanline - but + * it doesn't do this! Again: The first line of the area is + * correctly color expanded, but since the source pitch is + * ignored for scanline address incremention, the following + * lines are not correctly color expanded. + * WHATEVER I write to source pitch is ignored! + */ + +static void +SiSSubsequentScreenToScreenColorExpand(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int srcx, int srcy, int skipleft) +{ + SISPtr pSiS = SISPTR(pScrn); + long srcbase, dstbase; +#if 0 + int _x0, _y0, _x1, _y1; +#endif +#ifdef pitchdw + int newsrcx, newsrcy; + + /* srcx and srcy are provided based on a scrnOffset pitch ( = displayWidth * bpp / 8 ) + * We recalulate srcx and srcy based on pitch = displayWidth / 8 + */ + newsrcy = ((pSiS->scrnOffset * srcy) + (srcx * ((pScrn->bitsPerPixel+7)/8))) / + (pScrn->displayWidth/8); + newsrcx = ((pSiS->scrnOffset * srcy) + (srcx * ((pScrn->bitsPerPixel+7)/8))) % + (pScrn->displayWidth/8); +#endif + xf86DrvMsg(0, X_INFO, "Sub ScreenToScreen ColorExp(%d,%d, %d,%d, %d,%d, %d)\n", + x, y, w, h, srcx, srcy, skipleft); + + srcbase = dstbase = 0; + +#ifdef pitchdw + if (newsrcy >= 2048) { + srcbase = (pScrn->displayWidth / 8) * newsrcy; + newsrcy = 0; + } +#endif +#ifdef nopitch + srcbase = (pSiS->scrnOffset * srcy) + (srcx * ((pScrn->bitsPerPixel+7)/8)); +#endif +#ifdef npitch + if (srcy >= 2048) { + srcbase = pSiS->scrnOffset * srcy; + srcy = 0; + } +#endif + if (y >= 2048) { + dstbase = pSiS->scrnOffset * y; + y = 0; + } +#ifdef SISDUALHEAD + if(pSiS->VGAEngine != SIS_530_VGA) { + srcbase += HEADOFFSET; + dstbase += HEADOFFSET; + } +#endif + SiSSetupSRCBase(srcbase) + SiSSetupDSTBase(dstbase) + +#ifdef pitchdw + SiSSetupSRCPitch(pScrn->displayWidth/8) +#endif +#ifdef nopitch + SiSSetupSRCPitch(pSiS->scrnOffset) + /* SiSSetupSRCPitch(100) */ /* For test - has NO effect WHATSOEVER */ +#endif +#ifdef npitch + SiSSetupSRCPitch(pSiS->scrnOffset) +#endif + + SiSSetupRect(w,h) + +#if 0 /* How do I implement the offset? Not this way, that's for sure.. */ + if (skipleft > 0) { + _x0 = x+skipleft; + _y0 = y; + _x1 = x+w; + _y1 = y+h; + SiSSetupClipLT(_x0, _y0); + SiSSetupClipRB(_x1, _y1); + SiSSetupCMDFlag(CLIPENABLE); + } +#endif +#ifdef pitchdw + SiSSetupSRCXY(newsrcx, newsrcy) +#endif +#ifdef nopitch + SiSSetupSRCXY(0,0) +#endif +#ifdef npitch + SiSSetupSRCXY(srcx, srcy) +#endif + + SiSSetupDSTXY(x,y) + + SiSDoCMD +} +#endif + +/* TW: TEST: Do it scanline-wise because the other way does not seem to + * be supported by the hardware. (The source pitch seems to be + * displayWidth * (bbp/8) as opposed by the XAA HOWTO, where + * it is stated that the pitch would be displayWidth pixels; + * besides, the hardware seems to ignore the source pitch + * for address increments.) + * Apart from this (which can be solved by doing the color + * expand scanline-wise), I don't know how to implement the + * offset argument. The current method (which uses hardware + * clipping) does not work. + * + * THIS DOES NOT WORK IN THE CURRENT STATE. + */ +#if 0 +static void +SiSSubsequentScreenToScreenColorExpand(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int srcx, int srcy, int offset) +{ + SISPtr pSiS = SISPTR(pScrn); + long srcbase, dstbase; + int _x0, _y0, _x1, _y1; + + int newsrcx, newsrcy; + + newsrcy = ((pSiS->scrnOffset * srcy) + (srcx * ((pScrn->bitsPerPixel+7)/8))) / + (((((w+7)/8)+3) >> 2) * 4); + /* (pScrn->displayWidth/8); */ + newsrcx = ((pSiS->scrnOffset * srcy) + (srcx * ((pScrn->bitsPerPixel+7)/8))) % + (((((w+7)/8)+3) >> 2) * 4); + /* (pScrn->displayWidth/8); */ + + xf86DrvMsg(0, X_INFO, "Sub STS CE(%d,%d, %d,%d, %d,%d, %d)\n", + x, y, w, h, srcx, srcy, skipleft); + + srcbase = dstbase = 0; + if (newsrcy >= 2048) { + srcbase = (((((w+7)/8)+3) >> 2) * 4) * newsrcy; + /* (pScrn->displayWidth/8) * newsrcy; */ + /* pSiS->scrnOffset * srcy; */ + newsrcy = 0; + } + if (y >= 2048) { + dstbase = pSiS->scrnOffset * y; + y = 0; + } +#ifdef SISDUALHEAD + srcbase += HEADOFFSET; + dstbase += HEADOFFSET; +#endif + SiSSetupDSTBase(dstbase) + + SiSSetupRect(w, 1) + + SiSSetupSRCXY(newsrcx, newsrcy) + + /* SiSSetupSRCPitch(pScrn->displayWidth/8) */ /* old: (((w+31)&0xFFE0)/8) */ + SiSSetupSRCPitch(((((w+7)/8)+3) >> 2) * 4) +#if 1 + if (offset > 0) { + SiSSetupCMDFlag(CLIPENABLE) + } else + pSiS->CommandReg &= ~CLIPENABLE; +#endif + + while (h) { + + SiSSetupSRCBase(srcbase) +#if 1 + if (offset > 0) { + _x0 = x+skipleft; + _y0 = y; + _x1 = x+w; + _y1 = y+h; + SiSSetupClipLT(_x0, _y0); + SiSSetupClipRB(_x1, _y1); + } +#endif + SiSSetupDSTXY(x,y) + + SiSDoCMD + + srcbase += ((((w+7)/8)+3) >> 2) * 4 * 8* ((pScrn->bitsPerPixel+7)/8); + /* pSiS->scrnOffset; */ + y++; + h--; + } +} +#endif + + +/* ----- CPU To Screen Color Expand (scanline-wise) ----------------- */ + +/* We do it using the indirect method */ + +static void +SiSSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, int rop, unsigned int planemask) +{ + SISPtr pSiS=SISPTR(pScrn); + + /* TW: Make sure that current CPU-driven BitBlt buffer stage is 0 + * This is required!!! (Otherwise -> drawing errors) + */ + while((MMIO_IN16(pSiS->IOBase, 0x8242) & 0x1F00) != 0) {} /* WDR: == 0x10 */ + +#if 0 /* TW: This is obviously not needed */ + pSiS->ColorExpandRingHead = 0; + pSiS->ColorExpandRingTail = pSiS->ColorExpandBufferNumber - 1; +#endif + + SiSSetupSRCXY(0,0); + SiSSetupROP(sisALUConv[rop]); + SiSSetupSRCFG(fg); + SiSSetupDSTRect(pSiS->scrnOffset, -1); + SiSSetupDSTColorDepth(pSiS->DstColor); + if(bg == -1) { + SiSSetupCMDFlag(TRANSPARENT | + ENCOLOREXP | + X_INC | Y_INC | + SRCCPUBLITBUF); + } else { + SiSSetupSRCBG(bg); + SiSSetupCMDFlag(ENCOLOREXP | + X_INC | Y_INC | + SRCCPUBLITBUF); + } +} + + +static void +SiSSubsequentScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, int x, int y, int w, + int h, int skipleft) +{ + SISPtr pSiS = SISPTR(pScrn); + int _x0, _y0, _x1, _y1; + long dstbase; + + dstbase = 0; + if (y >= 2048) { + dstbase = pSiS->scrnOffset * y; + y = 0; + } +#ifdef SISDUALHEAD + if(pSiS->VGAEngine != SIS_530_VGA) { + dstbase += HEADOFFSET; + } +#endif + + /* TW: Wait until there is no color expansion command in queue + * (This solves the OpenOffice.org window-move bug) + * Added Idle-check - bit 23 is set sometimes, although + * engine is actually idle! + * Update: Bit 23 is not reliable. After heavy 3D engine + * action, this bit never gets cleared again. So do + * SiSIdle instead. + */ + if((MMIO_IN16(pSiS->IOBase, 0x8242) & 0xe000) != 0xe000) { + /* while ((MMIO_IN16(pSiS->IOBase, 0x8242) & 0x0080) != 0) {} */ + SiSIdle + } + + SiSSetupDSTBase(dstbase) + + if (skipleft > 0) { + _x0 = x + skipleft; + _y0 = y; + _x1 = x + w; + _y1 = y + h; + SiSSetupClipLT(_x0, _y0); + SiSSetupClipRB(_x1, _y1); + SiSSetupCMDFlag(CLIPENABLE); + } else { + pSiS->CommandReg &= (~CLIPENABLE); + } + + SiSSetupRect(w, 1); + SiSSetupSRCPitch(((((w+7)/8)+3) >> 2) * 4); + pSiS->xcurrent = x; + pSiS->ycurrent = y; +} + +static void +SiSSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) +{ + SISPtr pSiS=SISPTR(pScrn); +#if 0 + int newhead,bltbufstage,newtail; +#endif + long cbo; + + cbo = pSiS->ColorExpandBufferScreenOffset[bufno]; +#ifdef SISDUALHEAD + if(pSiS->VGAEngine != SIS_530_VGA) { + cbo += HEADOFFSET; + } +#endif + + /* TW: Wait until there is no color expansion command in queue + * (This solves the GTK-big-font bug) + * Added Idle-check - bit 23 is set sometimes, although + * engine is actually idle! + * Update: Bit 23 is not reliable. After heavy 3D engine + * action, this bit never gets cleared again. So do + * SiSIdle instead. + */ + if((MMIO_IN16(pSiS->IOBase, 0x8242) & 0xe000) != 0xe000) { + /* while ((MMIO_IN16(pSiS->IOBase, 0x8242) & 0x0080) != 0) {} */ + SiSIdle + } + + SiSSetupSRCBase(cbo); + + SiSSetupDSTXY(pSiS->xcurrent, pSiS->ycurrent); + + SiSDoCMD + + pSiS->ycurrent++; + + if(pSiS->VGAEngine == SIS_530_VGA) { + while(MMIO_IN8(pSiS->IOBase, 0x8242) & 0x80) {} + } + +#if 0 /* TW: What is this good for? The Head/Tail data is never ever used elsewhere! */ + pSiS->ColorExpandRingHead = newhead = + (bufno + 1) & pSiS->ColorExpandBufferCountMask; + while (newhead == pSiS->ColorExpandRingTail) { + bltbufstage = (int)((MMIO_IN16(pSiS->IOBase,0x8242) & 0x1F00) >> 8); + newtail = newhead - (bltbufstage + 1); + pSiS->ColorExpandRingTail = (newtail >= 0) ? + newtail : (pSiS->ColorExpandBufferNumber + newtail); + } +#endif +} + diff --git a/src/sis300_accel.h b/src/sis300_accel.h new file mode 100644 index 0000000..33948d0 --- /dev/null +++ b/src/sis300_accel.h @@ -0,0 +1,297 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis300_accel.h,v 1.8 2003/01/29 15:42:16 eich Exp $ */ +/* + * 2D acceleration for SiS530/620 and 300 series + * + * Copyright 1998,1999 by Alan Hourihane, Wigan, England. + * Parts Copyright 2002 Thomas Winischhofer, Vienna, Austria + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk + * Mike Chapman <mike@paranoia.com>, + * Juanjo Santamarta <santamarta@ctv.es>, + * Mitani Hiroshi <hmitani@drl.mei.co.jp> + * David Thomas <davtom@dream.org.uk>. + * Xavier Ducoin <x.ducoin@lectra.com> + * Thomas Winischhofer <thomas@winischhofer.net> + */ + + +/* 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 */ + +/* 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 */ +#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 + +/* Trapezoid */ +#define T_XISMAJORL 0x00800000 /* X axis is driving axis (left) */ +#define T_XISMAJORR 0x01000000 /* X axis is driving axis (right) */ +#define T_L_Y_INC Y_INC /* left edge direction Y */ +#define T_L_X_INC X_INC /* left edge direction X */ +#define T_R_Y_INC 0x00400000 /* right edge direction Y */ +#define T_R_X_INC 0x00200000 /* right edge direction X */ + +/* ? */ +#define DSTAGP 0x02000000 +#define DSTVIDEO 0x02000000 + +/* Line */ +#define LINE_STYLE 0x00800000 +#define NO_RESET_COUNTER 0x00400000 +#define NO_LAST_PIXEL 0x00200000 + + +/* Macros to do useful things with the SIS BitBLT engine */ + +/* 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 (530/620: 12:0) + +*/ + +/* TW: BR(16)+2 = 0x8242 */ + +#define CmdQueLen pSiS->cmdQueueLen + +#define SiSIdle \ + { \ + while( (MMIO_IN16(pSiS->IOBase, BR(16)+2) & 0xE000) != 0xE000){}; \ + while( (MMIO_IN16(pSiS->IOBase, BR(16)+2) & 0xE000) != 0xE000){}; \ + while( (MMIO_IN16(pSiS->IOBase, BR(16)+2) & 0xE000) != 0xE000){}; \ + CmdQueLen = (MMIO_IN16(pSiS->IOBase, 0x8240) & pSiS->CmdQueLenMask) - pSiS->CmdQueLenFix; \ + } +/* TW: (do three times, because 2D engine seems quite unsure about whether or not it's idle) */ + +#define SiSSetupSRCBase(base) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(0), base);\ + CmdQueLen--; + +#define SiSSetupSRCPitch(pitch) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT16(pSiS->IOBase, BR(1), pitch);\ + CmdQueLen--; + +#define SiSSetupSRCXY(x,y) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(2), (x)<<16 | (y) );\ + CmdQueLen--; + +#define SiSSetupDSTBase(base) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(4), base);\ + CmdQueLen--; + +#define SiSSetupDSTXY(x,y) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(3), (x)<<16 | (y) );\ + CmdQueLen--; + +#define SiSSetupDSTRect(x,y) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(5), (y)<<16 | (x) );\ + CmdQueLen--; + +#define SiSSetupDSTColorDepth(bpp) \ + if(pSiS->VGAEngine != SIS_530_VGA) { \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT16(pSiS->IOBase, BR(1)+2, bpp);\ + CmdQueLen--; \ + } + +#define SiSSetupRect(w,h) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(6), (h)<<16 | (w) );\ + CmdQueLen--; + +#define SiSSetupPATFG(color) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(7), color);\ + CmdQueLen--; + +#define SiSSetupPATBG(color) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(8), color);\ + CmdQueLen--; + +#define SiSSetupSRCFG(color) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(9), color);\ + CmdQueLen--; + +#define SiSSetupSRCBG(color) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(10), color);\ + CmdQueLen--; + +/* 0x8224 src colorkey high */ +/* 0x8228 src colorkey low */ +/* 0x821c dest colorkey high */ +/* 0x8220 dest colorkey low */ +#define SiSSetupSRCTrans(color) \ + if (CmdQueLen <= 1) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, 0x8224, color);\ + MMIO_OUT32(pSiS->IOBase, 0x8228, color);\ + CmdQueLen -= 2; + +#define SiSSetupDSTTrans(color) \ + if (CmdQueLen <= 1) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, 0x821C, color); \ + MMIO_OUT32(pSiS->IOBase, 0x8220, color); \ + CmdQueLen -= 2; + +#define SiSSetupMONOPAT(p0,p1) \ + if (CmdQueLen <= 1) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(11), p0);\ + MMIO_OUT32(pSiS->IOBase, BR(12), p1);\ + CmdQueLen -= 2; + +#define SiSSetupClipLT(left,top) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\ + CmdQueLen--; + +#define SiSSetupClipRB(right,bottom) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\ + CmdQueLen--; + +/* General */ +#define SiSSetupROP(rop) \ + pSiS->CommandReg = (rop) << 8; + +#define SiSSetupCMDFlag(flags) \ + pSiS->CommandReg |= (flags); + +#define SiSDoCMD \ + if (CmdQueLen <= 1) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(15), pSiS->CommandReg); \ + CmdQueLen--; \ + if(pSiS->VGAEngine != SIS_530_VGA) { \ + MMIO_OUT32(pSiS->IOBase, BR(16), 0);\ + CmdQueLen--; \ + } else { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, BR(16)); \ + } \ + +/* Line */ +#define SiSSetupX0Y0(x,y) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(2), (y)<<16 | (x) );\ + CmdQueLen--; + +#define SiSSetupX1Y1(x,y) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(3), (y)<<16 | (x) );\ + CmdQueLen--; + +#define SiSSetupLineCount(c) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT16(pSiS->IOBase, BR(6), c);\ + CmdQueLen--; + +#define SiSSetupStylePeriod(p) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT16(pSiS->IOBase, BR(6)+2, p);\ + CmdQueLen--; + +#define SiSSetupStyleLow(ls) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(11), ls);\ + CmdQueLen--; + +#define SiSSetupStyleHigh(ls) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, BR(12), ls);\ + CmdQueLen--; + +/* TW: Trapezoid */ +#define SiSSetupYH(y,h) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, 0x8208, (y)<<16 | (h) );\ + CmdQueLen--; + +#define SiSSetupLR(left,right) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, 0x820C, (right)<<16 | (left) );\ + CmdQueLen--; + +#define SiSSetupdL(dxL,dyL) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, 0x8244, (dyL)<<16 | (dxL) );\ + CmdQueLen--; + +#define SiSSetupdR(dxR,dyR) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, 0x8248, (dyR)<<16 | (dxR) );\ + CmdQueLen--; + +#define SiSSetupEL(eL) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, 0x824C, eL);\ + CmdQueLen--; + +#define SiSSetupER(eR) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, 0x8250, eR);\ + CmdQueLen--; + diff --git a/src/sis310_accel.c b/src/sis310_accel.c new file mode 100644 index 0000000..aeee273 --- /dev/null +++ b/src/sis310_accel.c @@ -0,0 +1,894 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis310_accel.c,v 1.2 2003/01/29 15:42:16 eich Exp $ */ +/* + * 2D Acceleration for SiS 310/325 series (315, 550, 650, 740, M650, 651) + * + * Copyright 2002 by Thomas Winischhofer, Vienna, Austria + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Thomas Winischhofer not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Winischhofer makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS WINISCHHOFER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS WINISCHHOFER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Based on sis300_accel.c + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "compiler.h" +#include "xaa.h" + +#include "sis.h" +#include "sis310_accel.h" + +#ifdef SISDUALHEAD +/* TW: This is the offset to the memory for each head */ +#define HEADOFFSET (pSiS->dhmOffset) +#endif + +#undef TRAP /* TW: Use/Don't use Trapezoid Fills - does not work - XAA provides + * illegal trapezoid data (left and right edges cross each other + * sometimes) which causes drawing errors. + */ + +#define CTSCE /* Use/Don't use CPUToScreenColorExpand. */ + +/* Accelerator functions */ +static void SiSInitializeAccelerator(ScrnInfoPtr pScrn); +static void SiSSync(ScrnInfoPtr pScrn); +static void SiSSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, int trans_color); +static void SiSSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, + int width, int height); +static void SiSSetupForSolidFill(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void SiSSubsequentSolidFillRect(ScrnInfoPtr pScrn, + int x, int y, int w, int h); +#ifdef TRAP +static void SiSSubsequentSolidFillTrap(ScrnInfoPtr pScrn, int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR); +#endif +static void SiSSetupForSolidLine(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void SiSSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, + int y1, int x2, int y2, int flags); +static void SiSSubsequentSolidHorzVertLine(ScrnInfoPtr pScrn, + int x, int y, int len, int dir); +static void SiSSetupForDashedLine(ScrnInfoPtr pScrn, + int fg, int bg, int rop, unsigned int planemask, + int length, unsigned char *pattern); +static void SiSSubsequentDashedTwoPointLine(ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, + int flags, int phase); +static void SiSSetupForMonoPatternFill(ScrnInfoPtr pScrn, + int patx, int paty, int fg, int bg, + int rop, unsigned int planemask); +static void SiSSubsequentMonoPatternFill(ScrnInfoPtr pScrn, + int patx, int paty, + int x, int y, int w, int h); +#ifdef TRAP +static void SiSSubsequentMonoPatternFillTrap(ScrnInfoPtr pScrn, + int patx, int paty, + int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR); +#endif +#ifdef CTSCE +static void SiSSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); +static void SiSSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft); +static void SiSSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); +#endif + +#ifdef SISDUALHEAD +static void SiSRestoreAccelState(ScrnInfoPtr pScrn); +#endif + +static void +SiSInitializeAccelerator(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + + pSiS->DoColorExpand = FALSE; +} + +Bool +SiS310AccelInit(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + int topFB; + int reservedFbSize; + int UsableFbSize; + unsigned char *AvailBufBase; + BoxRec Avail; + int i; + + pSiS->AccelInfoPtr = infoPtr = XAACreateInfoRec(); + if (!infoPtr) + return FALSE; + + SiSInitializeAccelerator(pScrn); + + infoPtr->Flags = LINEAR_FRAMEBUFFER | + OFFSCREEN_PIXMAPS | + PIXMAP_CACHE; + + /* sync */ + infoPtr->Sync = SiSSync; + + if ((pScrn->bitsPerPixel != 8) && (pScrn->bitsPerPixel != 16) && + (pScrn->bitsPerPixel != 32)) + return FALSE; + + /* BitBlt */ + infoPtr->SetupForScreenToScreenCopy = SiSSetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = SiSSubsequentScreenToScreenCopy; + infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK | TRANSPARENCY_GXCOPY_ONLY; + /*| NO_TRANSPARENCY; */ + + /* solid fills */ + infoPtr->SetupForSolidFill = SiSSetupForSolidFill; + infoPtr->SubsequentSolidFillRect = SiSSubsequentSolidFillRect; +#ifdef TRAP + infoPtr->SubsequentSolidFillTrap = SiSSubsequentSolidFillTrap; +#endif + infoPtr->SolidFillFlags = NO_PLANEMASK; + + /* solid line */ + infoPtr->SetupForSolidLine = SiSSetupForSolidLine; + infoPtr->SubsequentSolidTwoPointLine = SiSSubsequentSolidTwoPointLine; + infoPtr->SubsequentSolidHorVertLine = SiSSubsequentSolidHorzVertLine; + infoPtr->SolidLineFlags = NO_PLANEMASK; + + /* dashed line */ + infoPtr->SetupForDashedLine = SiSSetupForDashedLine; + infoPtr->SubsequentDashedTwoPointLine = SiSSubsequentDashedTwoPointLine; + infoPtr->DashPatternMaxLength = 64; + infoPtr->DashedLineFlags = NO_PLANEMASK | + LINE_PATTERN_MSBFIRST_LSBJUSTIFIED; + + /* 8x8 mono pattern fill */ + infoPtr->SetupForMono8x8PatternFill = SiSSetupForMonoPatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = SiSSubsequentMonoPatternFill; +#ifdef TRAP + infoPtr->SubsequentMono8x8PatternFillTrap = SiSSubsequentMonoPatternFillTrap; +#endif + infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK | + HARDWARE_PATTERN_SCREEN_ORIGIN | + HARDWARE_PATTERN_PROGRAMMED_BITS | + NO_TRANSPARENCY | + BIT_ORDER_IN_BYTE_MSBFIRST ; + +#if 0 + /* Screen To Screen Color Expand */ + /* TW: The hardware does not seem to support this the way we need it */ + infoPtr->SetupForScreenToScreenColorExpandFill = + SiSSetupForScreenToScreenColorExpand; + infoPtr->SubsequentScreenToScreenColorExpandFill = + SiSSubsequentScreenToScreenColorExpand; + infoPtr->ScreenToScreenColorExpandFillFlags = NO_PLANEMASK | + BIT_ORDER_IN_BYTE_MSBFIRST ; +#endif + + /* per-scanline color expansion - indirect method */ + pSiS->ColorExpandBufferNumber = 16; + pSiS->ColorExpandBufferCountMask = 0x0F; + pSiS->PerColorExpandBufferSize = ((pScrn->virtualX + 31)/32) * 4; +#ifdef CTSCE + infoPtr->NumScanlineColorExpandBuffers = pSiS->ColorExpandBufferNumber; + infoPtr->ScanlineColorExpandBuffers = (unsigned char **)&pSiS->ColorExpandBufferAddr[0]; + infoPtr->SetupForScanlineCPUToScreenColorExpandFill = SiSSetupForScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = SiSSubsequentScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentColorExpandScanline = SiSSubsequentColorExpandScanline; + infoPtr->ScanlineCPUToScreenColorExpandFillFlags = + NO_PLANEMASK | + CPU_TRANSFER_PAD_DWORD | + SCANLINE_PAD_DWORD | + BIT_ORDER_IN_BYTE_MSBFIRST | + LEFT_EDGE_CLIPPING; +#endif + +#ifdef SISDUALHEAD + if (pSiS->DualHeadMode) { + infoPtr->RestoreAccelState = SiSRestoreAccelState; + } +#endif + + /* init Frame Buffer Manager */ + + topFB = pSiS->maxxfbmem; + + reservedFbSize = (pSiS->ColorExpandBufferNumber + * pSiS->PerColorExpandBufferSize); + /* TW: New for MaxXFBmem Option */ + UsableFbSize = topFB - reservedFbSize; + /* Layout: + * |--------------++++++++++++++++++++^************==========~~~~~~~~~~~~| + * UsableFbSize ColorExpandBuffers | DRI-Heap HWCursor CommandQueue + * topFB + */ + AvailBufBase = pSiS->FbBase + UsableFbSize; + for (i = 0; i < pSiS->ColorExpandBufferNumber; i++) { + pSiS->ColorExpandBufferAddr[i] = AvailBufBase + + i * pSiS->PerColorExpandBufferSize; + pSiS->ColorExpandBufferScreenOffset[i] = UsableFbSize + + i * pSiS->PerColorExpandBufferSize; + } + Avail.x1 = 0; + Avail.y1 = 0; + Avail.x2 = pScrn->displayWidth; + Avail.y2 = UsableFbSize + / (pScrn->displayWidth * pScrn->bitsPerPixel/8) - 1; + if (Avail.y2 < 0) + Avail.y2 = 32767; + if (Avail.y2 < pScrn->currentMode->VDisplay) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Not enough video RAM for accelerator. At least " + "%dKB needed, %dKB available\n", + ((((pScrn->displayWidth * pScrn->bitsPerPixel/8) /* TW: +8 for make it sure */ + * pScrn->currentMode->VDisplay) + reservedFbSize) / 1024) + 8, + pSiS->maxxfbmem/1024); + pSiS->NoAccel = TRUE; + pSiS->NoXvideo = TRUE; + XAADestroyInfoRec(pSiS->AccelInfoPtr); + pSiS->AccelInfoPtr = NULL; + return FALSE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Frame Buffer From (%d,%d) To (%d,%d)\n", + Avail.x1, Avail.y1, Avail.x2, Avail.y2); + + xf86InitFBManager(pScreen, &Avail); + + return(XAAInit(pScreen, infoPtr)); +} + +static void +SiSSync(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("SiSSync()\n")); + + pSiS->DoColorExpand = FALSE; + SiSIdle +} + +#ifdef SISDUALHEAD +static void +SiSRestoreAccelState(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + + /* TW: We don't need to do anything special here */ + pSiS->DoColorExpand = FALSE; + SiSIdle +} +#endif + +static const int 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 int 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 */ +}; + +static void SiSSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, int trans_color) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("Setup ScreenCopy(%d, %d, 0x%x, 0x%x, 0x%x)\n", + xdir, ydir, rop, planemask, trans_color)); + + /* "AGP base" - color depth depending value (see sis_vga.c) */ + SiSSetupDSTColorDepth(pSiS->DstColor); + /* SRC pitch */ + SiSSetupSRCPitch(pSiS->scrnOffset) + /* DST pitch and height (-1 for disabling merge-clipping) */ + SiSSetupDSTRect(pSiS->scrnOffset, -1) + /* Init CommandReg and set ROP */ + if (trans_color != -1) { + SiSSetupROP(0x0A) + SiSSetupSRCTrans(trans_color) + SiSSetupCMDFlag(TRANSPARENT_BITBLT) + } else { + SiSSetupROP(sisALUConv[rop]) + /* Set command - not needed, both 0 */ + /* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */ + } + /* Set some color depth depending value (see sis_vga.c) */ + SiSSetupCMDFlag(pSiS->SiS310_AccelDepth) + + /* TW: The 310/325 series is smart enough to know the direction */ +} + +static void SiSSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int src_x, int src_y, int dst_x, int dst_y, + int width, int height) +{ + SISPtr pSiS = SISPTR(pScrn); + long srcbase, dstbase; + + PDEBUG(ErrorF("Subsequent ScreenCopy(%d,%d, %d,%d, %d,%d)\n", + src_x, src_y, dst_x, dst_y, width, height)); + + srcbase = dstbase = 0; + if (src_y >= 2048) { + srcbase = pSiS->scrnOffset * src_y; + src_y = 0; + } + if ((dst_y >= pScrn->virtualY) || (dst_y >= 2048)) { + dstbase = pSiS->scrnOffset*dst_y; + dst_y = 0; + } +#ifdef SISDUALHEAD + srcbase += HEADOFFSET; + dstbase += HEADOFFSET; +#endif + SiSSetupSRCBase(srcbase); + SiSSetupDSTBase(dstbase); + SiSSetupRect(width, height) + SiSSetupSRCXY(src_x, src_y) + SiSSetupDSTXY(dst_x, dst_y) + SiSDoCMD +} + +static void +SiSSetupForSolidFill(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("Setup SolidFill(0x%x, 0x%x, 0x%x)\n", + color, rop, planemask)); + + SiSSetupPATFG(color) + SiSSetupDSTRect(pSiS->scrnOffset, -1) + SiSSetupDSTColorDepth(pSiS->DstColor); + SiSSetupROP(sisPatALUConv[rop]) + SiSSetupCMDFlag(PATFG | pSiS->SiS310_AccelDepth) +} + +static void +SiSSubsequentSolidFillRect(ScrnInfoPtr pScrn, + int x, int y, int w, int h) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase; + + PDEBUG(ErrorF("Subsequent SolidFillRect(%d, %d, %d, %d)\n", + x, y, w, h)); + dstbase = 0; + if (y >= 2048) { + dstbase=pSiS->scrnOffset*y; + y = 0; + } +#ifdef SISDUALHEAD + dstbase += HEADOFFSET; +#endif + SiSSetupDSTBase(dstbase) + SiSSetupDSTXY(x,y) + SiSSetupRect(w,h) + pSiS->CommandReg &= ~(T_XISMAJORL | T_XISMAJORR | + T_L_X_INC | T_L_Y_INC | + T_R_X_INC | T_R_Y_INC | + TRAPAZOID_FILL); + SiSSetupCMDFlag(BITBLT) + SiSDoCMD +} + +/* TW: Trapezoid */ +/* This would work better if XAA would provide us with valid trapezoids. + * In fact, with small trapezoids the left and the right edge often cross + * each other which causes drawing errors (filling over whole scanline). + */ +#ifdef TRAP +static void +SiSSubsequentSolidFillTrap(ScrnInfoPtr pScrn, int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR ) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase; +#if 0 + float kL, kR; +#endif + + dstbase = 0; + if (y >= 2048) { + dstbase=pSiS->scrnOffset*y; + y = 0; + } +#ifdef SISDUALHEAD + dstbase += HEADOFFSET; +#endif + SiSSetupDSTBase(dstbase) + +#if 1 + SiSSetupPATFG(0xff0000) /* FOR TESTING */ +#endif + + /* Clear CommandReg because SetUp can be used for Rect and Trap */ + pSiS->CommandReg &= ~(T_L_X_INC | T_L_Y_INC | + T_R_X_INC | T_R_Y_INC | + T_XISMAJORL | T_XISMAJORR | + BITBLT); + + xf86DrvMsg(0, X_INFO, "Trap (%d %d %d %d) dxL %d dyL %d eL %d dxR %d dyR %d eR %d\n", + left, right, y, h, dxL, dyL, eL, dxR, dyR, eR); + + /* Unfortunately, we must check if the right and the left edge + * cross each other... INCOMPLETE (equation wrong) + */ +#if 0 + if (dxL == 0) kL = 0; + else kL = (float)dyL / (float)dxL; + if (dxR == 0) kR = 0; + else kR = (float)dyR / (float)dxR; + xf86DrvMsg(0, X_INFO, "kL %f kR %f!\n", kL, kR); + if ( (kR != kL) && + (!(kR == 0 && kL == 0)) && + (!(kR < 0 && kL > 0)) ) { + xf86DrvMsg(0, X_INFO, "Inside if (%f - %d)\n", ( kL * ( ( ((float)right - (float)left) / (kL - kR) ) - left) + y), h+y); + if ( ( ( kL * ( ( ((float)right - (float)left) / (kL - kR) ) - (float)left) + (float)y) < (h + y) ) ) { + xf86DrvMsg(0, X_INFO, "Cross detected!\n"); + } + } +#endif + + /* Determine egde angles */ + if (dxL < 0) { dxL = -dxL; } + else { SiSSetupCMDFlag(T_L_X_INC) } + if (dxR < 0) { dxR = -dxR; } + else { SiSSetupCMDFlag(T_R_X_INC) } + + /* (Y direction always positive - do this anyway) */ + if (dyL < 0) { dyL = -dyL; } + else { SiSSetupCMDFlag(T_L_Y_INC) } + if (dyR < 0) { dyR = -dyR; } + else { SiSSetupCMDFlag(T_R_Y_INC) } + + /* Determine major axis */ + if (dxL >= dyL) { /* X is major axis */ + SiSSetupCMDFlag(T_XISMAJORL) + } + if (dxR >= dyR) { /* X is major axis */ + SiSSetupCMDFlag(T_XISMAJORR) + } + + /* Set up deltas */ + SiSSetupdL(dxL, dyL) + SiSSetupdR(dxR, dyR) + + /* Set up y, h, left, right */ + SiSSetupYH(y,h) + SiSSetupLR(left,right) + + /* Set up initial error term */ + SiSSetupEL(eL) + SiSSetupER(eR) + + SiSSetupCMDFlag(TRAPAZOID_FILL); + + SiSDoCMD +} +#endif + +static void +SiSSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("Setup SolidLine(0x%x, 0x%x, 0x%x)\n", + color, rop, planemask)); + + SiSSetupLineCount(1) + SiSSetupPATFG(color) + SiSSetupDSTRect(pSiS->scrnOffset, -1) + SiSSetupDSTColorDepth(pSiS->DstColor); + SiSSetupROP(sisPatALUConv[rop]) + SiSSetupCMDFlag(PATFG | LINE | pSiS->SiS310_AccelDepth) +} + +static void +SiSSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, int flags) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase,miny,maxy; + + PDEBUG(ErrorF("Subsequent SolidLine(%d, %d, %d, %d, 0x%x)\n", + x1, y1, x2, y2, flags)); + + dstbase = 0; + miny = (y1 > y2) ? y2 : y1; + maxy = (y1 > y2) ? y1 : y2; + if (maxy >= 2048) { + dstbase = pSiS->scrnOffset*miny; + y1 -= miny; + y2 -= miny; + } +#ifdef SISDUALHEAD + dstbase += HEADOFFSET; +#endif + SiSSetupDSTBase(dstbase) + + SiSSetupX0Y0(x1,y1) + SiSSetupX1Y1(x2,y2) + if (flags & OMIT_LAST) { + SiSSetupCMDFlag(NO_LAST_PIXEL) + } else { + pSiS->CommandReg &= ~(NO_LAST_PIXEL); + } + SiSDoCMD +} + +static void +SiSSubsequentSolidHorzVertLine(ScrnInfoPtr pScrn, + int x, int y, int len, int dir) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase; + + PDEBUG(ErrorF("Subsequent SolidHorzVertLine(%d, %d, %d, %d)\n", + x, y, len, dir)); + + len--; /* starting point is included! */ + dstbase = 0; + if ((y >= 2048) || ((y + len) >= 2048)) { + dstbase = pSiS->scrnOffset * y; + y = 0; + } +#ifdef SISDUALHEAD + dstbase += HEADOFFSET; +#endif + SiSSetupDSTBase(dstbase) + + SiSSetupX0Y0(x,y) + if (dir == DEGREES_0) { + SiSSetupX1Y1(x + len, y); + } else { + SiSSetupX1Y1(x, y + len); + } + SiSDoCMD +} + +static void +SiSSetupForDashedLine(ScrnInfoPtr pScrn, + int fg, int bg, int rop, unsigned int planemask, + int length, unsigned char *pattern) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("Setup DashedLine(0x%x, 0x%x, 0x%x, 0x%x, %d, 0x%x:%x)\n", + fg, bg, rop, planemask, length, *(pattern+4), *pattern)); + + SiSSetupLineCount(1) + SiSSetupDSTRect(pSiS->scrnOffset, -1) + SiSSetupDSTColorDepth(pSiS->DstColor); + SiSSetupStyleLow(*pattern) + SiSSetupStyleHigh(*(pattern+4)) + SiSSetupStylePeriod(length-1); /* TW: This was missing!!! */ + SiSSetupROP(sisPatALUConv[rop]) + SiSSetupPATFG(fg) + SiSSetupCMDFlag(LINE | LINE_STYLE) /* TW: This was missing!!! */ + if (bg != -1) { + SiSSetupPATBG(bg) + } else { + SiSSetupCMDFlag(TRANSPARENT) /* TW: This was missing!!! */ + } + SiSSetupCMDFlag(pSiS->SiS310_AccelDepth) +} + +static void +SiSSubsequentDashedTwoPointLine(ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, + int flags, int phase) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase,miny,maxy; + + PDEBUG(ErrorF("Subsequent DashedLine(%d,%d, %d,%d, 0x%x,0x%x)\n", + x1, y1, x2, y2, flags, phase)); + + dstbase = 0; + miny=(y1 > y2) ? y2 : y1; + maxy=(y1 > y2) ? y1 : y2; + if (maxy >= 2048) { + dstbase = pSiS->scrnOffset * miny; + y1 -= miny; + y2 -= miny; + } +#ifdef SISDUALHEAD + dstbase += HEADOFFSET; +#endif + SiSSetupDSTBase(dstbase) + + SiSSetupX0Y0(x1,y1) + SiSSetupX1Y1(x2,y2) + if (flags & OMIT_LAST) { + SiSSetupCMDFlag(NO_LAST_PIXEL) + } else { + pSiS->CommandReg &= ~(NO_LAST_PIXEL); + } + SiSDoCMD +} + +static void +SiSSetupForMonoPatternFill(ScrnInfoPtr pScrn, + int patx, int paty, int fg, int bg, + int rop, unsigned int planemask) +{ + SISPtr pSiS = SISPTR(pScrn); + + PDEBUG(ErrorF("Setup MonoPatFill(0x%x,0x%x, 0x%x,0x%x, 0x%x, 0x%x)\n", + patx, paty, fg, bg, rop, planemask)); + SiSSetupDSTRect(pSiS->scrnOffset, -1) + SiSSetupDSTColorDepth(pSiS->DstColor); + SiSSetupMONOPAT(patx,paty) + SiSSetupPATFG(fg) + SiSSetupROP(sisPatALUConv[rop]) + SiSSetupCMDFlag(PATMONO | pSiS->SiS310_AccelDepth) + SiSSetupPATBG(bg) +} + +static void +SiSSubsequentMonoPatternFill(ScrnInfoPtr pScrn, + int patx, int paty, + int x, int y, int w, int h) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase; + + PDEBUG(ErrorF("Subsequent MonoPatFill(0x%x,0x%x, %d,%d, %d,%d)\n", + patx, paty, x, y, w, h)); + dstbase = 0; + if (y >= 2048) { + dstbase = pSiS->scrnOffset * y; + y = 0; + } +#ifdef SISDUALHEAD + dstbase += HEADOFFSET; +#endif + SiSSetupDSTBase(dstbase) + SiSSetupDSTXY(x,y) + SiSSetupRect(w,h) + /* Clear commandReg because Setup can be used for Rect and Trap */ + pSiS->CommandReg &= ~(T_XISMAJORL | T_XISMAJORR | + T_L_X_INC | T_L_Y_INC | + T_R_X_INC | T_R_Y_INC | + TRAPAZOID_FILL); + SiSDoCMD +} + +/* TW: Trapezoid */ +#ifdef TRAP +static void +SiSSubsequentMonoPatternFillTrap(ScrnInfoPtr pScrn, + int patx, int paty, + int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR) +{ + SISPtr pSiS = SISPTR(pScrn); + long dstbase; + + PDEBUG(ErrorF("Subsequent Mono8x8PatternFillTrap(%d, %d, %d - %d %d/%d %d/%d)\n", + y, h, left, right, dxL, dxR, eL, eR)); + + dstbase = 0; + if (y >= 2048) { + dstbase=pSiS->scrnOffset*y; + y = 0; + } +#ifdef SISDUALHEAD + dstbase += HEADOFFSET; +#endif + SiSSetupDSTBase(dstbase) + + /* Clear CommandReg because SetUp can be used for Rect and Trap */ + pSiS->CommandReg &= ~(T_XISMAJORL | T_XISMAJORR | + T_L_X_INC | T_L_Y_INC | + T_R_X_INC | T_R_Y_INC | + BITBLT); + + if (dxL < 0) { dxL = -dxL; } + else { SiSSetupCMDFlag(T_L_X_INC) } + if (dxR < 0) { dxR = -dxR; } + else { SiSSetupCMDFlag(T_R_X_INC) } + + if (dyL < 0) { dyL = -dyL; } + else { SiSSetupCMDFlag(T_L_Y_INC) } + if (dyR < 0) { dyR = -dyR; } + else { SiSSetupCMDFlag(T_R_Y_INC) } + + /* Determine major axis */ + if (dxL >= dyL) { /* X is major axis */ + SiSSetupCMDFlag(T_XISMAJORL) + } + if (dxR >= dyR) { /* X is major axis */ + SiSSetupCMDFlag(T_XISMAJORR) + } + + SiSSetupYH(y,h) + SiSSetupLR(left,right) + + SiSSetupdL(dxL, dyL) + SiSSetupdR(dxR, dyR) + + SiSSetupEL(eL) + SiSSetupER(eR) + + SiSSetupCMDFlag(TRAPAZOID_FILL); + + SiSDoCMD +} +#endif + +/* ---- CPUToScreen Color Expand */ + +#ifdef CTSCE +/* We use the indirect method */ +static void +SiSSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, int rop, unsigned int planemask) +{ + SISPtr pSiS=SISPTR(pScrn); + + /* TW: FIXME: How do I check the "CPU driven blit stage" on the + * 310/325 series? + * That's the 300 series method but definitely wrong for + * 310/325 series (bit 28 is already used for idle!) + */ + /* while ((MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x1F00) != 0) {} */ + + /* TW: Do Idle instead... */ + SiSIdle + + SiSSetupSRCXY(0,0); + SiSSetupROP(sisALUConv[rop]); + SiSSetupSRCFG(fg); + SiSSetupDSTRect(pSiS->scrnOffset, -1); + SiSSetupDSTColorDepth(pSiS->DstColor); + if (bg == -1) { + SiSSetupCMDFlag(TRANSPARENT | ENCOLOREXP | SRCCPUBLITBUF + | pSiS->SiS310_AccelDepth); + } else { + SiSSetupSRCBG(bg); + SiSSetupCMDFlag(ENCOLOREXP | SRCCPUBLITBUF + | pSiS->SiS310_AccelDepth); + }; +} + +static void +SiSSubsequentScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, int x, int y, int w, + int h, int skipleft) +{ + SISPtr pSiS = SISPTR(pScrn); + int _x0, _y0, _x1, _y1; + long dstbase; + + dstbase = 0; + if (y >= 2048) { + dstbase = pSiS->scrnOffset*y; + y = 0; + } +#ifdef SISDUALHEAD + dstbase += HEADOFFSET; +#endif + + if((MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000) { + SiSIdle; + } + + SiSSetupDSTBase(dstbase) + + if (skipleft > 0) { + _x0 = x+skipleft; + _y0 = y; + _x1 = x+w; + _y1 = y+h; + SiSSetupClipLT(_x0, _y0); + SiSSetupClipRB(_x1, _y1); + SiSSetupCMDFlag(CLIPENABLE); + } else { + pSiS->CommandReg &= (~CLIPENABLE); + } + SiSSetupRect(w, 1); + SiSSetupSRCPitch(((((w+7)/8)+3) >> 2) * 4); + pSiS->ycurrent = y; + pSiS->xcurrent = x; +} + +static void +SiSSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) +{ + SISPtr pSiS=SISPTR(pScrn); + long cbo; + + cbo = pSiS->ColorExpandBufferScreenOffset[bufno]; +#ifdef SISDUALHEAD + cbo += HEADOFFSET; +#endif + + if((MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000) { + SiSIdle; + } + + SiSSetupSRCBase(cbo); + + SiSSetupDSTXY(pSiS->xcurrent, pSiS->ycurrent); + + SiSDoCMD + + pSiS->ycurrent++; + + SiSIdle +} +#endif + + diff --git a/src/sis310_accel.h b/src/sis310_accel.h new file mode 100644 index 0000000..9a6b20a --- /dev/null +++ b/src/sis310_accel.h @@ -0,0 +1,341 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis310_accel.h,v 1.2 2003/01/29 15:42:16 eich Exp $ */ +/* + * Copyright 2002 by Thomas Winischhofer, Vienna, Austria + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Thomas Winischhofer not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Winischhofer makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS WINISCHHOFER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS WINISCHHOFER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Based on sis300_accel.h + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * + */ + +/* Definitions for the SIS engine communication. */ + + +/* SiS310 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 */ +#define ALPHA_BLEND 0x00000007 /* Alpha blend ? */ +#define A3D_FUNCTION 0x00000008 /* 3D command ? */ +#define CLEAR_Z_BUFFER 0x00000009 /* ? */ +#define GRADIENT_FILL 0x0000000A /* Gradient fill */ +#define STRETCH_BITBLT 0x0000000B /* Stretched Blit */ + +/* Command bits */ + +/* Source selection */ +#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 source selection */ +#define PATFG 0x00000000 /* foreground color */ +#define PATPATREG 0x00000040 /* pattern in pattern buffer (0x8300) */ +#define PATMONO 0x00000080 /* mono pattern */ + +/* 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 */ +#define COLOR_TO_MONO 0x00100000 +#define AA_TEXT 0x00200000 + +/* Line */ +#define LINE_STYLE 0x00800000 +#define NO_RESET_COUNTER 0x00400000 +#define NO_LAST_PIXEL 0x00200000 + +/* Trapezoid */ +#define T_XISMAJORL 0x00800000 /* X axis is driving axis (left) */ +#define T_XISMAJORR 0x08000000 /* X axis is driving axis (right) */ +#define T_L_Y_INC 0x00000020 /* left edge direction Y */ +#define T_L_X_INC 0x00000010 /* left edge direction X */ +#define T_R_Y_INC 0x00400000 /* right edge direction Y */ +#define T_R_X_INC 0x00200000 /* right edge direction X */ + +/* Some general registers */ +#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 */ + +/* Line registers */ +#define LINE_X0 SRC_Y +#define LINE_X1 DST_Y +#define LINE_Y0 SRC_X +#define LINE_Y1 DST_X +#define LINE_COUNT RECT_WIDTH +#define LINE_STYLE_PERIOD RECT_HEIGHT +#define LINE_STYLE_0 MONO_MASK +#define LINE_STYLE_1 0x8230 +#define LINE_XN PATTERN_REG +#define LINE_YN PATTERN_REG+2 + +/* 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 + +/* Trapezoid registers */ +#define TRAP_YH SRC_Y /* 0x8208 */ +#define TRAP_LR DST_Y /* 0x820C */ +#define TRAP_DL 0x8244 +#define TRAP_DR 0x8248 +#define TRAP_EL 0x824C +#define TRAP_ER 0x8250 + +/* Queue */ +#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 */ + +/* Macros to do useful things with the SIS 310 BitBLT engine */ + +/* 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 + + Where is the command queue length (current amount of commands the queue + can accept) on the 310 series? (The current implementation is taken + from 300 series and certainly wrong...) +*/ + +int CmdQueLen; + +/* TW: FIXME: CmdQueLen is... where....? */ +#define SiSIdle \ + { \ + while( (MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000){}; \ + while( (MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000){}; \ + CmdQueLen=MMIO_IN16(pSiS->IOBase, Q_STATUS); \ + } + /* TW: (do twice like on 300 series?) */ + +#define SiSSetupSRCBase(base) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, SRC_ADDR, base);\ + CmdQueLen--; + +#define SiSSetupSRCPitch(pitch) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT16(pSiS->IOBase, SRC_PITCH, pitch);\ + CmdQueLen--; + +#define SiSSetupSRCXY(x,y) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, SRC_Y, (x)<<16 | (y) );\ + CmdQueLen--; + +#define SiSSetupDSTBase(base) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, DST_ADDR, base);\ + CmdQueLen--; + +#define SiSSetupDSTXY(x,y) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, DST_Y, (x)<<16 | (y) );\ + CmdQueLen--; + +#define SiSSetupDSTRect(x,y) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, DST_PITCH, (y)<<16 | (x) );\ + CmdQueLen--; + +#define SiSSetupDSTColorDepth(bpp) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT16(pSiS->IOBase, AGP_BASE, bpp);\ + CmdQueLen--; + +#define SiSSetupRect(w,h) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, RECT_WIDTH, (h)<<16 | (w) );\ + CmdQueLen--; + +#define SiSSetupPATFG(color) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, PAT_FGCOLOR, color);\ + CmdQueLen--; + +#define SiSSetupPATBG(color) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, PAT_BGCOLOR, color);\ + CmdQueLen--; + +#define SiSSetupSRCFG(color) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, SRC_FGCOLOR, color);\ + CmdQueLen--; + +#define SiSSetupSRCBG(color) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, SRC_BGCOLOR, color);\ + CmdQueLen--; + +#define SiSSetupSRCTrans(color) \ + if (CmdQueLen <= 1) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, TRANS_SRC_KEY_HIGH, color);\ + MMIO_OUT32(pSiS->IOBase, TRANS_SRC_KEY_LOW, color);\ + CmdQueLen -= 2; + +#define SiSSetupDSTTrans(color) \ + if (CmdQueLen <= 1) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, TRANS_DST_KEY_HIGH, color); \ + MMIO_OUT32(pSiS->IOBase, TRANS_DST_KEY_LOW, color); \ + CmdQueLen -= 2; + +#define SiSSetupMONOPAT(p0,p1) \ + if (CmdQueLen <= 1) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, MONO_MASK, p0);\ + MMIO_OUT32(pSiS->IOBase, MONO_MASK+4, p1);\ + CmdQueLen=CmdQueLen-2; + +#define SiSSetupClipLT(left,top) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\ + CmdQueLen--; + +#define SiSSetupClipRB(right,bottom) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\ + CmdQueLen--; + +#define SiSSetupROP(rop) \ + pSiS->CommandReg = (rop) << 8; + +#define SiSSetupCMDFlag(flags) \ + pSiS->CommandReg |= (flags); + +#define SiSDoCMD \ + if (CmdQueLen <= 1) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, COMMAND_READY, pSiS->CommandReg); \ + MMIO_OUT32(pSiS->IOBase, FIRE_TRIGGER, 0); \ + CmdQueLen=CmdQueLen-2; + +#define SiSSetupX0Y0(x,y) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, LINE_X0, (y)<<16 | (x) );\ + CmdQueLen--; + +#define SiSSetupX1Y1(x,y) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, LINE_X1, (y)<<16 | (x) );\ + CmdQueLen--; + +#define SiSSetupLineCount(c) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT16(pSiS->IOBase, LINE_COUNT, c);\ + CmdQueLen--; + +#define SiSSetupStylePeriod(p) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT16(pSiS->IOBase, LINE_STYLE_PERIOD, p);\ + CmdQueLen--; + +#define SiSSetupStyleLow(ls) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, LINE_STYLE_0, ls);\ + CmdQueLen--; + +#define SiSSetupStyleHigh(ls) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, LINE_STYLE_1, ls);\ + CmdQueLen--; + +/* Trapezoid */ +#define SiSSetupYH(y,h) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, TRAP_YH, (y)<<16 | (h) );\ + CmdQueLen --; + +#define SiSSetupLR(left,right) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, TRAP_LR, (right)<<16 | (left) );\ + CmdQueLen --; + +#define SiSSetupdL(dxL,dyL) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, TRAP_DL, (dyL)<<16 | (dxL) );\ + CmdQueLen --; + +#define SiSSetupdR(dxR,dyR) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, TRAP_DR, (dyR)<<16 | (dxR) );\ + CmdQueLen --; + +#define SiSSetupEL(eL) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, TRAP_EL, eL);\ + CmdQueLen --; + +#define SiSSetupER(eR) \ + if (CmdQueLen <= 0) SiSIdle;\ + MMIO_OUT32(pSiS->IOBase, TRAP_ER, eR);\ + CmdQueLen --; + + diff --git a/src/sis6326_video.c b/src/sis6326_video.c new file mode 100644 index 0000000..f474755 --- /dev/null +++ b/src/sis6326_video.c @@ -0,0 +1,1662 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis6326_video.c,v 1.2 2003/01/29 15:42:16 eich Exp $ */ +/* + * Xv driver for SiS 5597/5598, 6236 and 530/620. + * + * Copyright 2002 by Thomas Winischhofer, Vienna, Austria. + * + * Based on sis_video.c which is + * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. + * Parts Copyright 2002 by Thomas Winischhofer, Vienna, Austria. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: + * Thomas Winischhofer <thomas@winischhofer.net> + */ + +#include "sis.h" +#ifdef USE6326VIDEO + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "compiler.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "xf86fbman.h" +#include "regionstr.h" + +#include "xf86xv.h" +#include "Xv.h" +#include "xaa.h" +#include "xaalocal.h" +#include "dixstruct.h" +#include "fourcc.h" + +#include "sis_regs.h" + +#define OFF_DELAY 200 /* milliseconds */ +#define FREE_DELAY 60000 + +#define OFF_TIMER 0x01 +#define FREE_TIMER 0x02 +#define CLIENT_VIDEO_ON 0x04 + +#define TIMER_MASK (OFF_TIMER | FREE_TIMER) + +#define WATCHDOG_DELAY 500000 /* Watchdog counter for Vertical Restrace waiting */ + +static XF86VideoAdaptorPtr SIS6326SetupImageVideo(ScreenPtr); +static void SIS6326StopVideo(ScrnInfoPtr, pointer, Bool); +static int SIS6326SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); +static int SIS6326GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); +static void SIS6326QueryBestSize(ScrnInfoPtr, Bool, short, short, short, + short, unsigned int *,unsigned int *, pointer); +static int SIS6326PutImage( ScrnInfoPtr, + short, short, short, short, short, short, short, short, + int, unsigned char*, short, short, Bool, RegionPtr, pointer); +static int SIS6326QueryImageAttributes(ScrnInfoPtr, + int, unsigned short *, unsigned short *, int *, int *); +static void SIS6326VideoTimerCallback(ScrnInfoPtr pScrn, Time now); +static void SIS6326InitOffscreenImages(ScreenPtr pScrn); + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static Atom xvBrightness, xvContrast, xvColorKey; +static Atom xvAutopaintColorKey, xvSetDefaults; + +#define IMAGE_MIN_WIDTH 32 /* Minimum and maximum image sizes */ +#define IMAGE_MIN_HEIGHT 24 +#define IMAGE_MAX_WIDTH 720 /* Are these correct for the chips ? */ +#define IMAGE_MAX_HEIGHT 576 +#define IMAGE_MAX_WIDTH_5597 384 +#define IMAGE_MAX_HEIGHT_5597 288 + +#if 0 +static int oldH, oldW; +#endif + +/**************************************************************************** + * Raw register access : These routines directly interact with the sis's + * control aperature. Must not be called until after + * the board's pci memory has been mapped. + ****************************************************************************/ + +#if 0 +static CARD32 _sisread(SISPtr pSiS, CARD32 reg) +{ + return *(pSiS->IOBase + reg); +} + +static void _siswrite(SISPtr pSiS, CARD32 reg, CARD32 data) +{ + *(pSiS->IOBase + reg) = data; +} +#endif + +static CARD8 getvideoreg(SISPtr pSiS, CARD8 reg) +{ + CARD8 ret; + inSISIDXREG(SISCR, reg, ret); + return(ret); +} + +static void setvideoreg(SISPtr pSiS, CARD8 reg, CARD8 data) +{ + outSISIDXREG(SISCR, reg, data); +} + +static void setvideoregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask) +{ + CARD8 old; + + inSISIDXREG(SISCR, reg, old); + data = (data & mask) | (old & (~mask)); + outSISIDXREG(SISCR, reg, data); +} + +/* VBlank */ +static CARD8 vblank_active_CRT1(SISPtr pSiS) +{ + return (inSISREG(SISINPSTAT) & 0x08); +} + +/* Scanline - unused */ +#if 0 +static CARD32 get_scanline_CRT1(SISPtr pSiS) +{ + CARD8 temp; + + temp = getvideoreg(pSiS, 0x20); + temp = getvideoreg(pSiS, 0x1b); + return((getvideoreg(pSiS, 0x1d) << 8) | getvideoreg(pSiS, 0x1c)); +} +#endif + +void SIS6326InitVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; + XF86VideoAdaptorPtr newAdaptor = NULL; + int num_adaptors; + + newAdaptor = SIS6326SetupImageVideo(pScreen); + if(newAdaptor) + SIS6326InitOffscreenImages(pScreen); + + num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); + + if(newAdaptor) { + if(!num_adaptors) { + num_adaptors = 1; + adaptors = &newAdaptor; + } else { + /* need to free this someplace */ + newAdaptors = xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); + if(newAdaptors) { + memcpy(newAdaptors, adaptors, num_adaptors * + sizeof(XF86VideoAdaptorPtr)); + newAdaptors[num_adaptors] = newAdaptor; + adaptors = newAdaptors; + num_adaptors++; + } + } + } + + if(num_adaptors) + xf86XVScreenInit(pScreen, adaptors, num_adaptors); + + if(newAdaptors) + xfree(newAdaptors); +#if 0 + oldW = 0; oldH = 0; /* DEBUG */ +#endif +} + +/* client libraries expect an encoding */ +static XF86VideoEncodingRec DummyEncoding = +{ + 0, + "XV_IMAGE", + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + {1, 1} +}; + +static XF86VideoEncodingRec DummyEncoding5597 = +{ + 0, + "XV_IMAGE", + IMAGE_MAX_WIDTH_5597, IMAGE_MAX_HEIGHT_5597, + {1, 1} +}; + +#define NUM_FORMATS 4 + +static XF86VideoFormatRec SIS6326Formats[NUM_FORMATS] = +{ + { 8, PseudoColor}, + {15, TrueColor}, + {16, TrueColor}, + {24, TrueColor} +}; + +#define NUM_ATTRIBUTES 5 + +static XF86AttributeRec SIS6326Attributes[NUM_ATTRIBUTES] = +{ + {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, + {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, 0, 7, "XV_CONTRAST"}, + {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, + {XvSettable , 0, 0, "XV_SET_DEFAULTS"} +}; + +#define NUM_IMAGES 6 +#define NUM_IMAGES_NOYV12 4 +#define PIXEL_FMT_YV12 FOURCC_YV12 /* 0x32315659 */ +#define PIXEL_FMT_UYVY FOURCC_UYVY /* 0x59565955 */ +#define PIXEL_FMT_YUY2 FOURCC_YUY2 /* 0x32595559 */ +#define PIXEL_FMT_I420 FOURCC_I420 /* 0x30323449 */ +#define PIXEL_FMT_RGB5 0x35315652 +#define PIXEL_FMT_RGB6 0x36315652 + +static XF86ImageRec SIS6326Images[NUM_IMAGES] = +{ + XVIMAGE_YUY2, /* TW: If order is changed, SIS6326OffscreenImages must be adapted */ + XVIMAGE_UYVY, + XVIMAGE_YV12, + XVIMAGE_I420, + { + 0x35315652, + XvRGB, + LSBFirst, + {'R','V','1','5', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, +/* 15, 0x001F, 0x03E0, 0x7C00, - incorrect! */ + 15, 0x7C00, 0x03E0, 0x001F, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R', 'V', 'B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + }, + { + 0x36315652, + XvRGB, + LSBFirst, + {'R','V','1','6', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, +/* 16, 0x001F, 0x07E0, 0xF800, - incorrect! */ + 16, 0xF800, 0x07E0, 0x001F, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R', 'V', 'B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + } +}; + +static XF86ImageRec SIS6326ImagesNoYV12[NUM_IMAGES_NOYV12] = +{ + XVIMAGE_YUY2, /* TW: If order is changed, SIS6326OffscreenImages must be adapted */ + XVIMAGE_UYVY, + { + 0x35315652, + XvRGB, + LSBFirst, + {'R','V','1','5', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, +/* 15, 0x001F, 0x03E0, 0x7C00, */ + 15, 0x7C00, 0x03E0, 0x001F, /* TW: Should be more correct than the other... */ + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R', 'V', 'B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + }, + { + 0x36315652, + XvRGB, + LSBFirst, + {'R','V','1','6', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, +/* 16, 0x001F, 0x07E0, 0xF800, */ + 16, 0xF800, 0x07E0, 0x001F, /* TW: Should be more correct than the other... */ + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R', 'V', 'B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + } +}; + +typedef struct { + int pixelFormat; + + CARD16 pitch; + + CARD8 keyOP; + + CARD8 HUSF; + CARD8 VUSF; + CARD8 HIntBit; + CARD8 wHPre; + CARD8 PitchMult; + + CARD16 srcW; + CARD16 srcH; + + BoxRec dstBox; + + CARD32 PSY; + CARD32 PSV; + CARD32 PSU; + CARD8 YUVEnd; + + CARD8 lineBufSize; + + CARD8 (*VBlankActiveFunc)(SISPtr); +/* CARD32 (*GetScanLineFunc)(SISPtr pSiS); */ + +} SISOverlayRec, *SISOverlayPtr; + +typedef struct { + FBLinearPtr linear; /* TW: We now use Linear, not Area */ + CARD32 bufAddr[2]; + + unsigned char currentBuf; + + short drw_x, drw_y, drw_w, drw_h; + short src_x, src_y, src_w, src_h; + int id; + short srcPitch, height, width; + CARD32 totalSize; + + char brightness; + unsigned char contrast; + + RegionRec clip; + CARD32 colorKey; + Bool autopaintColorKey; + + CARD32 videoStatus; + Time offTime; + Time freeTime; + + short oldx1, oldx2, oldy1, oldy2; + int mustwait; + + Bool grabbedByV4L; /* V4L stuff */ + int pitch; + int offset; + +} SISPortPrivRec, *SISPortPrivPtr; + +#define GET_PORT_PRIVATE(pScrn) \ + (SISPortPrivPtr)((SISPTR(pScrn))->adaptor->pPortPrivates[0].ptr) + +static void +SIS6326SetPortDefaults (ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) +{ + pPriv->colorKey = 0x000101fe; + pPriv->videoStatus = 0; + pPriv->brightness = 0; + pPriv->contrast = 4; + pPriv->autopaintColorKey = TRUE; +} + +static void +SIS6326ResetVideo(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + + /* Unlock registers */ +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + if(getvideoreg (pSiS, Index_VI6326_Passwd) != 0xa1) { + setvideoreg (pSiS, Index_VI6326_Passwd, 0x86); + if(getvideoreg (pSiS, Index_VI6326_Passwd) != 0xa1) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Xv: Video password could not unlock video registers\n"); + } + + /* Initialize the overlay ----------------------------------- */ + + switch(pSiS->Chipset) { + case PCI_CHIP_SIS6326: + /* Disable overlay (D[1]) & capture (D[0]) */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x03); + + /* What do these do? (Datasheet names these bits "reserved") */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x18); + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x0c); + + /* Select YUV format (D[6]) and "gfx + video" mode (D[4]), odd polarity? (D[7]) */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x40, 0xD0); + /* No interrupt, no filter, disable dithering */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc1, 0x00, 0x7A); + /* Disable VMI (D[4:3]), Brooktree support (D[6]) and system memory framebuffer (D[7]) */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc3, 0x00, 0xF8); + /* Disable video decimation */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc6, 0x00, 0x80); + break; + case PCI_CHIP_SIS5597: + /* Disable overlay (D[1]) & capture (D[0]) */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x03); + + /* What do these do? (Datasheet names these bits "reserved") */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x18); + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x0c); + + /* Select YUV format (D[6]) and "gfx + video" mode (D[4]), odd polarity? (D[7]) */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x40, 0xD0); + /* No interrupt, no filter, disable dithering */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc1, 0x00, 0x7A); + /* Disable Brooktree support (D[6]) and system memory framebuffer (D[7]) */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc3, 0x00, 0xC0); + /* Disable video decimation (has a really strange effect if enabled) */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc6, 0x00, 0x80); + break; + case PCI_CHIP_SIS530: + /* What is this? (Bit is "reserved") */ + setvideoregmask (pSiS, Index_VI6326_Control_Misc4, 0x40, 0x40); + /* Disable overlay (D[1]) */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x02); + + /* What do these do? (Datasheet names these bits "reserved") */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x18); + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x0c); + + /* Select YUV format (D[6]) and "gfx + video" mode (D[4]) */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x40, 0x50); + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Internal error: SiS6326ResetVideo() called with invalid chipset (%x)\n", + pSiS->Chipset); + return; + } + + /* Clear format selection */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc1, 0x00, 0x04); + setvideoregmask(pSiS, Index_VI6326_Control_Misc4, 0x00, 0x07); + + /* Select RGB Chromakey format (D[2]=0), CCIR 601 UV data format (D[1]=0) */ + /* D[1]: 1 = 2's complement, 0 = CCIR 601 format */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc3, 0x00, 0x06); + + /* Reset contrast control */ + setvideoregmask(pSiS, Index_VI6326_Contrast_Enh_Ctrl, 0x04, 0x1F); + + /* Set treshold */ + if(pSiS->oldChipset < OC_SIS6326) { + CARD8 temp; + inSISIDXREG(SISSR, 0x33, temp); /* Synchronous DRAM Timing? */ + if(temp & 0x01) temp = 0x50; + else temp = 0; + setvideoreg(pSiS, Index_VI6326_Play_Threshold_Low, temp); + setvideoreg(pSiS, Index_VI6326_Play_Threshold_High, temp); + } else { + CARD8 temp; + setvideoreg(pSiS, Index_VI6326_Play_Threshold_Low, 0x00); + setvideoreg(pSiS, Index_VI6326_Play_Threshold_High, 0x00); + inSISIDXREG(SISSR, 0x33, temp); /* Are we using SGRAM Timing? */ + if(temp & 0x01) temp = 0x10; + else temp = 0; + setvideoregmask(pSiS, Index_VI6326_Control_Misc4, temp, 0x10); + } + + /* set default properties for overlay ------------------------------- */ + + setvideoregmask (pSiS, Index_VI6326_Contrast_Enh_Ctrl, 0x04, 0x07); + setvideoreg (pSiS, Index_VI6326_Brightness, 0x20); + + if(pSiS->oldChipset < OC_SIS6205A || pSiS->oldChipset > OC_SIS82204) { + setvideoregmask(pSiS, Index_VI6326_AlphaGraph, 0x00, 0xF8); + setvideoregmask(pSiS, Index_VI6326_AlphaVideo, 0xF8, 0xF8); + } else { + setvideoregmask(pSiS, Index_VI6326_AlphaGraph, 0x00, 0xE1); + setvideoregmask(pSiS, Index_VI6326_AlphaVideo, 0xE1, 0xE1); + } +} + +static XF86VideoAdaptorPtr +SIS6326SetupImageVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + XF86VideoAdaptorPtr adapt; + SISPortPrivPtr pPriv; + + if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + + sizeof(SISPortPrivRec) + + sizeof(DevUnion)))) + return NULL; + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->name = "SIS 5597/5598/6326/530/620 Video Overlay"; + adapt->nEncodings = 1; + if(pSiS->oldChipset < OC_SIS6326) { + adapt->pEncodings = &DummyEncoding5597; + } else { + adapt->pEncodings = &DummyEncoding; + } + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = SIS6326Formats; + adapt->nPorts = 1; + adapt->pPortPrivates = (DevUnion*)(&adapt[1]); + + pPriv = (SISPortPrivPtr)(&adapt->pPortPrivates[1]); + + adapt->pPortPrivates[0].ptr = (pointer)(pPriv); + adapt->pAttributes = SIS6326Attributes; + adapt->nAttributes = NUM_ATTRIBUTES; + if(pSiS->NoYV12 == 1) { + adapt->nImages = NUM_IMAGES_NOYV12; + adapt->pImages = SIS6326ImagesNoYV12; + } else { + adapt->nImages = NUM_IMAGES; + adapt->pImages = SIS6326Images; + } + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = SIS6326StopVideo; + adapt->SetPortAttribute = SIS6326SetPortAttribute; + adapt->GetPortAttribute = SIS6326GetPortAttribute; + adapt->QueryBestSize = SIS6326QueryBestSize; + adapt->PutImage = SIS6326PutImage; + adapt->QueryImageAttributes = SIS6326QueryImageAttributes; + + pPriv->videoStatus = 0; + pPriv->currentBuf = 0; + pPriv->linear = NULL; + pPriv->grabbedByV4L= FALSE; + + SIS6326SetPortDefaults(pScrn, pPriv); + + /* gotta uninit this someplace */ + REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); + + pSiS->adaptor = adapt; + + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + xvColorKey = MAKE_ATOM("XV_COLORKEY"); + xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); + xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); + + SIS6326ResetVideo(pScrn); + + return adapt; +} + +static Bool +RegionsEqual(RegionPtr A, RegionPtr B) +{ + int *dataA, *dataB; + int num; + + num = REGION_NUM_RECTS(A); + if(num != REGION_NUM_RECTS(B)) + return FALSE; + + if((A->extents.x1 != B->extents.x1) || + (A->extents.x2 != B->extents.x2) || + (A->extents.y1 != B->extents.y1) || + (A->extents.y2 != B->extents.y2)) + return FALSE; + + dataA = (int*)REGION_RECTS(A); + dataB = (int*)REGION_RECTS(B); + + while(num--) { + if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) + return FALSE; + dataA += 2; + dataB += 2; + } + + return TRUE; +} + +static int +SIS6326SetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 value, pointer data) +{ + SISPortPrivPtr pPriv = (SISPortPrivPtr)data; + + if(attribute == xvBrightness) { + if((value < -128) || (value > 127)) + return BadValue; + pPriv->brightness = value; + } else if(attribute == xvContrast) { + if((value < 0) || (value > 7)) + return BadValue; + pPriv->contrast = value; + } else if(attribute == xvColorKey) { + pPriv->colorKey = value; + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + } else if (attribute == xvAutopaintColorKey) { + if ((value < 0) || (value > 1)) + return BadValue; + pPriv->autopaintColorKey = value; + } else if (attribute == xvSetDefaults) { + SIS6326SetPortDefaults(pScrn, pPriv); + } else return BadMatch; + return Success; +} + +static int +SIS6326GetPortAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value, + pointer data +){ + SISPortPrivPtr pPriv = (SISPortPrivPtr)data; + + if(attribute == xvBrightness) { + *value = pPriv->brightness; + } else if(attribute == xvContrast) { + *value = pPriv->contrast; + } else if(attribute == xvColorKey) { + *value = pPriv->colorKey; + } else if (attribute == xvAutopaintColorKey) + *value = (pPriv->autopaintColorKey) ? 1 : 0; + else return BadMatch; + return Success; +} + +static void +SIS6326QueryBestSize( + ScrnInfoPtr pScrn, + Bool motion, + short vid_w, short vid_h, + short drw_w, short drw_h, + unsigned int *p_w, unsigned int *p_h, + pointer data +){ + *p_w = drw_w; + *p_h = drw_h; + + /* TODO: report the HW limitation */ +} + +static void /* V 530/6326 */ +calc_scale_factor(SISPtr pSiS, SISOverlayPtr pOverlay, ScrnInfoPtr pScrn, + SISPortPrivPtr pPriv) +{ + CARD32 temp=0; + + int dstW = pOverlay->dstBox.x2 - pOverlay->dstBox.x1; + int dstH = pOverlay->dstBox.y2 - pOverlay->dstBox.y1; + int srcW = pOverlay->srcW; + int srcH = pOverlay->srcH; + +#if 0 + /* DEBUG */ + if((oldH != dstH) || (oldW != dstW)){ + xf86DrvMsg(0, X_INFO, "Video size %dx%d\n", dstW, dstH); + oldH = dstH; oldW = dstW; + } + /* /DEBUG */ +#endif + + /* TW: For double scan modes, we need to double the height */ + if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) { + dstH <<= 1; + } + /* TW: For interlace modes, we need to half the height */ + if(pSiS->CurrentLayout.mode->Flags & V_INTERLACE) { + dstH >>= 1; + } + + /* Horizontal */ + if(dstW < IMAGE_MIN_WIDTH) dstW = IMAGE_MIN_WIDTH; + if(dstW == srcW) { + pOverlay->HUSF = 0x00; + pOverlay->HIntBit = 0x01; + } else if(dstW > srcW) { + pOverlay->HIntBit = 0x00; + temp = srcW * 64 / (dstW + 1); + if(temp > 63) temp = 63; + pOverlay->HUSF = temp; + } else { + /* TW: 6326 can't scale below factor .440 - to check with 530/620 */ + if(((dstW * 1000) / srcW) < 440) dstW = ((srcW * 440) / 1000) + 1; + temp = srcW / dstW; + if(temp > 15) temp = 15; + pOverlay->HIntBit = temp; + temp = srcW * 64 / dstW; + pOverlay->HUSF = temp - (pOverlay->HIntBit * 64); + } + + /* Vertical */ + if(dstH < IMAGE_MIN_HEIGHT) dstH = IMAGE_MIN_HEIGHT; + if(dstH == srcH) { + pOverlay->VUSF = 0x00; + pOverlay->PitchMult = 1; + } else if(dstH > srcH) { + temp = srcH * 64 / (dstH + 1); + if (temp > 63) temp = 63; + pOverlay->VUSF = temp; + pOverlay->PitchMult = 1; + } else { + /* TW: 6326 can't scale below factor .440 - to check with 530/620 */ + if(((dstH * 1000) / srcH) < 440) dstH = ((srcH * 440) / 1000) + 1; + temp = srcH / dstH; + if(srcH % dstH) { + temp++; + pOverlay->VUSF = (srcH * 64) / (temp * dstH); + } else { + pOverlay->VUSF = 0x00; + } + pOverlay->PitchMult = temp; + } +} + +static void /* V 530/6326 */ +calc_line_buf_size(SISOverlayPtr pOverlay) +{ + CARD32 I; + CARD32 line = pOverlay->srcW; + + if( (pOverlay->pixelFormat == PIXEL_FMT_YV12) || + (pOverlay->pixelFormat == PIXEL_FMT_I420) ) + { + I = (line >> 5) + (((line >> 6) * 2)) + 3; + I <<= 5; + } else { /* YUV2, UYVY, RGB */ + I = line << 1; + if(I & 7) I += 8; + } + I += 8; + I >>= 3; + pOverlay->lineBufSize = (CARD8)I; +} + +static void /* V 530/6326 */ +merge_line_buf(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable) +{ + if(enable) { + setvideoregmask(pSiS, Index_VI6326_Control_Misc5, 0x10, 0x10); + } else { + setvideoregmask(pSiS, Index_VI6326_Control_Misc5, 0x00, 0x10); + } +} + +static void /* V 530/6326 */ +set_format(SISPtr pSiS, SISOverlayPtr pOverlay) +{ + CARD8 fmt, misc0, misc1, misc4; + + switch (pOverlay->pixelFormat){ + case PIXEL_FMT_YV12: + case PIXEL_FMT_I420: /* V/530 V/6326 */ + fmt = 0x80; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */ + misc0 = 0x40; /* D[6]: 1 = YUV, 0 = RGB */ + misc4 = 0x05; /* D[1:0] 00 RGB 555, 01 YUV 422, 10 RGB 565; D[2] 1 = YUV420 mode */ + misc1 = 0xff; + break; + case PIXEL_FMT_UYVY: + fmt = 0x00; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */ + misc0 = 0x40; /* D[6]: 1 = YUV, 0 = RGB */ + misc4 = 0x00; /* D[1:0] 00 RGB 555, 01 YUV 422, 10 RGB 565; D[2] 1 = YUV420 mode */ + misc1 = 0xff; + break; + case PIXEL_FMT_YUY2: /* V/530 V/6326 */ + fmt = 0x80; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */ + misc0 = 0x40; /* D[6]: 1 = YUV, 0 = RGB */ + misc4 = 0x00; /* D[1:0] 00 RGB 555, 01 YUV 422, 10 RGB 565; D[2] 1 = YUV420 mode */ + misc1 = 0xff; + break; + case PIXEL_FMT_RGB6: /* V/530 V/6326 */ + fmt = 0x40; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */ + misc0 = 0x00; /* D[6]: 1 = YUV, 0 = RGB */ + misc4 = 0xff; + misc1 = 0x00; /* D[2] = Capture format selection (DS5597) - WDR sets this */ + break; + case PIXEL_FMT_RGB5: /* V/530 V/6326 */ + default: + fmt = 0x00; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */ + misc0 = 0x00; /* D[6]: 1 = YUV, 0 = RGB */ + misc4 = 0xff; + misc1 = 0x04; /* D[2] = Capture format selection (DS5597) - WDR sets this */ + break; + } + + setvideoregmask(pSiS, Index_VI6326_VideoFormatSelect, fmt, 0xC0); + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, misc0, 0x40); + if(misc4 == 0xff) { + setvideoregmask(pSiS, Index_VI6326_Control_Misc1, misc1, 0x04); + if(pSiS->oldChipset >= OC_SIS5597) { + setvideoregmask(pSiS, Index_VI6326_Control_Misc4, 0x00, 0x05); + } + } else { + if(pSiS->oldChipset >= OC_SIS5597) { + setvideoregmask(pSiS, Index_VI6326_Control_Misc4, misc4, 0x05); + } + setvideoregmask(pSiS, Index_VI6326_Control_Misc1, 0x00, 0x04); + } +} + +static void /* V 6326/530 */ +set_colorkey(SISPtr pSiS, CARD32 colorkey) +{ + CARD8 r, g, b, s; + + b = (CARD8)(colorkey & 0xFF); + g = (CARD8)((colorkey>>8) & 0xFF); + r = (CARD8)((colorkey>>16) & 0xFF); + + if(pSiS->CurrentLayout.bitsPerPixel >= 24) { + s = b; + b = r; + r = s; + } + + setvideoreg(pSiS, Index_VI6326_Overlay_ColorKey_Blue_Min ,(CARD8)b); + setvideoreg(pSiS, Index_VI6326_Overlay_ColorKey_Green_Min ,(CARD8)g); + setvideoreg(pSiS, Index_VI6326_Overlay_ColorKey_Red_Min ,(CARD8)r); + + setvideoreg(pSiS, Index_VI6326_Overlay_ColorKey_Blue_Max ,(CARD8)b); + setvideoreg(pSiS, Index_VI6326_Overlay_ColorKey_Green_Max ,(CARD8)g); + setvideoreg(pSiS, Index_VI6326_Overlay_ColorKey_Red_Max ,(CARD8)r); +} + +static void +set_brightness(SISPtr pSiS, CARD8 brightness) +{ + setvideoreg(pSiS, Index_VI6326_Brightness, brightness); +} + +static void +set_contrast(SISPtr pSiS, CARD8 contrast) +{ + setvideoregmask(pSiS, Index_VI6326_Contrast_Enh_Ctrl, contrast, 0x07); +} + +static void +set_contrast_data(SISPtr pSiS, int value) +{ + unsigned long temp; + + if(value < 10000) temp = 0; + else temp = (value - 10000) / 20000; + if(temp > 3) temp = 3; + setvideoregmask(pSiS, Index_VI6326_Contrast_Enh_Ctrl, (temp << 6), 0xC0); + switch(temp) { + case 0: temp = 2048; break; + case 1: temp = 4096; break; + case 2: temp = 8192; break; + case 3: temp = 16384; break; + } + temp <<= 10; + temp /= value; + setvideoreg(pSiS, Index_VI6326_Contrast_Factor, temp); +} + +static void +set_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index) +{ + ScrnInfoPtr pScrn = pSiS->pScrn; + + CARD16 pitch=0; + CARD8 h_over=0, v_over=0; + CARD16 top, bottom, left, right; + CARD16 screenX = pSiS->CurrentLayout.mode->HDisplay; + CARD16 screenY = pSiS->CurrentLayout.mode->VDisplay; + CARD32 watchdog; + + top = pOverlay->dstBox.y1; + bottom = pOverlay->dstBox.y2; + if(bottom > screenY) { + bottom = screenY; + } + + left = pOverlay->dstBox.x1; + right = pOverlay->dstBox.x2; + if(right > screenX) { + right = screenX; + } + + /* TW: DoubleScan modes require Y coordinates * 2 */ + if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) { + top <<= 1; + bottom <<= 1; + } + /* TW: Interlace modes require Y coordinates / 2 */ + if(pSiS->CurrentLayout.mode->Flags & V_INTERLACE) { + top >>= 1; + bottom >>= 1; + } + + h_over = (((left>>8) & 0x07) | ((right>>4) & 0x70)); + v_over = (((top>>8) & 0x07) | ((bottom>>4) & 0x70)); + + pitch = pOverlay->pitch * pOverlay->PitchMult; + pitch >>= 2; /* Datasheet: Unit = double word - verified */ + if(pitch > 0xfff) { + pitch = pOverlay->pitch * (0xFFF * 2 / pOverlay->pitch); + pOverlay->VUSF = 0x3F; + } + + /* set color key */ + set_colorkey(pSiS, pPriv->colorKey); + + /* set color key mode */ + setvideoregmask(pSiS, Index_VI6326_Key_Overlay_OP, pOverlay->keyOP, 0x0f); + + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x0c); + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x18); + + /* Set Y buf pitch */ /* Datasheet: Unit = double word - verified */ + setvideoreg(pSiS, Index_VI6326_Disp_Y_Buf_Pitch_Low, (CARD8)(pitch)); + setvideoregmask(pSiS, Index_VI6326_Disp_Y_Buf_Pitch_High, (CARD8)(pitch>>8), 0x0f); + /* Set U/V pitch if using planar formats */ + if( (pOverlay->pixelFormat == PIXEL_FMT_YV12) || + (pOverlay->pixelFormat == PIXEL_FMT_I420) ) { + /* Set U/V pitch */ /* Datasheet: Unit = double word - verified */ + setvideoreg(pSiS, Index_VI6326_Disp_UV_Buf_Pitch_Low, (CARD8)pitch >> 1); + setvideoregmask(pSiS, Index_VI6326_Disp_UV_Buf_Pitch_High, (CARD8)(pitch >> 9), 0x0f); + } + + /* set line buffer size */ + setvideoreg(pSiS, Index_VI6326_Line_Buffer_Size, pOverlay->lineBufSize); + + /* set scale factor */ + setvideoreg(pSiS, Index_VI6326_Hor_Scale, (CARD8)((pOverlay->HUSF) | 0xC0)); + setvideoregmask(pSiS, Index_VI6326_Hor_Scale_Integer, (CARD8)(pOverlay->HIntBit), 0x0F); + setvideoregmask(pSiS, Index_VI6326_Ver_Scale, (CARD8)(pOverlay->VUSF), 0x3F); + + /* TW: We don't have to wait for vertical retrace in all cases */ + if(pPriv->mustwait) { + watchdog = WATCHDOG_DELAY; + while ((!pOverlay->VBlankActiveFunc(pSiS)) && --watchdog); + if(!watchdog) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Xv: Waiting for vertical retrace timed-out\n"); + } + + /* set destination window position */ + setvideoreg(pSiS, Index_VI6326_Win_Hor_Disp_Start_Low, (CARD8)left); + setvideoreg(pSiS, Index_VI6326_Win_Hor_Disp_End_Low, (CARD8)right); + setvideoreg(pSiS, Index_VI6326_Win_Hor_Over, (CARD8)h_over); + + setvideoreg(pSiS, Index_VI6326_Win_Ver_Disp_Start_Low, (CARD8)top); + setvideoreg(pSiS, Index_VI6326_Win_Ver_Disp_End_Low, (CARD8)bottom); + setvideoreg(pSiS, Index_VI6326_Win_Ver_Over, (CARD8)v_over); + + /* Set Y start address */ + setvideoreg (pSiS, Index_VI6326_Disp_Y_Buf_Start_Low, (CARD8)(pOverlay->PSY)); + setvideoreg (pSiS, Index_VI6326_Disp_Y_Buf_Start_Middle, (CARD8)((pOverlay->PSY)>>8)); + if(pSiS->oldChipset <= OC_SIS6326) { /* all old chipsets incl 6326 */ + /* Set overflow bits */ + setvideoregmask (pSiS, Index_VI6326_Disp_Capt_Y_Buf_Start_High, + (CARD8)(((pOverlay->PSY)>>12) & 0xF0), 0xF0); + /* Set framebuffer end address */ + setvideoreg (pSiS, Index_VI6326_Disp_Y_End, (CARD8)(pOverlay->YUVEnd)); + } else { /* 530/620 */ + /* Set overflow bits */ + setvideoregmask (pSiS, Index_VI6326_Disp_Capt_Y_Buf_Start_High, + (CARD8)(((pOverlay->PSY)>>13) & 0xF8), 0xF8); + } + + /* Set U/V start addresses if using plane formats */ + if( (pOverlay->pixelFormat == PIXEL_FMT_YV12) || + (pOverlay->pixelFormat == PIXEL_FMT_I420) ) { + + CARD32 PSU = pOverlay->PSU; + CARD32 PSV = pOverlay->PSV; + + /* set U/V start address */ + setvideoreg (pSiS, Index_VI6326_U_Buf_Start_Low, (CARD8)PSU); + setvideoreg (pSiS, Index_VI6326_U_Buf_Start_Middle,(CARD8)(PSU >> 8)); + + setvideoreg (pSiS, Index_VI6326_V_Buf_Start_Low, (CARD8)PSV); + setvideoreg (pSiS, Index_VI6326_V_Buf_Start_Middle,(CARD8)(PSV >> 8)); + + setvideoreg (pSiS, Index_VI6326_UV_Buf_Start_High, + (CARD8)(((PSU >> 16) & 0x0F) | ((PSV >> 12) & 0xF0)) ); + + if(pSiS->oldChipset > OC_SIS6326) { + /* Set bit 20 of the addresses in Misc5 (530/620 only) */ + setvideoreg (pSiS, Index_VI6326_Control_Misc5, + (CARD8)(((PSU >> (20-1)) & 0x02) | ((PSV >> (20-2)) & 0x04)) ); + } + } + + /* set brightness and contrast */ + set_brightness(pSiS, pPriv->brightness); + if(pSiS->oldChipset > OC_SIS6205C) { + set_contrast_data(pSiS, (pOverlay->dstBox.x2 - pOverlay->dstBox.x1) * + (pOverlay->dstBox.y2 - pOverlay->dstBox.y1)); + set_contrast(pSiS, pPriv->contrast); + } + + /* set format */ + set_format(pSiS, pOverlay); +} + +/* TW: Overlay MUST NOT be switched off while beam is over it */ +static void +close_overlay(SISPtr pSiS, SISPortPrivPtr pPriv) +{ + CARD32 watchdog; + + watchdog = WATCHDOG_DELAY; + while((!vblank_active_CRT1(pSiS)) && --watchdog); + if(pSiS->oldChipset > OC_SIS6326) { + /* what is this? */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc4, 0x40, 0x40); + } + /* disable overlay */ + setvideoregmask(pSiS, Index_VI6326_Control_Misc0, 0x00, 0x02); +} + +static void +SIS6326DisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) +{ + SISPtr pSiS = SISPTR(pScrn); + + short srcPitch = pPriv->srcPitch; + short height = pPriv->height; + short width = pPriv->width; + SISOverlayRec overlay; + int srcOffsetX=0, srcOffsetY=0; + int sx, sy; + int index = 0; + int pitch; + + memset(&overlay, 0, sizeof(overlay)); + overlay.pixelFormat = pPriv->id; + overlay.pitch = srcPitch; + overlay.keyOP = VI6326_ROP_DestKey; /* DestKey mode */ + + overlay.dstBox.x1 = pPriv->drw_x - pScrn->frameX0; + overlay.dstBox.x2 = pPriv->drw_x + pPriv->drw_w - pScrn->frameX0; + overlay.dstBox.y1 = pPriv->drw_y - pScrn->frameY0; + overlay.dstBox.y2 = pPriv->drw_y + pPriv->drw_h - pScrn->frameY0; + + if((overlay.dstBox.x1 > overlay.dstBox.x2) || + (overlay.dstBox.y1 > overlay.dstBox.y2)) + return; + + if((overlay.dstBox.x2 < 0) || (overlay.dstBox.y2 < 0)) + return; + + if(overlay.dstBox.x1 < 0) { + srcOffsetX = pPriv->src_w * (-overlay.dstBox.x1) / pPriv->drw_w; + overlay.dstBox.x1 = 0; + } + if(overlay.dstBox.y1 < 0) { + srcOffsetY = pPriv->src_h * (-overlay.dstBox.y1) / pPriv->drw_h; + overlay.dstBox.y1 = 0; + } + + switch(pPriv->id){ + case PIXEL_FMT_YV12: + sx = (pPriv->src_x + srcOffsetX) & ~7; + sy = (pPriv->src_y + srcOffsetY) & ~1; + pitch = (width + 3) & ~3; + overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy * pitch; + overlay.PSV = overlay.PSY + pitch * height; + overlay.PSU = overlay.PSV + ((((width >> 1) + 3) & ~3) * (height >> 1)); + overlay.PSY >>= 2; + overlay.PSV >>= 2; + overlay.PSU >>= 2; + break; + case PIXEL_FMT_I420: + sx = (pPriv->src_x + srcOffsetX) & ~7; + sy = (pPriv->src_y + srcOffsetY) & ~1; + pitch = (width + 3) & ~3; + overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy * pitch; + overlay.PSU = overlay.PSY + pitch * height; + overlay.PSV = overlay.PSU + ((((width >> 1) + 3) & ~3) * (height >> 1)); + overlay.PSY >>= 2; + overlay.PSV >>= 2; + overlay.PSU >>= 2; + break; + case PIXEL_FMT_YUY2: + case PIXEL_FMT_UYVY: + case PIXEL_FMT_RGB6: + case PIXEL_FMT_RGB5: + default: + sx = (pPriv->src_x + srcOffsetX) & ~1; + sy = (pPriv->src_y + srcOffsetY); + overlay.PSY = (pPriv->bufAddr[pPriv->currentBuf] + sx*2 + sy*srcPitch); + overlay.PSY >>= 2; + break; + } + + /* FIXME: Is this correct? (Is it required to set the end address? + * Datasheet is not clear) - (reg does not exist on 530/620) + */ + overlay.YUVEnd = (pPriv->bufAddr[pPriv->currentBuf] + pPriv->totalSize) >> 14; + + /* FIXME: is it possible that srcW < 0 */ + overlay.srcW = pPriv->src_w - (sx - pPriv->src_x); + overlay.srcH = pPriv->src_h - (sy - pPriv->src_y); + + if ( (pPriv->oldx1 != overlay.dstBox.x1) || + (pPriv->oldx2 != overlay.dstBox.x2) || + (pPriv->oldy1 != overlay.dstBox.y1) || + (pPriv->oldy2 != overlay.dstBox.y2) ) { + pPriv->mustwait = 1; + pPriv->oldx1 = overlay.dstBox.x1; pPriv->oldx2 = overlay.dstBox.x2; + pPriv->oldy1 = overlay.dstBox.y1; pPriv->oldy2 = overlay.dstBox.y2; + } + + /* calculate line buffer length */ + calc_line_buf_size(&overlay); + + overlay.VBlankActiveFunc = vblank_active_CRT1; +/* overlay.GetScanLineFunc = get_scanline_CRT1; */ + + /* calculate scale factor */ + calc_scale_factor(pSiS, &overlay, pScrn, pPriv); + + /* set (not only determine) if line buffer is to be merged */ + if(pSiS->oldChipset > OC_SIS5597) { + int temp; + if(pSiS->oldChipset <= OC_SIS6326) temp = 352; + else temp = 384; + merge_line_buf(pSiS, pPriv, (overlay.srcW > temp)); + } + + /* set overlay */ + set_overlay(pSiS, &overlay, pPriv, index); + + /* enable overlay */ + if(pSiS->oldChipset > OC_SIS6326) { + setvideoregmask (pSiS, Index_VI6326_Control_Misc4, 0x40, 0x40); + } + setvideoregmask (pSiS, Index_VI6326_Control_Misc0, 0x02, 0x02); + + pPriv->mustwait = 0; +} + +static FBLinearPtr +SIS6326AllocateOverlayMemory( + ScrnInfoPtr pScrn, + FBLinearPtr linear, + int size +){ + ScreenPtr pScreen; + FBLinearPtr new_linear; + + if(linear) { + if(linear->size >= size) + return linear; + + if(xf86ResizeOffscreenLinear(linear, size)) + return linear; + + xf86FreeOffscreenLinear(linear); + } + + pScreen = screenInfo.screens[pScrn->scrnIndex]; + + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32, + NULL, NULL, NULL); + + if(!new_linear) { + int max_size; + + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 32, + PRIORITY_EXTREME); + + if(max_size < size) return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32, + NULL, NULL, NULL); + } + if (!new_linear) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Xv: Failed to allocate %dK of video memory\n", size/1024); + + return new_linear; +} + +static void +SIS6326FreeOverlayMemory(ScrnInfoPtr pScrn) +{ + SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); + + if(pPriv->linear) { + xf86FreeOffscreenLinear(pPriv->linear); + pPriv->linear = NULL; + } +} + +static void +SIS6326StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) +{ + SISPortPrivPtr pPriv = (SISPortPrivPtr)data; + SISPtr pSiS = SISPTR(pScrn); + + if(pPriv->grabbedByV4L) + return; + + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + + if(shutdown) { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + close_overlay(pSiS, pPriv); + pPriv->mustwait = 1; + } + SIS6326FreeOverlayMemory(pScrn); + pPriv->videoStatus = 0; + pSiS->VideoTimerCallback = NULL; + } else { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON; + pPriv->offTime = currentTime.milliseconds + OFF_DELAY; + pSiS->VideoTimerCallback = SIS6326VideoTimerCallback; + } + } +} + +static int +SIS6326PutImage( + ScrnInfoPtr pScrn, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + int id, unsigned char* buf, + short width, short height, + Bool sync, + RegionPtr clipBoxes, pointer data +){ + SISPtr pSiS = SISPTR(pScrn); + SISPortPrivPtr pPriv = (SISPortPrivPtr)data; + + int totalSize=0; + int depth = pSiS->CurrentLayout.bitsPerPixel >> 3; + + if(pPriv->grabbedByV4L) + return Success; + + pPriv->drw_x = drw_x; + pPriv->drw_y = drw_y; + pPriv->drw_w = drw_w; + pPriv->drw_h = drw_h; + pPriv->src_x = src_x; + pPriv->src_y = src_y; + pPriv->src_w = src_w; + pPriv->src_h = src_h; + pPriv->id = id; + pPriv->height = height; + pPriv->width = width; + + /* TW: Pixel formats: + 1. YU12: 3 planes: H V + Y sample period 1 1 (8 bit per pixel) + V sample period 2 2 (8 bit per pixel, subsampled) + U sample period 2 2 (8 bit per pixel, subsampled) + + Y plane is fully sampled (width*height), U and V planes + are sampled in 2x2 blocks, hence a group of 4 pixels requires + 4 + 1 + 1 = 6 bytes. The data is planar, ie in single planes + for Y, U and V. + 2. UYVY: 3 planes: H V + Y sample period 1 1 (8 bit per pixel) + V sample period 2 1 (8 bit per pixel, subsampled) + U sample period 2 1 (8 bit per pixel, subsampled) + Y plane is fully sampled (width*height), U and V planes + are sampled in 2x1 blocks, hence a group of 4 pixels requires + 4 + 2 + 2 = 8 bytes. The data is bit packed, there are no separate + Y, U or V planes. + Bit order: U0 Y0 V0 Y1 U2 Y2 V2 Y3 ... + 3. I420: Like YU12, but planes U and V are in reverse order. + 4. YUY2: Like UYVY, but order is + Y0 U0 Y1 V0 Y2 U2 Y3 V2 ... + */ + + switch(id){ + case PIXEL_FMT_YV12: + case PIXEL_FMT_I420: + pPriv->srcPitch = (width + 7) & ~7; + /* Size = width * height * 3 / 2 */ + totalSize = (pPriv->srcPitch * height * 3) >> 1; + break; + case PIXEL_FMT_YUY2: + case PIXEL_FMT_UYVY: + case PIXEL_FMT_RGB5: + case PIXEL_FMT_RGB6: + default: + pPriv->srcPitch = ((width << 1) + 3) & ~3; + /* Size = width * 2 * height */ + totalSize = pPriv->srcPitch * height; + } + + pPriv->totalSize = totalSize; + + /* allocate memory (we do doublebuffering) */ + if(!(pPriv->linear = SIS6326AllocateOverlayMemory(pScrn, pPriv->linear, + totalSize<<1))) + return BadAlloc; + + /* fixup pointers */ + pPriv->bufAddr[0] = (pPriv->linear->offset * depth); + pPriv->bufAddr[1] = pPriv->bufAddr[0] + totalSize; + + /* copy data */ + memcpy(pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize); + + SIS6326DisplayVideo(pScrn, pPriv); + + /* update cliplist */ + if( pPriv->autopaintColorKey && + (pPriv->grabbedByV4L || !RegionsEqual(&pPriv->clip, clipBoxes))) { + /* We always paint colorkey for V4L */ + if (!pPriv->grabbedByV4L) + REGION_COPY(pScreen, &pPriv->clip, clipBoxes); + /* draw these */ + /* xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); - for X4.2 */ + XAAFillSolidRects(pScrn, pPriv->colorKey, GXcopy, ~0, + REGION_NUM_RECTS(clipBoxes), + REGION_RECTS(clipBoxes)); + } + + pPriv->currentBuf ^= 1; + + pPriv->videoStatus = CLIENT_VIDEO_ON; + + pSiS->VideoTimerCallback = SIS6326VideoTimerCallback; + + return Success; +} + +static int +SIS6326QueryImageAttributes( + ScrnInfoPtr pScrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets +){ + SISPtr pSiS = SISPTR(pScrn); + int pitchY, pitchUV; + int size, sizeY, sizeUV; + + if(*w < IMAGE_MIN_WIDTH) *w = IMAGE_MIN_WIDTH; + if(*h < IMAGE_MIN_HEIGHT) *h = IMAGE_MIN_HEIGHT; + + if(pSiS->oldChipset < OC_SIS6326) { + if(*w > IMAGE_MAX_WIDTH_5597) *w = IMAGE_MAX_WIDTH_5597; + if(*h > IMAGE_MAX_HEIGHT_5597) *h = IMAGE_MAX_HEIGHT_5597; + } else { + if(*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH; + if(*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT; + } + + switch(id) { + case PIXEL_FMT_YV12: + case PIXEL_FMT_I420: + *w = (*w + 7) & ~7; + *h = (*h + 1) & ~1; + pitchY = *w; + pitchUV = *w >> 1; + if(pitches) { + pitches[0] = pitchY; + pitches[1] = pitches[2] = pitchUV; + } + sizeY = pitchY * (*h); + sizeUV = pitchUV * ((*h) >> 1); + if(offsets) { + offsets[0] = 0; + offsets[1] = sizeY; + offsets[2] = sizeY + sizeUV; + } + size = sizeY + (sizeUV << 1); + break; + case PIXEL_FMT_YUY2: + case PIXEL_FMT_UYVY: + case PIXEL_FMT_RGB5: + case PIXEL_FMT_RGB6: + default: + *w = (*w + 1) & ~1; + pitchY = *w << 1; + if(pitches) pitches[0] = pitchY; + if(offsets) offsets[0] = 0; + size = pitchY * (*h); + break; + } + + return size; +} + +static void +SIS6326VideoTimerCallback (ScrnInfoPtr pScrn, Time now) +{ + SISPtr pSiS = SISPTR(pScrn); + SISPortPrivPtr pPriv = NULL; + unsigned char sridx, cridx; + + pSiS->VideoTimerCallback = NULL; + + if(!pScrn->vtSema) return; + + if(pSiS->adaptor) { + pPriv = GET_PORT_PRIVATE(pScrn); + if(!pPriv->videoStatus) + pPriv = NULL; + } + + if(pPriv) { + if(pPriv->videoStatus & TIMER_MASK) { + UpdateCurrentTime(); + if(pPriv->offTime < currentTime.milliseconds) { + if(pPriv->videoStatus & OFF_TIMER) { + /* Turn off the overlay */ + sridx = inSISREG(SISSR); cridx = inSISREG(SISCR); + close_overlay(pSiS, pPriv); + outSISREG(SISSR, sridx); outSISREG(SISCR, cridx); + pPriv->mustwait = 1; + pPriv->videoStatus = FREE_TIMER; + pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; + pSiS->VideoTimerCallback = SIS6326VideoTimerCallback; + } else + if(pPriv->videoStatus & FREE_TIMER) { + SIS6326FreeOverlayMemory(pScrn); + pPriv->mustwait = 1; + pPriv->videoStatus = 0; + } + } else + pSiS->VideoTimerCallback = SIS6326VideoTimerCallback; + } + } +} + +/* TW: Offscreen surface stuff for v4l */ + +static int +SIS6326AllocSurface ( + ScrnInfoPtr pScrn, + int id, + unsigned short w, + unsigned short h, + XF86SurfacePtr surface +) +{ + SISPtr pSiS = SISPTR(pScrn); + SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); + int size, depth; + + if((w < IMAGE_MIN_WIDTH) || (h < IMAGE_MIN_HEIGHT)) + return BadValue; + + if(pSiS->oldChipset < OC_SIS6326) { + if((w > IMAGE_MAX_WIDTH_5597) || (h > IMAGE_MAX_HEIGHT_5597)) + return BadValue; + } else { + if((w > IMAGE_MAX_WIDTH) || (h > IMAGE_MAX_HEIGHT)) + return BadValue; + } + + if(pPriv->grabbedByV4L) + return BadAlloc; + + depth = pSiS->CurrentLayout.bitsPerPixel >> 3; + + w = (w + 1) & ~1; + pPriv->pitch = ((w << 1) + 63) & ~63; /* Only packed pixel modes supported */ + size = h * pPriv->pitch; + pPriv->linear = SIS6326AllocateOverlayMemory(pScrn, pPriv->linear, size); + if(!pPriv->linear) + return BadAlloc; + + pPriv->totalSize = size; + + pPriv->offset = pPriv->linear->offset * depth; + + surface->width = w; + surface->height = h; + surface->pScrn = pScrn; + surface->id = id; + surface->pitches = &pPriv->pitch; + surface->offsets = &pPriv->offset; + surface->devPrivate.ptr = (pointer)pPriv; + + close_overlay(pSiS, pPriv); + pPriv->videoStatus = 0; + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + pSiS->VideoTimerCallback = NULL; + pPriv->grabbedByV4L = TRUE; + return Success; +} + +static int +SIS6326StopSurface (XF86SurfacePtr surface) +{ + SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); + SISPtr pSiS = SISPTR(surface->pScrn); + + if(pPriv->grabbedByV4L && pPriv->videoStatus) { + close_overlay(pSiS, pPriv); + pPriv->mustwait = 1; + pPriv->videoStatus = 0; + } + return Success; +} + +static int +SIS6326FreeSurface (XF86SurfacePtr surface) +{ + SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); + + if(pPriv->grabbedByV4L) { + SIS6326StopSurface(surface); + SIS6326FreeOverlayMemory(surface->pScrn); + pPriv->grabbedByV4L = FALSE; + } + return Success; +} + +static int +SIS6326GetSurfaceAttribute ( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value +) +{ + SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); + + return SIS6326GetPortAttribute(pScrn, attribute, value, (pointer)pPriv); +} + +static int +SIS6326SetSurfaceAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 value +) +{ + SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);; + + return SIS6326SetPortAttribute(pScrn, attribute, value, (pointer)pPriv); +} + +static int +SIS6326DisplaySurface ( + XF86SurfacePtr surface, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + RegionPtr clipBoxes +) +{ + ScrnInfoPtr pScrn = surface->pScrn; + SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); + + if(!pPriv->grabbedByV4L) + return Success; + + pPriv->drw_x = drw_x; + pPriv->drw_y = drw_y; + pPriv->drw_w = drw_w; + pPriv->drw_h = drw_h; + pPriv->src_x = src_x; + pPriv->src_y = src_y; + pPriv->src_w = src_w; + pPriv->src_h = src_h; + pPriv->id = surface->id; + pPriv->height = surface->height; + pPriv->bufAddr[0] = surface->offsets[0]; + pPriv->currentBuf = 0; + pPriv->srcPitch = surface->pitches[0]; + + SIS6326DisplayVideo(pScrn, pPriv); + + if(pPriv->autopaintColorKey) { + XAAFillSolidRects(pScrn, pPriv->colorKey, GXcopy, ~0, + REGION_NUM_RECTS(clipBoxes), + REGION_RECTS(clipBoxes)); + } + + pPriv->videoStatus = CLIENT_VIDEO_ON; + + return Success; +} + +XF86OffscreenImageRec SIS6326OffscreenImages[2] = +{ + { + &SIS6326Images[0], /* YUV2 */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SIS6326AllocSurface, + SIS6326FreeSurface, + SIS6326DisplaySurface, + SIS6326StopSurface, + SIS6326GetSurfaceAttribute, + SIS6326SetSurfaceAttribute, + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + NUM_ATTRIBUTES, + &SIS6326Attributes[0] /* Support all attributes */ + }, + { + &SIS6326Images[1], /* UYVY */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SIS6326AllocSurface, + SIS6326FreeSurface, + SIS6326DisplaySurface, + SIS6326StopSurface, + SIS6326GetSurfaceAttribute, + SIS6326SetSurfaceAttribute, + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + NUM_ATTRIBUTES, + &SIS6326Attributes[0] /* Support all attributes */ + }, +}; + +static void +SIS6326InitOffscreenImages(ScreenPtr pScrn) +{ + xf86XVRegisterOffscreenImages(pScrn, SIS6326OffscreenImages, 2); +} +#else +int sis_foo; +#endif + diff --git a/src/sis_accel.c b/src/sis_accel.c new file mode 100644 index 0000000..a9d305f --- /dev/null +++ b/src/sis_accel.c @@ -0,0 +1,651 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_accel.c,v 1.25 2003/01/29 15:42:16 eich Exp $ */ +/* + * Copyright 1998,1999 by Alan Hourihane, Wigan, England. + * Parts Copyright 2002 Thomas Winischhofer, Vienna, Austria. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk + * Mike Chapman <mike@paranoia.com>, + * Juanjo Santamarta <santamarta@ctv.es>, + * Mitani Hiroshi <hmitani@drl.mei.co.jp> + * David Thomas <davtom@dream.org.uk> + * Thomas Winischhofer <thomas@winischhofer.net> + */ + +#if 0 +#define CTSCE /* TW: Include enhanced color expansion code */ +#endif /* This produces drawing errors sometimes */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +#include "xf86PciInfo.h" +#include "xf86Pci.h" + +#include "sis_accel.h" +#include "sis_regs.h" +#include "sis.h" +#include "xaarop.h" + +static void SiSSync(ScrnInfoPtr pScrn); +static void SiSSetupForFillRectSolid(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void SiSSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, + int y, int w, int h); +static void SiSSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, int transparency_color); +static void SiSSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int x1, int y1, int x2, + int y2, int w, int h); +static void SiSSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, + int patternx, int patterny, int fg, int bg, + int rop, unsigned int planemask); +static void SiSSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, + int patternx, int patterny, int x, int y, + int w, int h); +#if 0 +static void SiSSetupForScreenToScreenColorExpandFill (ScrnInfoPtr pScrn, + int fg, int bg, + int rop, unsigned int planemask); +static void SiSSubsequentScreenToScreenColorExpandFill( ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int srcx, int srcy, int offset ); +#endif +static void SiSSetClippingRectangle ( ScrnInfoPtr pScrn, + int left, int top, int right, int bottom); +static void SiSDisableClipping (ScrnInfoPtr pScrn); +static void SiSSetupForSolidLine(ScrnInfoPtr pScrn, + int color, int rop, unsigned int planemask); +static void SiSSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, int flags); +static void SiSSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, + int x, int y, int len, int dir); +#ifdef CTSCE +static void SiSSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); +static void SiSSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft); +static void SiSSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); +#endif + +Bool +SiSAccelInit(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + BoxRec AvailFBArea; + int topFB, i; + int reservedFbSize; + int UsableFbSize; + unsigned char *AvailBufBase; + + pSiS->AccelInfoPtr = infoPtr = XAACreateInfoRec(); + if (!infoPtr) return FALSE; + + infoPtr->Flags = LINEAR_FRAMEBUFFER | + OFFSCREEN_PIXMAPS | + PIXMAP_CACHE; + + /* Sync */ + infoPtr->Sync = SiSSync; + + /* Screen To Screen copy */ + infoPtr->SetupForScreenToScreenCopy = SiSSetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = SiSSubsequentScreenToScreenCopy; + infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY | NO_PLANEMASK; + + /* Solid fill */ + infoPtr->SetupForSolidFill = SiSSetupForFillRectSolid; + infoPtr->SubsequentSolidFillRect = SiSSubsequentFillRectSolid; + infoPtr->SolidFillFlags = NO_PLANEMASK; + + /* On 5597/5598 and 6326, clipping and lines only work + for 1024, 2048, 4096 logical width */ + if(pSiS->ValidWidth) { + /* Clipping */ + infoPtr->SetClippingRectangle = SiSSetClippingRectangle; + infoPtr->DisableClipping = SiSDisableClipping; + infoPtr->ClippingFlags = + HARDWARE_CLIP_SOLID_LINE | + HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY | + HARDWARE_CLIP_MONO_8x8_FILL | + HARDWARE_CLIP_SOLID_FILL ; + + /* Solid Lines */ + infoPtr->SetupForSolidLine = SiSSetupForSolidLine; + infoPtr->SubsequentSolidTwoPointLine = SiSSubsequentSolidTwoPointLine; + infoPtr->SubsequentSolidHorVertLine = SiSSubsequentSolidHorVertLine; + infoPtr->SolidLineFlags = NO_PLANEMASK; + } + + if(pScrn->bitsPerPixel != 24) { + /* 8x8 mono pattern */ + infoPtr->SetupForMono8x8PatternFill = SiSSetupForMono8x8PatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = SiSSubsequentMono8x8PatternFillRect; + infoPtr->Mono8x8PatternFillFlags = + NO_PLANEMASK | + HARDWARE_PATTERN_PROGRAMMED_BITS | + HARDWARE_PATTERN_PROGRAMMED_ORIGIN | + BIT_ORDER_IN_BYTE_MSBFIRST; + } + +#ifdef CTSCE + if(pScrn->bitsPerPixel != 24) { + /* TW: per-scanline color expansion (using indirect method) */ + pSiS->ColorExpandBufferNumber = 4; + pSiS->ColorExpandBufferCountMask = 0x03; + pSiS->PerColorExpandBufferSize = ((pScrn->virtualX + 31) / 32) * 4; + + infoPtr->NumScanlineColorExpandBuffers = pSiS->ColorExpandBufferNumber; + infoPtr->ScanlineColorExpandBuffers = (unsigned char **)&pSiS->ColorExpandBufferAddr[0]; + + infoPtr->SetupForScanlineCPUToScreenColorExpandFill = + SiSSetupForScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = + SiSSubsequentScanlineCPUToScreenColorExpandFill; + infoPtr->SubsequentColorExpandScanline = + SiSSubsequentColorExpandScanline; + infoPtr->ScanlineCPUToScreenColorExpandFillFlags = + NO_PLANEMASK | + CPU_TRANSFER_PAD_DWORD | + SCANLINE_PAD_DWORD | + BIT_ORDER_IN_BYTE_MSBFIRST | + LEFT_EDGE_CLIPPING; + } else { + pSiS->ColorExpandBufferNumber = 0; + } +#else + pSiS->ColorExpandBufferNumber = 0; +#endif + + topFB = pSiS->maxxfbmem; + + reservedFbSize = pSiS->ColorExpandBufferNumber * pSiS->PerColorExpandBufferSize; + + UsableFbSize = topFB - reservedFbSize; + + /* Layout: (Sizes do not reflect correct proportions) + * |--------------++++++++++++++++++++| ====================~~~~~~~~~~~~| + * UsableFbSize ColorExpandBuffers | TurboQueue HWCursor + * topFB + */ + + if(pSiS->ColorExpandBufferNumber) { + AvailBufBase = pSiS->FbBase + UsableFbSize; + for (i = 0; i < pSiS->ColorExpandBufferNumber; i++) { + pSiS->ColorExpandBufferAddr[i] = AvailBufBase + + i * pSiS->PerColorExpandBufferSize; + pSiS->ColorExpandBufferScreenOffset[i] = UsableFbSize + + i * pSiS->PerColorExpandBufferSize; + } + } + AvailFBArea.x1 = 0; + AvailFBArea.y1 = 0; + AvailFBArea.x2 = pScrn->displayWidth; + AvailFBArea.y2 = UsableFbSize / (pScrn->displayWidth * pScrn->bitsPerPixel / 8) - 1; + + if (AvailFBArea.y2 < 0) + AvailFBArea.y2 = 32767; + + if(AvailFBArea.y2 < pScrn->currentMode->VDisplay) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Not enough video RAM for accelerator. At least " + "%dKB needed, %dKB available\n", + ((((pScrn->displayWidth * pScrn->bitsPerPixel/8) /* TW: +8 for make it sure */ + * pScrn->currentMode->VDisplay) + reservedFbSize) / 1024) + 8, + pSiS->maxxfbmem/1024); + pSiS->NoAccel = TRUE; + pSiS->NoXvideo = TRUE; + XAADestroyInfoRec(pSiS->AccelInfoPtr); + pSiS->AccelInfoPtr = NULL; + return FALSE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Frame Buffer From (%d,%d) To (%d,%d)\n", + AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2, AvailFBArea.y2); + + xf86InitFBManager(pScreen, &AvailFBArea); + + return(XAAInit(pScreen, infoPtr)); +} + +/* sync */ +static void +SiSSync(ScrnInfoPtr pScrn) { + SISPtr pSiS = SISPTR(pScrn); + sisBLTSync; +} + +/* Clipping */ +static void SiSSetClippingRectangle ( ScrnInfoPtr pScrn, + int left, int top, int right, int bottom) +{ + SISPtr pSiS = SISPTR(pScrn); + + sisBLTSync; + sisSETCLIPTOP(left,top); + sisSETCLIPBOTTOM(right,bottom); + pSiS->ClipEnabled = TRUE; +} + +static void SiSDisableClipping (ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + pSiS->ClipEnabled = FALSE; +} + +static const int 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 int 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 */ +}; + + +/* Screen to screen copy */ +static void +SiSSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, + int rop, unsigned int planemask, + int transparency_color) +{ + SISPtr pSiS = SISPTR(pScrn); + sisBLTSync; + sisSETPITCH(pSiS->scrnOffset, pSiS->scrnOffset); + + sisSETROP(XAACopyROP[rop]); + pSiS->Xdirection = xdir; + pSiS->Ydirection = ydir; +} + +static void +SiSSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2, + int y2, int w, int h) +{ + SISPtr pSiS = SISPTR(pScrn); + int srcaddr, destaddr; + int op ; + + op = sisCMDBLT | sisSRCVIDEO; + if(pSiS->Ydirection == -1) { + op |= sisBOTTOM2TOP; + srcaddr = (y1 + h - 1) * pSiS->CurrentLayout.displayWidth; + destaddr = (y2 + h - 1) * pSiS->CurrentLayout.displayWidth; + } else { + op |= sisTOP2BOTTOM; + srcaddr = y1 * pSiS->CurrentLayout.displayWidth; + destaddr = y2 * pSiS->CurrentLayout.displayWidth; + } + if(pSiS->Xdirection == -1) { + op |= sisRIGHT2LEFT; + srcaddr += x1 + w - 1; + destaddr += x2 + w - 1; + } else { + op |= sisLEFT2RIGHT; + srcaddr += x1; + destaddr += x2; + } + if (pSiS->ClipEnabled) + op |= sisCLIPINTRN | sisCLIPENABL; + + srcaddr *= (pSiS->CurrentLayout.bitsPerPixel/8); + destaddr *= (pSiS->CurrentLayout.bitsPerPixel/8); + if(((pSiS->CurrentLayout.bitsPerPixel / 8) > 1) && (pSiS->Xdirection == -1)) { + srcaddr += (pSiS->CurrentLayout.bitsPerPixel/8)-1; + destaddr += (pSiS->CurrentLayout.bitsPerPixel/8)-1; + } + + sisBLTSync; + sisSETSRCADDR(srcaddr); + sisSETDSTADDR(destaddr); + sisSETHEIGHTWIDTH(h-1, w * (pSiS->CurrentLayout.bitsPerPixel/8)-1); + sisSETCMD(op); +} + +/* solid fill */ +static void +SiSSetupForFillRectSolid(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask) +{ + SISPtr pSiS = SISPTR(pScrn); + + sisBLTSync; + sisSETBGROPCOL(XAACopyROP[rop], color); + sisSETFGROPCOL(XAACopyROP[rop], color); + sisSETPITCH(pSiS->scrnOffset, pSiS->scrnOffset); +} + +static void +SiSSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, int y, int w, int h) +{ + SISPtr pSiS = SISPTR(pScrn); + int destaddr, op; + + destaddr = y * pSiS->CurrentLayout.displayWidth + x; + + op = sisCMDBLT | sisSRCBG | sisTOP2BOTTOM | sisLEFT2RIGHT; + + if(pSiS->ClipEnabled) + op |= sisCLIPINTRN | sisCLIPENABL; + + destaddr *= (pSiS->CurrentLayout.bitsPerPixel / 8); + + sisBLTSync; + sisSETHEIGHTWIDTH(h-1, w * (pSiS->CurrentLayout.bitsPerPixel/8)-1); + sisSETDSTADDR(destaddr); + sisSETCMD(op); +} + +/* 8x8 mono */ +static void +SiSSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny, + int fg, int bg, int rop, unsigned int planemask) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned int *patternRegPtr; + int i; + + (void)XAAHelpPatternROP(pScrn, &fg, &bg, planemask, &rop); + + sisBLTSync; + if(bg != -1) { + sisSETBGROPCOL(0xcc, bg); /* copy */ + } else { + sisSETBGROPCOL(0xAA, bg); /* noop */ + } + sisSETFGROPCOL(rop, fg); + sisSETPITCH(0, pSiS->scrnOffset); + sisSETSRCADDR(0); + patternRegPtr = (unsigned int *)sisSETPATREG(); + pSiS->sisPatternReg[0] = pSiS->sisPatternReg[2] = patternx ; + pSiS->sisPatternReg[1] = pSiS->sisPatternReg[3] = patterny ; + for ( i = 0 ; i < 16 /* sisPatternHeight */ ; ) { + patternRegPtr[i++] = patternx ; + patternRegPtr[i++] = patterny ; + } +} + +static void +SiSSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patternx, + int patterny, int x, int y, int w, int h) +{ + SISPtr pSiS = SISPTR(pScrn); + int dstaddr; + register unsigned char *patternRegPtr; + register unsigned char *srcPatternRegPtr; + register unsigned int *patternRegPtrL; + int i, k; + unsigned short tmp; + int shift; + int op = sisCMDCOLEXP | + sisTOP2BOTTOM | + sisLEFT2RIGHT | + sisPATFG | + sisSRCBG; + + if (pSiS->ClipEnabled) + op |= sisCLIPINTRN | sisCLIPENABL; + + dstaddr = ( y * pSiS->CurrentLayout.displayWidth + x ) * + pSiS->CurrentLayout.bitsPerPixel / 8; + + sisBLTSync; + + patternRegPtr = sisSETPATREG(); + srcPatternRegPtr = (unsigned char *)pSiS->sisPatternReg ; + shift = 8 - patternx ; + for ( i = 0, k = patterny ; i < 8 ; i++, k++ ) { + tmp = srcPatternRegPtr[k]<<8 | srcPatternRegPtr[k] ; + tmp >>= shift ; + patternRegPtr[i] = tmp & 0xff; + } + patternRegPtrL = (unsigned int *)sisSETPATREG(); + for ( i = 2 ; i < 16 /* sisPatternHeight */; ) { + patternRegPtrL[i++] = patternRegPtrL[0]; + patternRegPtrL[i++] = patternRegPtrL[1]; + } + + sisSETDSTADDR(dstaddr); + sisSETHEIGHTWIDTH(h-1, w*(pSiS->CurrentLayout.bitsPerPixel/8)-1); + sisSETCMD(op); +} + +/* Line */ +static void SiSSetupForSolidLine(ScrnInfoPtr pScrn, + int color, int rop, unsigned int planemask) +{ + SISPtr pSiS = SISPTR(pScrn); + + sisBLTSync; + sisSETBGROPCOL(XAACopyROP[rop], 0); + sisSETFGROPCOL(XAACopyROP[rop], color); +} + +static void SiSSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, int flags) + +{ + SISPtr pSiS = SISPTR(pScrn); + int op ; + int major, minor, err,K1,K2, tmp; + + op = sisCMDLINE | sisSRCFG; + + if ((flags & OMIT_LAST)) + op |= sisLASTPIX; + + if (pSiS->ClipEnabled) + op |= sisCLIPINTRN | sisCLIPENABL; + + if ((major = x2 - x1) <= 0) { + major = -major; + } else + op |= sisXINCREASE; + + if ((minor = y2 - y1) <= 0) { + minor = -minor; + } else + op |= sisYINCREASE; + + if (minor >= major) { + tmp = minor; + minor = major; + major = tmp; + } else + op |= sisXMAJOR; + + K1 = (minor - major)<<1; + K2 = minor<<1; + err = (minor<<1) - major; + + sisBLTSync; + sisSETXStart(x1); + sisSETYStart(y1); + sisSETLineSteps((short)K1,(short)K2); + sisSETLineErrorTerm((short)err); + sisSETLineMajorCount((short)major); + sisSETCMD(op); +} + +static void SiSSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, + int x, int y, int len, int dir) +{ + SISPtr pSiS = SISPTR(pScrn); + int destaddr, op; + + destaddr = y * pSiS->CurrentLayout.displayWidth + x; + + op = sisCMDBLT | sisSRCFG | sisTOP2BOTTOM | sisLEFT2RIGHT; + + if (pSiS->ClipEnabled) + op |= sisCLIPINTRN | sisCLIPENABL; + + destaddr *= (pSiS->CurrentLayout.bitsPerPixel / 8); + + sisBLTSync; + + sisSETPITCH(pSiS->scrnOffset, pSiS->scrnOffset); + + if(dir == DEGREES_0) { + sisSETHEIGHTWIDTH(0, len * (pSiS->CurrentLayout.bitsPerPixel >> 3) - 1); + } else { + sisSETHEIGHTWIDTH(len - 1, (pSiS->CurrentLayout.bitsPerPixel >> 3) - 1); + } + + sisSETDSTADDR(destaddr); + sisSETCMD(op); +} + +#ifdef CTSCE +/* TW: ----- CPU To Screen Color Expand (scanline-wise) ------ */ +static void +SiSSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, int rop, unsigned int planemask) +{ + SISPtr pSiS=SISPTR(pScrn); + + pSiS->CommandReg = 0; + + pSiS->CommandReg |= (sisCMDECOLEXP | + sisLEFT2RIGHT | + sisTOP2BOTTOM); + + sisBLTSync; + + /* TW: The combination of flags in the following + * is not understandable. However, this is the + * only combination that seems to work. + */ + if(bg == -1) { + sisSETROPBG(0xAA); /* dst = dst (=noop) */ + pSiS->CommandReg |= sisSRCFG; + } else { + sisSETBGROPCOL(sisPatALUConv[rop], bg); + pSiS->CommandReg |= sisSRCFG | sisPATBG; + } + + sisSETFGROPCOL(sisALUConv[rop], fg); + + sisSETDSTPITCH(pSiS->scrnOffset); +} + + +static void +SiSSubsequentScanlineCPUToScreenColorExpandFill( + ScrnInfoPtr pScrn, int x, int y, int w, + int h, int skipleft) +{ + SISPtr pSiS = SISPTR(pScrn); + int _x0, _y0, _x1, _y1; + int op = pSiS->CommandReg; + + if(skipleft > 0) { + _x0 = x + skipleft; + _y0 = y; + _x1 = x + w; + _y1 = y + h; + sisSETCLIPTOP(_x0, _y0); + sisSETCLIPBOTTOM(_x1, _y1); + op |= sisCLIPENABL; + } else { + op &= (~(sisCLIPINTRN | sisCLIPENABL)); + } + + sisSETSRCPITCH(((((w+7)/8)+3) >> 2) * 4); + + sisSETHEIGHTWIDTH(1-1, (w * (pSiS->CurrentLayout.bitsPerPixel/8)) - 1); + + pSiS->xcurrent = x; + pSiS->ycurrent = y; + + pSiS->CommandReg = op; +} + +static void +SiSSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) +{ + SISPtr pSiS = SISPTR(pScrn); + long cbo = pSiS->ColorExpandBufferScreenOffset[bufno]; + int op = pSiS->CommandReg; + int destaddr; + + destaddr = (pSiS->ycurrent * pSiS->CurrentLayout.displayWidth) + pSiS->xcurrent; + destaddr *= (pSiS->CurrentLayout.bitsPerPixel / 8); + + /* TW: Wait until there is no color expansion command in queue */ + /* sisBLTSync; */ + + sisSETSRCADDR(cbo); + + sisSETDSTADDR(destaddr); + + sisSETCMD(op); + + pSiS->ycurrent++; + + /* TW: Wait for eventual color expand commands to finish */ + /* (needs to be done, otherwise the data in the buffer may + * be overwritten while accessed by the hardware) + */ + while((MMIO_IN32(pSiS->IOBase, 0x8284) & 0x80000000)) {} + + sisBLTSync; +} +#endif /* CTSCE */ + + diff --git a/src/sis_accel.h b/src/sis_accel.h new file mode 100644 index 0000000..e0d2d3f --- /dev/null +++ b/src/sis_accel.h @@ -0,0 +1,237 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_accel.h,v 1.2 2003/01/29 15:42:16 eich Exp $ */ +/* + * Copyright 1998,1999 by Alan Hourihane, Wigan, England. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk + * Mike Chapman <mike@paranoia.com>, + * Juanjo Santamarta <santamarta@ctv.es>, + * Mitani Hiroshi <hmitani@drl.mei.co.jp> + * David Thomas <davtom@dream.org.uk> + * Thomas Winischhofer <thomas@winischhofer.net> + */ + +/* Definitions for the SIS engine communication. ------------------------------------ */ + +/* For pre-530 chipsets only!!! */ + +/* Engine Registers for 1st generation engines (5597/5598/6326) */ +const int sisReg32MMIO[] = { + 0x8280,0x8284,0x8288,0x828C,0x8290,0x8294, + 0x8298,0x829C,0x82A0,0x82A4,0x82A8,0x82AC +}; + +#define BR(x) sisReg32MMIO[x] + +/* These are done using Memory Mapped IO, of the registers */ +/* + * Modified for Sis by Xavier Ducoin (xavier@rd.lectra.fr) + * + */ + +/* Command Reg 0 (0x82aa, [15:0]) */ +#define sisSRCBG 0x0000 /* source select */ +#define sisSRCFG 0x0001 +#define sisSRCVIDEO 0x0002 +#define sisSRCSYSTEM 0x0003 + +#define sisPATFG 0x0004 /* pattern select */ +#define sisPATREG 0x0008 +#define sisPATBG 0x0000 + +#define sisLEFT2RIGHT 0x0010 /* Direction select */ +#define sisRIGHT2LEFT 0x0000 +#define sisTOP2BOTTOM 0x0020 +#define sisBOTTOM2TOP 0x0000 +#define sisXINCREASE sisLEFT2RIGHT +#define sisYINCREASE sisTOP2BOTTOM + +#define sisCLIPENABL 0x0040 /* Clipping select */ +#define sisCLIPINTRN 0x0080 +#define sisCLIPEXTRN 0x0000 + +#define sisCMDBLT 0x0000 /* Command select */ +#define sisCMDBLTMSK 0x0100 +#define sisCMDCOLEXP 0x0200 +#define sisCMDLINE 0x0300 +#define sisFLGECOLEXP 0x2000 +#define sisCMDECOLEXP (sisCMDCOLEXP | sisFLGECOLEXP) + +#define sisLASTPIX 0x0800 /* Line parameters */ +#define sisXMAJOR 0x0400 + + +/* Macros to do useful things with the SIS BitBLT engine */ + +#define sisBLTSync \ + while(MMIO_IN16(pSiS->IOBase, BR(10) + 2) & 0x4000) {} + +/* According to SiS 6326 2D programming guide, 16 bits position at */ +/* 0x82A8 returns queue free. But this don't work, so don't wait */ +/* anything when turbo-queue is enabled. If there are frequent syncs */ +/* this should work. But not for xaa_benchmark :-( */ + +/* TW: Bit 16 only applies to the hardware queue, not the software + * (=turbo) queue. + */ + +#define sisBLTWAIT \ + if(!pSiS->TurboQueue) { \ + while(MMIO_IN16(pSiS->IOBase, BR(10) + 2) & 0x4000) {} \ + } else { \ + sisBLTSync \ + } + +#define sisSETPATREG() \ + ((unsigned char *)(pSiS->IOBase + BR(11))) + +#define sisSETPATREGL() \ + ((unsigned long *)(pSiS->IOBase + BR(11))) + +/* trigger command */ +#define sisSETCMD(op) \ + { \ + unsigned long temp; \ + MMIO_OUT16(pSiS->IOBase, BR(10) + 2, op); \ + temp = MMIO_IN32(pSiS->IOBase, BR(10)); \ + } + +/* set foreground color and fg ROP */ +#define sisSETFGROPCOL(rop, color) \ + MMIO_OUT32(pSiS->IOBase, BR(4), ((rop << 24) | (color & 0xFFFFFF))); + +/* set background color and bg ROP */ +#define sisSETBGROPCOL(rop, color) \ + MMIO_OUT32(pSiS->IOBase, BR(5), ((rop << 24) | (color & 0xFFFFFF))); + +/* background color */ +#define sisSETBGCOLOR(bgColor) \ + MMIO_OUT32(pSiS->IOBase, BR(5), (bgColor)); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(5)) = (bgColor) +#endif + +/* foreground color */ +#define sisSETFGCOLOR(fgColor) \ + MMIO_OUT32(pSiS->IOBase, BR(4), (fgcolor)); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(4)) = (fgColor) +#endif + +/* ROP */ +#define sisSETROPFG(op) \ + MMIO_OUT8(pSiS->IOBase, BR(4) + 3, op); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(4)) = ((*(volatile unsigned int *)(pSiS->IOBase + BR(4)))&0xffffff) | (op<<24) +#endif + +#define sisSETROPBG(op) \ + MMIO_OUT8(pSiS->IOBase, BR(5) + 3, op); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(5)) = ((*(volatile unsigned int *)(pSiS->IOBase + BR(5)))&0xffffff) | (op<<24) +#endif + +#define sisSETROP(op) \ + sisSETROPFG(op); sisSETROPBG(op); + +/* source and dest address */ +#define sisSETSRCADDR(srcAddr) \ + MMIO_OUT32(pSiS->IOBase, BR(0), (srcAddr & 0x3FFFFFL)); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(0)) = srcAddr & 0x3FFFFFL +#endif + +#define sisSETDSTADDR(dstAddr) \ + MMIO_OUT32(pSiS->IOBase, BR(1), (dstAddr & 0x3FFFFFL)); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(1)) = dstAddr & 0x3FFFFFL +#endif + +/* pitch */ +#define sisSETPITCH(srcPitch,dstPitch) \ + MMIO_OUT32(pSiS->IOBase, BR(2), ((((dstPitch) & 0xFFFF) << 16) | ((srcPitch) & 0xFFFF))); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(2)) = ((dstPitch&0xFFFF)<<16)| \ + (srcPitch&0xFFFF) +#endif + +#define sisSETSRCPITCH(srcPitch) \ + MMIO_OUT16(pSiS->IOBase, BR(2), ((srcPitch) & 0xFFFF)); + +#define sisSETDSTPITCH(dstPitch) \ + MMIO_OUT16(pSiS->IOBase, BR(2) + 2, ((dstPitch) & 0xFFFF)); + +/* Height and width + * According to SIS 2D Engine Programming Guide + * height -1, width - 1 independant of Bpp + */ +#define sisSETHEIGHTWIDTH(Height, Width) \ + MMIO_OUT32(pSiS->IOBase, BR(3), ((((Height) & 0xFFFF) << 16) | ((Width) & 0xFFFF))); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(3)) = (((Height)&0xFFFF)<<16)| \ + ((Width)&0xFFFF) +#endif + +/* Clipping */ +#define sisSETCLIPTOP(x, y) \ + MMIO_OUT32(pSiS->IOBase, BR(8), ((((y) & 0xFFFF) << 16) | ((x) & 0xFFFF))); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(8)) = (((y)&0xFFFF)<<16)| \ + ((x)&0xFFFF) +#endif + +#define sisSETCLIPBOTTOM(x, y) \ + MMIO_OUT32(pSiS->IOBase, BR(9), ((((y) & 0xFFFF) << 16) | ((x) & 0xFFFF))); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(9)) = (((y)&0xFFFF)<<16)| \ + ((x)&0xFFFF) +#endif + +/* Line drawing */ +#define sisSETXStart(XStart) \ + MMIO_OUT32(pSiS->IOBase, BR(0), ((XStart) & 0xFFFF)); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(0)) = XStart&0xFFFF +#endif + +#define sisSETYStart(YStart) \ + MMIO_OUT32(pSiS->IOBase, BR(1), ((YStart) & 0xFFFF)); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(1)) = YStart&0xFFFF +#endif + +#define sisSETLineMajorCount(MajorAxisCount) \ + MMIO_OUT32(pSiS->IOBase, BR(3), ((MajorAxisCount) & 0xFFFF)); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(3)) = MajorAxisCount&0xFFFF +#endif + +#define sisSETLineSteps(K1,K2) \ + MMIO_OUT32(pSiS->IOBase, BR(6), ((((K1) & 0xFFFF) << 16) | ((K2) & 0xFFFF))); +#if 0 + *(volatile unsigned int *)(pSiS->IOBase + BR(6)) = (((K1)&0xFFFF)<<16)| \ + ((K2)&0xFFFF) +#endif + +#define sisSETLineErrorTerm(ErrorTerm) \ + MMIO_OUT16(pSiS->IOBase, BR(7), (ErrorTerm)); +#if 0 + *(volatile unsigned short *)(pSiS->IOBase + BR(7)) = ErrorTerm +#endif diff --git a/src/sis_cursor.c b/src/sis_cursor.c new file mode 100644 index 0000000..b8aed78 --- /dev/null +++ b/src/sis_cursor.c @@ -0,0 +1,1106 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_cursor.c,v 1.10 2003/01/30 21:43:33 tsi Exp $ */ +/* + * Copyright 1998,1999 by Alan Hourihane, Wigan, England. + * Parts Copyright 2001, 2002 by Thomas Winischhofer, Vienna, Austria. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk + * Mike Chapman <mike@paranoia.com>, + * Juanjo Santamarta <santamarta@ctv.es>, + * Mitani Hiroshi <hmitani@drl.mei.co.jp> + * David Thomas <davtom@dream.org.uk>. + * Thomas Winischhofer <thomas@winischhofer.net>: + */ + +#include "xf86.h" +#include "xf86PciInfo.h" +#include "cursorstr.h" +#include "vgaHW.h" + +#include "sis.h" +#include "sis_regs.h" +#include "sis_cursor.h" + +#if 0 +#define SIS300_USE_ARGB16 +#endif + +extern void SISWaitRetraceCRT1(ScrnInfoPtr pScrn); +extern void SISWaitRetraceCRT2(ScrnInfoPtr pScrn); + +static void +SiSShowCursor(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char sridx, cridx; + + /* TW: Backup current indices of SR and CR since we run async:ly + * and might be interrupting an on-going register read/write + */ + sridx = inSISREG(SISSR); cridx = inSISREG(SISCR); + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + orSISIDXREG(SISSR, 0x06, 0x40); + + outSISREG(SISSR, sridx); outSISREG(SISCR, cridx); +} + +static void +SiS300ShowCursor(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(pSiS->SecondHead) { + /* TW: Head 2 is always CRT1 */ + if(pSiS->UseHWARGBCursor) { +#ifdef SIS300_USE_ARGB16 + sis300EnableHWARGB16Cursor() +#else + sis300EnableHWARGBCursor() +#endif + } else { + sis300EnableHWCursor() + } + } else { + /* TW: Head 1 is always CRT2 */ + if(pSiS->UseHWARGBCursor) { +#ifdef SIS300_USE_ARGB16 + sis301EnableHWARGB16Cursor() +#else + sis301EnableHWARGBCursor() +#endif + } else { + sis301EnableHWCursor() + } + } + } else { +#endif + if(pSiS->UseHWARGBCursor) { +#ifdef SIS300_USE_ARGB16 + sis300EnableHWARGB16Cursor() +#else + sis300EnableHWARGBCursor() +#endif + if(pSiS->VBFlags & CRT2_ENABLE) { +#ifdef SIS300_USE_ARGB16 + sis301EnableHWARGB16Cursor() +#else + sis301EnableHWARGBCursor() +#endif + } + } else { + sis300EnableHWCursor() + if(pSiS->VBFlags & CRT2_ENABLE) { + sis301EnableHWCursor() + } + } +#ifdef SISDUALHEAD + } +#endif +} + +/* TW: 310/325 series */ +static void +SiS310ShowCursor(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(pSiS->SecondHead) { + /* TW: Head 2 is always CRT1 */ + if(pSiS->UseHWARGBCursor) { + sis310EnableHWARGBCursor() + } else { + sis310EnableHWCursor() + } + } else { + /* TW: Head 1 is always CRT2 */ + if(pSiS->UseHWARGBCursor) { + sis301EnableHWARGBCursor310() + } else { + sis301EnableHWCursor310() + } + } + } else { +#endif + if(pSiS->UseHWARGBCursor) { + sis310EnableHWARGBCursor() + if(pSiS->VBFlags & CRT2_ENABLE) { + sis301EnableHWARGBCursor310() + } + } else { + sis310EnableHWCursor() + if(pSiS->VBFlags & CRT2_ENABLE) { + sis301EnableHWCursor310() + } + } +#ifdef SISDUALHEAD + } +#endif +} + +static void +SiSHideCursor(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char sridx, cridx; + + sridx = inSISREG(SISSR); cridx = inSISREG(SISCR); + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + andSISIDXREG(SISSR, 0x06, 0xBF); + + outSISREG(SISSR, sridx); outSISREG(SISCR, cridx); +} + +static void +SiS300HideCursor(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode && (!pSiS->ForceCursorOff)) { + if(pSiS->SecondHead) { + /* TW: Head 2 is always CRT1 */ + sis300DisableHWCursor() + sis300SetCursorPositionY(2000, 0) + } else { + /* TW: Head 1 is always CRT2 */ + sis301DisableHWCursor() + sis301SetCursorPositionY(2000, 0) + } + } else { +#endif + sis300DisableHWCursor() + sis300SetCursorPositionY(2000, 0) + if(pSiS->VBFlags & CRT2_ENABLE) { + sis301DisableHWCursor() + sis301SetCursorPositionY(2000, 0) + } +#ifdef SISDUALHEAD + } +#endif +} + +/* TW: 310/325 series */ +static void +SiS310HideCursor(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode && (!pSiS->ForceCursorOff)) { + if(pSiS->SecondHead) { + /* TW: Head 2 is always CRT1 */ + sis310DisableHWCursor() + sis310SetCursorPositionY(2000, 0) + } else { + /* TW: Head 1 is always CRT2 */ + sis301DisableHWCursor310() + sis301SetCursorPositionY310(2000, 0) + } + } else { +#endif + sis310DisableHWCursor() + sis310SetCursorPositionY(2000, 0) + if(pSiS->VBFlags & CRT2_ENABLE) { + sis301DisableHWCursor310() + sis301SetCursorPositionY310(2000, 0) + } +#ifdef SISDUALHEAD + } +#endif +} + +static void +SiSSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char x_preset = 0; + unsigned char y_preset = 0; + int temp; + unsigned char sridx, cridx; + + sridx = inSISREG(SISSR); cridx = inSISREG(SISCR); + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + if (x < 0) { + x_preset = (-x); + x = 0; + } + + if (y < 0) { + y_preset = (-y); + y = 0; + } + + /* are we in interlaced/doublescan mode? */ + if (pScrn->currentMode->Flags & V_INTERLACE) + y /= 2; + else if (pScrn->currentMode->Flags & V_DBLSCAN) + y *= 2; + + outSISIDXREG(SISSR, 0x1A, x & 0xff); + outSISIDXREG(SISSR, 0x1B, (x & 0xff00) >> 8); + outSISIDXREG(SISSR, 0x1D, y & 0xff); + + inSISIDXREG(SISSR, 0x1E, temp); + temp &= 0xF8; + outSISIDXREG(SISSR, 0x1E, temp | ((y >> 8) & 0x07)); + + outSISIDXREG(SISSR, 0x1C, x_preset); + outSISIDXREG(SISSR, 0x1F, y_preset); + + outSISREG(SISSR, sridx); outSISREG(SISCR, cridx); +} + +static void +SiS300SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char x_preset = 0; + unsigned char y_preset = 0; + + if (x < 0) { + x_preset = (-x); + x = 0; + } + if (y < 0) { + y_preset = (-y); + y = 0; + } + + /* are we in interlaced/doublescan mode? */ + if(pScrn->currentMode->Flags & V_INTERLACE) + y /= 2; + else if(pScrn->currentMode->Flags & V_DBLSCAN) + y *= 2; + +#ifdef SISDUALHEAD + if (pSiS->DualHeadMode) { + if (pSiS->SecondHead) { + /* TW: Head 2 is always CRT1 */ + sis300SetCursorPositionX(x, x_preset) + sis300SetCursorPositionY(y, y_preset) + } else { + /* TW: Head 1 is always CRT2 */ + sis301SetCursorPositionX(x+13, x_preset) + sis301SetCursorPositionY(y, y_preset) + } + } else { +#endif + sis300SetCursorPositionX(x, x_preset) + sis300SetCursorPositionY(y, y_preset) + if(pSiS->VBFlags & CRT2_ENABLE) { + sis301SetCursorPositionX(x+13, x_preset) + sis301SetCursorPositionY(y, y_preset) + } +#ifdef SISDUALHEAD + } +#endif +} + +static void +SiS310SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char x_preset = 0; + unsigned char y_preset = 0; + + if (x < 0) { + x_preset = (-x); + x = 0; + } + if (y < 0) { + y_preset = (-y); + y = 0; + } + + /* are we in interlaced/doublescan mode? */ + if(pScrn->currentMode->Flags & V_INTERLACE) + y /= 2; + else if(pScrn->currentMode->Flags & V_DBLSCAN) + y *= 2; + +#ifdef SISDUALHEAD + if (pSiS->DualHeadMode) { + if (pSiS->SecondHead) { + /* TW: Head 2 is always CRT1 */ + sis310SetCursorPositionX(x, x_preset) + sis310SetCursorPositionY(y, y_preset) + } else { + /* TW: Head 1 is always CRT2 */ + sis301SetCursorPositionX310(x + 17, x_preset) + sis301SetCursorPositionY310(y, y_preset) + } + } else { +#endif + sis310SetCursorPositionX(x, x_preset) + sis310SetCursorPositionY(y, y_preset) + if (pSiS->VBFlags & CRT2_ENABLE) { + sis301SetCursorPositionX310(x + 17, x_preset) + sis301SetCursorPositionY310(y, y_preset) + } +#ifdef SISDUALHEAD + } +#endif +} + +static void +SiSSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char f_red, f_green, f_blue; + unsigned char b_red, b_green, b_blue; + unsigned char sridx, cridx; + + sridx = inSISREG(SISSR); cridx = inSISREG(SISCR); + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + f_red = (fg & 0x00FF0000) >> (16+2); + f_green = (fg & 0x0000FF00) >> (8+2); + f_blue = (fg & 0x000000FF) >> 2; + b_red = (bg & 0x00FF0000) >> (16+2); + b_green = (bg & 0x0000FF00) >> (8+2); + b_blue = (bg & 0x000000FF) >> 2; + + outSISIDXREG(SISSR, 0x14, b_red); + outSISIDXREG(SISSR, 0x15, b_green); + outSISIDXREG(SISSR, 0x16, b_blue); + outSISIDXREG(SISSR, 0x17, f_red); + outSISIDXREG(SISSR, 0x18, f_green); + outSISIDXREG(SISSR, 0x19, f_blue); + + outSISREG(SISSR, sridx); outSISREG(SISCR, cridx); +} + +static void +SiS300SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +{ + SISPtr pSiS = SISPTR(pScrn); + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(pSiS->SecondHead) { + /* TW: Head 2 is always CRT1 */ + sis300SetCursorBGColor(bg) + sis300SetCursorFGColor(fg) + } else { + /* TW: Head 1 is always CRT2 */ + sis301SetCursorBGColor(bg) + sis301SetCursorFGColor(fg) + } + } else { +#endif + sis300SetCursorBGColor(bg) + sis300SetCursorFGColor(fg) + if(pSiS->VBFlags & CRT2_ENABLE) { + sis301SetCursorBGColor(bg) + sis301SetCursorFGColor(fg) + } +#ifdef SISDUALHEAD + } +#endif +} + +static void +SiS310SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +{ + SISPtr pSiS = SISPTR(pScrn); + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(pSiS->SecondHead) { + /* TW: Head 2 is always CRT1 */ + sis310SetCursorBGColor(bg) + sis310SetCursorFGColor(fg) + } else { + /* TW: Head 1 is always CRT2 */ + sis301SetCursorBGColor310(bg) + sis301SetCursorFGColor310(fg) + } + } else { +#endif + sis310SetCursorBGColor(bg) + sis310SetCursorFGColor(fg) + if(pSiS->VBFlags & CRT2_ENABLE) { + sis301SetCursorBGColor310(bg) + sis301SetCursorFGColor310(fg) + } +#ifdef SISDUALHEAD + } +#endif +} + +static void +SiSLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) +{ + SISPtr pSiS = SISPTR(pScrn); + int cursor_addr; + unsigned char temp; + unsigned char sridx, cridx; + + sridx = inSISREG(SISSR); cridx = inSISREG(SISCR); + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + cursor_addr = pScrn->videoRam - 1; + if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) { + int i; + for(i = 0; i < 32; i++) { + memcpy((unsigned char *)pSiS->FbBase + (cursor_addr * 1024) + (32 * i), + src + (16 * i), 16); + memcpy((unsigned char *)pSiS->FbBase + (cursor_addr * 1024) + (32 * i) + 16, + src + (16 * i), 16); + } + } else { + memcpy((unsigned char *)pSiS->FbBase + (cursor_addr * 1024), src, 1024); + } + + /* copy bits [21:18] into the top bits of SR38 */ + inSISIDXREG(SISSR, 0x38, temp); + temp &= 0x0F; + outSISIDXREG(SISSR, 0x38, temp | ((cursor_addr & 0xF00) >> 4)); + + if(pSiS->Chipset == PCI_CHIP_SIS530) { + /* store the bit [22] to SR3E */ + if(cursor_addr & 0x1000) { + orSISIDXREG(SISSR, 0x3E, 0x04); + } else { + andSISIDXREG(SISSR, 0x3E, ~0x04); + } + } + + /* set HW cursor pattern, use pattern 0xF */ + orSISIDXREG(SISSR, 0x1E, 0xF0); + + /* disable the hardware cursor side pattern */ + andSISIDXREG(SISSR, 0x1E, 0xF7); + + outSISREG(SISSR, sridx); outSISREG(SISCR, cridx); +} + +static void +SiS300LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) +{ + SISPtr pSiS = SISPTR(pScrn); + int cursor_addr; + CARD32 status1 = 0, status2 = 0; + +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + cursor_addr = pScrn->videoRam - pSiS->cursorOffset - (pSiS->CursorSize/1024); /* 1K boundary */ + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + /* TW: Use the global (real) FbBase in DHM */ + if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) { + int i; + for(i = 0; i < 32; i++) { + memcpy((unsigned char *)pSiSEnt->FbBase + (cursor_addr * 1024) + (32 * i), + src + (16 * i), 16); + memcpy((unsigned char *)pSiSEnt->FbBase + (cursor_addr * 1024) + (32 * i) + 16, + src + (16 * i), 16); + } + } else { + memcpy((unsigned char *)pSiSEnt->FbBase + (cursor_addr * 1024), src, 1024); + } + } else +#endif + if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) { + int i; + for(i = 0; i < 32; i++) { + memcpy((unsigned char *)pSiS->FbBase + (cursor_addr * 1024) + (32 * i), + src + (16 * i), 16); + memcpy((unsigned char *)pSiS->FbBase + (cursor_addr * 1024) + (32 * i) + 16, + src + (16 * i), 16); + } + } else { + memcpy((unsigned char *)pSiS->FbBase + (cursor_addr * 1024), src, 1024); + } + + if(pSiS->UseHWARGBCursor) { + if(pSiS->VBFlags & DISPTYPE_CRT1) { + status1 = sis300GetCursorStatus; + sis300DisableHWCursor() + if(pSiS->VBFlags & CRT2_ENABLE) { + status2 = sis301GetCursorStatus; + sis301DisableHWCursor() + } + SISWaitRetraceCRT1(pScrn); + sis300SwitchToMONOCursor(); + if(pSiS->VBFlags & CRT2_ENABLE) { + SISWaitRetraceCRT2(pScrn); + sis301SwitchToMONOCursor(); + } + } + } + sis300SetCursorAddress(cursor_addr); + sis300SetCursorPatternSelect(0); + if(status1) sis300SetCursorStatus(status1) + + if(pSiS->VBFlags & CRT2_ENABLE) { + if((pSiS->UseHWARGBCursor) && (!pSiS->VBFlags & DISPTYPE_CRT1)) { + status2 = sis301GetCursorStatus; + sis301DisableHWCursor() + SISWaitRetraceCRT2(pScrn); + sis301SwitchToMONOCursor(); + } + sis301SetCursorAddress(cursor_addr) + sis301SetCursorPatternSelect(0) + if(status2) sis301SetCursorStatus(status2) + } + + pSiS->UseHWARGBCursor = FALSE; +} + +static void +SiS310LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) +{ + SISPtr pSiS = SISPTR(pScrn); + int cursor_addr; + CARD32 status1 = 0, status2 = 0; + +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + cursor_addr = pScrn->videoRam - pSiS->cursorOffset - (pSiS->CursorSize/1024); /* 1K boundary */ + +#ifdef SISDUALHEAD + if (pSiS->DualHeadMode) { + /* TW: Use the global (real) FbBase in DHM */ + if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) { + int i; + for(i = 0; i < 32; i++) { + memcpy((unsigned char *)pSiSEnt->FbBase + (cursor_addr * 1024) + (32 * i), + src + (16 * i), 16); + memcpy((unsigned char *)pSiSEnt->FbBase + (cursor_addr * 1024) + (32 * i) + 16, + src + (16 * i), 16); + } + } else { + memcpy((unsigned char *)pSiSEnt->FbBase + (cursor_addr * 1024), src, 1024); + } + } else +#endif + if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) { + int i; + for(i = 0; i < 32; i++) { + memcpy((unsigned char *)pSiS->FbBase + (cursor_addr * 1024) + (32 * i), + src + (16 * i), 16); + memcpy((unsigned char *)pSiS->FbBase + (cursor_addr * 1024) + (32 * i) + 16, + src + (16 * i), 16); + } + } else { + memcpy((unsigned char *)pSiS->FbBase + (cursor_addr * 1024), src, 1024); + } + + if(pSiS->UseHWARGBCursor) { + if(pSiS->VBFlags & DISPTYPE_CRT1) { + status1 = sis310GetCursorStatus; + sis310DisableHWCursor() + if(pSiS->VBFlags & CRT2_ENABLE) { + status2 = sis301GetCursorStatus310; + sis301DisableHWCursor310() + } + SISWaitRetraceCRT1(pScrn); + sis310SwitchToMONOCursor(); + if(pSiS->VBFlags & CRT2_ENABLE) { + SISWaitRetraceCRT2(pScrn); + sis301SwitchToMONOCursor310(); + } + } + } + sis310SetCursorAddress(cursor_addr); + sis310SetCursorPatternSelect(0); + if(status1) sis310SetCursorStatus(status1) + + if(pSiS->VBFlags & CRT2_ENABLE) { + if((pSiS->UseHWARGBCursor) && (!pSiS->VBFlags & DISPTYPE_CRT1)) { + status2 = sis301GetCursorStatus310; + sis301DisableHWCursor310() + SISWaitRetraceCRT2(pScrn); + sis301SwitchToMONOCursor310(); + } + sis301SetCursorAddress310(cursor_addr) + sis301SetCursorPatternSelect310(0) + if(status2) sis301SetCursorStatus310(status2) + } + + pSiS->UseHWARGBCursor = FALSE; +} + +static Bool +SiSUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DisplayModePtr mode = pScrn->currentMode; + SISPtr pSiS = SISPTR(pScrn); + + if(pSiS->Chipset != PCI_CHIP_SIS6326) return TRUE; + if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return TRUE; + if((strcmp(mode->name, "PAL800x600U") == 0) || + (strcmp(mode->name, "NTSC640x480U") == 0)) + return FALSE; + else + return TRUE; +} + +static Bool +SiS300UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + DisplayModePtr mode = pSiS->CurrentLayout.mode; /* pScrn->currentMode; */ + + switch (pSiS->Chipset) { + case PCI_CHIP_SIS300: + case PCI_CHIP_SIS630: + case PCI_CHIP_SIS540: + if(mode->Flags & V_INTERLACE) + return FALSE; + if((mode->Flags & V_DBLSCAN) && (pCurs->bits->height > 32)) + return FALSE; + break; + case PCI_CHIP_SIS550: + case PCI_CHIP_SIS650: + case PCI_CHIP_SIS315: + case PCI_CHIP_SIS315H: + case PCI_CHIP_SIS315PRO: + case PCI_CHIP_SIS330: + if(mode->Flags & V_INTERLACE) + return FALSE; + if((mode->Flags & V_DBLSCAN) && (pCurs->bits->height > 32)) + return FALSE; + break; + default: + if(mode->Flags & V_INTERLACE) + return FALSE; + if((mode->Flags & V_DBLSCAN) && (pCurs->bits->height > 32)) + return FALSE; + break; + } + return TRUE; +} + +#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) +#ifdef ARGB_CURSOR +#ifdef SIS_ARGB_CURSOR +static Bool +SiSUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DisplayModePtr mode = pScrn->currentMode; + SISPtr pSiS = SISPTR(pScrn); + + switch (pSiS->Chipset) { + case PCI_CHIP_SIS300: + case PCI_CHIP_SIS630: + case PCI_CHIP_SIS540: + if(mode->Flags & V_INTERLACE) + return FALSE; + if(pCurs->bits->height > 32 || pCurs->bits->width > 32) + return FALSE; + if((mode->Flags & V_DBLSCAN) && (pCurs->bits->height > 16)) + return FALSE; + break; + case PCI_CHIP_SIS550: + case PCI_CHIP_SIS650: + case PCI_CHIP_SIS315: + case PCI_CHIP_SIS315H: + case PCI_CHIP_SIS315PRO: + case PCI_CHIP_SIS330: + if(mode->Flags & V_INTERLACE) + return FALSE; + if(pCurs->bits->height > 64 || pCurs->bits->width > 64) + return FALSE; + if((mode->Flags & V_DBLSCAN) && (pCurs->bits->height > 32)) + return FALSE; + break; + default: + return FALSE; + } + return TRUE; +} + +static void SiS300LoadCursorImageARGB(ScrnInfoPtr pScrn, CursorPtr pCurs) +{ + SISPtr pSiS = SISPTR(pScrn); + int cursor_addr, i, j, maxheight = 32; + CARD32 *src = pCurs->bits->argb, *p; +#ifdef SIS300_USE_ARGB16 + CARD16 *dest, *pb; + CARD16 temp1; +#define MYSISPTRTYPE CARD16 +#else + CARD32 *pb, *dest; +#define MYSISPTRTYPE CARD32 +#endif + int srcwidth = pCurs->bits->width; + int srcheight = pCurs->bits->height; + BOOLEAN sizedouble = FALSE; + CARD32 temp, status1 = 0, status2 = 0; + +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + cursor_addr = pScrn->videoRam - pSiS->cursorOffset - ((pSiS->CursorSize/1024) * 2); + + if(srcwidth > 32) srcwidth = 32; + if(srcheight > 32) srcheight = 32; + +#ifdef SISDUALHEAD + if (pSiS->DualHeadMode) + /* TW: Use the global (real) FbBase in DHM */ + dest = (MYSISPTRTYPE *)((unsigned char *)pSiSEnt->FbBase + (cursor_addr * 1024)); + else +#endif + dest = (MYSISPTRTYPE *)((unsigned char *)pSiS->FbBase + (cursor_addr * 1024)); + + if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) { + sizedouble = TRUE; + if(srcheight > 16) srcheight = 16; + maxheight = 16; + } + +#ifdef SIS300_USE_ARGB16 /* Use 16 Bit RGB pointer */ + for(i = 0; i < srcheight; i++) { + p = src; + pb = dest; + src += pCurs->bits->width; + for(j = 0; j < srcwidth; j++) { + temp = *p++; + if(temp & 0xffffff) { + temp1 = ((temp & 0xff) >> 3) | + ((((temp & 0xff00) >> (8 + 3)) << 5) & 0x03e0) | + ((((temp & 0xff0000) >> (16 + 3)) << 10) & 0x7c00); + } else temp1 = 0x8000; + *dest++ = temp1; + } + if(srcwidth < 32) { + for(; j < 32; j++) { + *dest++ = 0x8000; + } + } + } + if(srcheight < maxheight) { + for(; i < maxheight; i++) + for(j = 0; j < 32; j++) { + *dest++ = 0x8000; + } + if(sizedouble) { + for(j = 0; j < 32; j++) + *dest++ = 0x0000; + } + } +#else /* Use 32bit RGB pointer - preferred, saves us from the conversion */ + for(i = 0; i < srcheight; i++) { + p = src; + pb = dest; + src += pCurs->bits->width; + for(j = 0; j < srcwidth; j++) { + temp = *p++; +/* *dest1++ = ((temp ^ 0xff000000) << 4) | (((temp ^ 0xff000000) & 0xf0000000) >> 28); */ + if(pSiS->OptUseColorCursorBlend) { + if(temp & 0xffffff) { + if((temp & 0xff000000) > pSiS->OptColorCursorBlendThreshold) { + temp &= 0x00ffffff; + } else { + temp = 0xff111111; + } + } else temp = 0xff000000; + } else { + if(temp & 0xffffff) temp &= 0x00ffffff; + else temp = 0xff000000; + } + *dest++ = temp; + } + if(srcwidth < 32) { + for(; j < 32; j++) { + *dest++ = 0xff000000; + } + } + if(sizedouble) { + for(j = 0; j < 32; j++) { + *dest++ = *pb++; + } + } + + } + if(srcheight < maxheight) { + for(; i < maxheight; i++) { + for(j = 0; j < 32; j++) { + *dest++ = 0xff000000; + } + if(sizedouble) { + for(j = 0; j < 32; j++) { + *dest++ = 0xff000000; + } + } + } + } +#endif + + if(!pSiS->UseHWARGBCursor) { + if(pSiS->VBFlags & DISPTYPE_CRT1) { + status1 = sis300GetCursorStatus; + sis300DisableHWCursor() + if(pSiS->VBFlags & CRT2_ENABLE) { + status2 = sis301GetCursorStatus; + sis301DisableHWCursor() + } + SISWaitRetraceCRT1(pScrn); + sis300SwitchToRGBCursor(); + if(pSiS->VBFlags & CRT2_ENABLE) { + SISWaitRetraceCRT2(pScrn); + sis301SwitchToRGBCursor(); + } + } + } + sis300SetCursorAddress(cursor_addr); + sis300SetCursorPatternSelect(0); + if(status1) sis300SetCursorStatus(status1) + + if(pSiS->VBFlags & CRT2_ENABLE) { + if((!pSiS->UseHWARGBCursor) && (!pSiS->VBFlags & DISPTYPE_CRT1)) { + status2 = sis301GetCursorStatus; + sis301DisableHWCursor() + SISWaitRetraceCRT2(pScrn); + sis301SwitchToRGBCursor(); + } + sis301SetCursorAddress(cursor_addr) + sis301SetCursorPatternSelect(0) + if(status2) sis301SetCursorStatus(status2) + } + + pSiS->UseHWARGBCursor = TRUE; +} + +static void SiS310LoadCursorImageARGB(ScrnInfoPtr pScrn, CursorPtr pCurs) +{ + SISPtr pSiS = SISPTR(pScrn); + int cursor_addr, i, j, maxheight = 64; + CARD32 *src = pCurs->bits->argb, *p, *pb, *dest; + int srcwidth = pCurs->bits->width; + int srcheight = pCurs->bits->height; + BOOLEAN sizedouble = FALSE; + CARD32 status1 = 0, status2 = 0; + +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + cursor_addr = pScrn->videoRam - pSiS->cursorOffset - ((pSiS->CursorSize/1024) * 2); + + if(srcwidth > 64) srcwidth = 64; + if(srcheight > 64) srcheight = 64; + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) + /* TW: Use the global (real) FbBase in DHM */ + dest = (CARD32 *)((unsigned char *)pSiSEnt->FbBase + (cursor_addr * 1024)); + else +#endif + dest = (CARD32 *)((unsigned char *)pSiS->FbBase + (cursor_addr * 1024)); + + if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) { + sizedouble = TRUE; + if(srcheight > 32) srcheight = 32; + maxheight = 32; + } + + for(i = 0; i < srcheight; i++) { + p = src; + pb = dest; + src += pCurs->bits->width; + for(j = 0; j < srcwidth; j++) *dest++ = *p++; + if(srcwidth < 64) { + for(; j < 64; j++) *dest++ = 0; + } + if(sizedouble) { + for(j = 0; j < 64; j++) { + *dest++ = *pb++; + } + } + } + if(srcheight < maxheight) { + for(; i < maxheight; i++) + for(j = 0; j < 64; j++) *dest++ = 0; + if(sizedouble) { + for(j = 0; j < 64; j++) *dest++ = 0; + } + } + + if(!pSiS->UseHWARGBCursor) { + if(pSiS->VBFlags & DISPTYPE_CRT1) { + status1 = sis310GetCursorStatus; + sis310DisableHWCursor() + if(pSiS->VBFlags & CRT2_ENABLE) { + status2 = sis301GetCursorStatus310; + sis301DisableHWCursor310() + } + SISWaitRetraceCRT1(pScrn); + sis310SwitchToRGBCursor(); + if(pSiS->VBFlags & CRT2_ENABLE) { + SISWaitRetraceCRT2(pScrn); + sis301SwitchToRGBCursor310(); + } + } + } + sis310SetCursorAddress(cursor_addr); + sis310SetCursorPatternSelect(0); + if(status1) sis310SetCursorStatus(status1) + + if(pSiS->VBFlags & CRT2_ENABLE) { + if((!pSiS->UseHWARGBCursor) && (!pSiS->VBFlags & DISPTYPE_CRT1)) { + status2 = sis301GetCursorStatus310; + sis301DisableHWCursor310() + SISWaitRetraceCRT2(pScrn); + sis301SwitchToRGBCursor310(); + } + sis301SetCursorAddress310(cursor_addr) + sis301SetCursorPatternSelect310(0) + if(status2) sis301SetCursorStatus310(status2) + } + + pSiS->UseHWARGBCursor = TRUE; +} +#endif +#endif +#endif + +Bool +SiSHWCursorInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + xf86CursorInfoPtr infoPtr; + + PDEBUG(ErrorF("HW Cursor Init\n")); + infoPtr = xf86CreateCursorInfoRec(); + if(!infoPtr) + return FALSE; + + pSiS->CursorInfoPtr = infoPtr; + pSiS->UseHWARGBCursor = FALSE; + + switch (pSiS->Chipset) { + case PCI_CHIP_SIS300: + case PCI_CHIP_SIS630: + case PCI_CHIP_SIS540: + infoPtr->MaxWidth = 64; + infoPtr->MaxHeight = 64; + infoPtr->ShowCursor = SiS300ShowCursor; + infoPtr->HideCursor = SiS300HideCursor; + infoPtr->SetCursorPosition = SiS300SetCursorPosition; + infoPtr->SetCursorColors = SiS300SetCursorColors; + infoPtr->LoadCursorImage = SiS300LoadCursorImage; + infoPtr->UseHWCursor = SiS300UseHWCursor; +#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) +#ifdef ARGB_CURSOR +#ifdef SIS_ARGB_CURSOR + if(pSiS->OptUseColorCursor) { + infoPtr->UseHWCursorARGB = SiSUseHWCursorARGB; + infoPtr->LoadCursorARGB = SiS300LoadCursorImageARGB; + } +#endif +#endif +#endif + infoPtr->Flags = + HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_INVERT_MASK | + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64; + break; + case PCI_CHIP_SIS550: + case PCI_CHIP_SIS650: + case PCI_CHIP_SIS315: + case PCI_CHIP_SIS315H: + case PCI_CHIP_SIS315PRO: + case PCI_CHIP_SIS330: + infoPtr->MaxWidth = 64; + infoPtr->MaxHeight = 64; + infoPtr->ShowCursor = SiS310ShowCursor; + infoPtr->HideCursor = SiS310HideCursor; + infoPtr->SetCursorPosition = SiS310SetCursorPosition; + infoPtr->SetCursorColors = SiS310SetCursorColors; + infoPtr->LoadCursorImage = SiS310LoadCursorImage; + infoPtr->UseHWCursor = SiS300UseHWCursor; +#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) +#ifdef ARGB_CURSOR +#ifdef SIS_ARGB_CURSOR + if(pSiS->OptUseColorCursor) { + infoPtr->UseHWCursorARGB = SiSUseHWCursorARGB; + infoPtr->LoadCursorARGB = SiS310LoadCursorImageARGB; + } +#endif +#endif +#endif + infoPtr->Flags = + HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_INVERT_MASK | + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64; + break; + default: + infoPtr->MaxWidth = 64; + infoPtr->MaxHeight = 64; + infoPtr->SetCursorPosition = SiSSetCursorPosition; + infoPtr->ShowCursor = SiSShowCursor; + infoPtr->HideCursor = SiSHideCursor; + infoPtr->SetCursorColors = SiSSetCursorColors; + infoPtr->LoadCursorImage = SiSLoadCursorImage; + infoPtr->UseHWCursor = SiSUseHWCursor; + infoPtr->Flags = + HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_INVERT_MASK | + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + HARDWARE_CURSOR_NIBBLE_SWAPPED | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1; + break; + } + + return(xf86InitCursor(pScreen, infoPtr)); +} diff --git a/src/sis_cursor.h b/src/sis_cursor.h new file mode 100644 index 0000000..76258ac --- /dev/null +++ b/src/sis_cursor.h @@ -0,0 +1,427 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_cursor.h,v 1.5 2003/02/06 13:14:04 eich Exp $ */ +/* + * Copyright 1998,1999 by Alan Hourihane, Wigan, England. + * Parts Copyright 2001, 2002 by Thomas Winischhofer, Vienna, Austria. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk + * Mike Chapman <mike@paranoia.com>, + * Juanjo Santamarta <santamarta@ctv.es>, + * Mitani Hiroshi <hmitani@drl.mei.co.jp> + * David Thomas <davtom@dream.org.uk>. + * Thomas Winischhofer <thomas@winischhofer.net>: + */ + +#define CS(x) (0x8500+(x<<2)) + +/* 300 series, CRT1 */ + +/* 80000000 = RGB(1) - MONO(0) + * 40000000 = enable(1) - disable(0) + * 20000000 = 32(1) / 16(1) bit RGB + * 10000000 = "ghost"(1) - [other effect](0) + */ + +#define sis300GetCursorStatus \ + MMIO_IN32(pSiS->IOBase, CS(0)) & 0x40000000; + +#define sis300SetCursorStatus(status) \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0xbfffffff; \ + temp |= status; \ + MMIO_OUT32(pSiS->IOBase, CS(0), temp); \ + } + +#define sis300EnableHWCursor() \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0x0fffffff; \ + temp |= 0x40000000; \ + MMIO_OUT32(pSiS->IOBase, CS(0), temp); \ + } + +#define sis300EnableHWARGBCursor() \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp |= 0xF0000000; \ + MMIO_OUT32(pSiS->IOBase, CS(0), temp); \ + } + +#define sis300EnableHWARGB16Cursor() \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0x0fffffff; \ + temp |= 0xD0000000; \ + MMIO_OUT32(pSiS->IOBase, CS(0), temp); \ + } + +#define sis300SwitchToMONOCursor() \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0x4fffffff; \ + MMIO_OUT32(pSiS->IOBase, CS(0), temp); \ + } + +#define sis300SwitchToRGBCursor() \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp |= 0xB0000000; \ + MMIO_OUT32(pSiS->IOBase, CS(0), temp); \ + } + +#define sis300DisableHWCursor()\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0xbFFFFFFF; \ + MMIO_OUT32(pSiS->IOBase, CS(0), temp); \ + } + +#define sis300SetCursorBGColor(color)\ + MMIO_OUT32(pSiS->IOBase, CS(1), (color)); +#define sis300SetCursorFGColor(color)\ + MMIO_OUT32(pSiS->IOBase, CS(2), (color)); + +#define sis300SetCursorPositionX(x,preset)\ + MMIO_OUT32(pSiS->IOBase, CS(3), ((x) | ((preset) << 16))); +#define sis300SetCursorPositionY(y,preset)\ + MMIO_OUT32(pSiS->IOBase, CS(4), ((y) | ((preset) << 16))); + +#define sis300SetCursorAddress(address)\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0xFFFF0000; \ + temp |= address; \ + MMIO_OUT32(pSiS->IOBase,CS(0),temp); \ + } + +#define sis300SetCursorPatternSelect(pat_id)\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0xF0FFFFFF; \ + temp |= (pat_id) << 24; \ + MMIO_OUT32(pSiS->IOBase,CS(0),temp); \ + } + +/* 300 series, CRT2 */ + +/* 80000000 = RGB(1) - MONO(0) + * 40000000 = enable(1) - disable(0) + * 20000000 = 32(1) / 16(1) bit RGB + * 10000000 = unused (always "ghosting") + */ + +#define sis301GetCursorStatus \ + MMIO_IN32(pSiS->IOBase, CS(8)) & 0x40000000; + +#define sis301SetCursorStatus(status) \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0xbfffffff; \ + temp |= status; \ + MMIO_OUT32(pSiS->IOBase, CS(8), temp); \ + } + +#define sis301EnableHWCursor()\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0x0fffffff; \ + temp |= 0x40000000; \ + MMIO_OUT32(pSiS->IOBase, CS(8), temp); \ + } + +#define sis301EnableHWARGBCursor()\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp |= 0xF0000000; \ + MMIO_OUT32(pSiS->IOBase, CS(8), temp); \ + } + +#define sis301EnableHWARGB16Cursor()\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0x0FFFFFFF; \ + temp |= 0xD0000000; \ + MMIO_OUT32(pSiS->IOBase, CS(8), temp); \ + } + +#define sis301SwitchToRGBCursor() \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp |= 0xB0000000; \ + MMIO_OUT32(pSiS->IOBase, CS(8), temp); \ + } + +#define sis301SwitchToMONOCursor() \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0x4fffffff; \ + MMIO_OUT32(pSiS->IOBase, CS(8), temp); \ + } + +#define sis301DisableHWCursor()\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0xbFFFFFFF; \ + MMIO_OUT32(pSiS->IOBase, CS(8), temp); \ + } + +#define sis301SetCursorBGColor(color)\ + MMIO_OUT32(pSiS->IOBase, CS(9), (color)); +#define sis301SetCursorFGColor(color)\ + MMIO_OUT32(pSiS->IOBase, CS(10), (color)); + +#define sis301SetCursorPositionX(x,preset)\ + MMIO_OUT32(pSiS->IOBase, CS(11), ((x) | ((preset) << 16))); +#define sis301SetCursorPositionY(y,preset)\ + MMIO_OUT32(pSiS->IOBase, CS(12), ((y) | ((preset) << 16))); + +#define sis301SetCursorAddress(address)\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0xFFFF0000; \ + temp |= address; \ + MMIO_OUT32(pSiS->IOBase,CS(8),temp); \ + } + +#define sis301SetCursorPatternSelect(pat_id)\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0xF0FFFFFF; \ + temp |= (pat_id) << 24; \ + MMIO_OUT32(pSiS->IOBase,CS(8),temp); \ + } + +/* 310/325/330 series CRT1 */ + +/* 80000000 = RGB(1) - MONO(0) + * 40000000 = enable(1) - disable(0) + * 20000000 = 32(1) / 16(1) bit RGB + * 10000000 = "ghost"(1) - Alpha Blend(0) + */ + +#define sis310GetCursorStatus \ + MMIO_IN32(pSiS->IOBase, CS(0)) & 0x40000000; + +#define sis310SetCursorStatus(status) \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0xbfffffff; \ + temp |= status; \ + MMIO_OUT32(pSiS->IOBase, CS(0), temp); \ + } + +#define sis310EnableHWCursor()\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0x0fffffff; \ + temp |= 0x40000000; \ + MMIO_OUT32(pSiS->IOBase, CS(0), temp); \ + } + +#define sis310EnableHWARGBCursor()\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0x0FFFFFFF; \ + temp |= 0xE0000000; \ + MMIO_OUT32(pSiS->IOBase, CS(0), temp); \ + } + +#define sis310SwitchToMONOCursor() \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0x4fffffff; \ + MMIO_OUT32(pSiS->IOBase, CS(0), temp); \ + } + +#define sis310SwitchToRGBCursor() \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0xBFFFFFFF; \ + temp |= 0xA0000000; \ + MMIO_OUT32(pSiS->IOBase, CS(0), temp); \ + } + +#define sis310DisableHWCursor()\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0xBFFFFFFF; \ + MMIO_OUT32(pSiS->IOBase, CS(0), temp); \ + } + +#define sis310SetCursorBGColor(color)\ + MMIO_OUT32(pSiS->IOBase, CS(1), (color)); +#define sis310SetCursorFGColor(color)\ + MMIO_OUT32(pSiS->IOBase, CS(2), (color)); + +#define sis310SetCursorPositionX(x,preset)\ + MMIO_OUT32(pSiS->IOBase, CS(3), ((x) | ((preset) << 16))); +#define sis310SetCursorPositionY(y,preset)\ + MMIO_OUT32(pSiS->IOBase, CS(4), ((y) | ((preset) << 16))); + +#define sis310SetCursorAddress(address)\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0xFFF00000; \ + temp |= address; \ + MMIO_OUT32(pSiS->IOBase,CS(0),temp); \ + } + +#define sis310SetCursorPatternSelect(pat_id)\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(0)); \ + temp &= 0xF0FFFFFF; \ + temp |= (pat_id) << 24; \ + MMIO_OUT32(pSiS->IOBase,CS(0),temp); \ + } + +/* 310/325/330 series CRT2 */ + +/* 80000000 = RGB(1) - MONO(0) + * 40000000 = enable(1) - disable(0) + * 20000000 = 32(1) / 16(1) bit RGB + * 10000000 = "ghost"(1) - Alpha Blend(0) ? + */ + +#define sis301GetCursorStatus310 \ + MMIO_IN32(pSiS->IOBase, CS(8)) & 0x40000000; + +#define sis301SetCursorStatus310(status) \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0xbfffffff; \ + temp |= status; \ + MMIO_OUT32(pSiS->IOBase, CS(8), temp); \ + } + +#define sis301EnableHWCursor310()\ + { \ + unsigned long temp, temp1, temp2; \ + temp1 = MMIO_IN32(pSiS->IOBase, CS(11)); \ + temp2 = MMIO_IN32(pSiS->IOBase, CS(12)); \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0x0fffffff; \ + temp |= 0x40000000; \ + MMIO_OUT32(pSiS->IOBase, CS(8), temp); \ + MMIO_OUT32(pSiS->IOBase, CS(11), temp1); \ + MMIO_OUT32(pSiS->IOBase, CS(12), temp2); \ + } + +#define sis301EnableHWARGBCursor310()\ + { \ + unsigned long temp, temp1, temp2; \ + temp1 = MMIO_IN32(pSiS->IOBase, CS(11)); \ + temp2 = MMIO_IN32(pSiS->IOBase, CS(12)); \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0x0FFFFFFF; \ + temp |= 0xE0000000; \ + MMIO_OUT32(pSiS->IOBase, CS(8), temp); \ + MMIO_OUT32(pSiS->IOBase, CS(11), temp1); \ + MMIO_OUT32(pSiS->IOBase, CS(12), temp2); \ + } + +#define sis301SwitchToRGBCursor310() \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0xBFFFFFFF; \ + temp |= 0xA0000000; \ + MMIO_OUT32(pSiS->IOBase, CS(8), temp); \ + } + +#define sis301SwitchToMONOCursor310() \ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0x4fffffff; \ + MMIO_OUT32(pSiS->IOBase, CS(8), temp); \ + } + +#define sis301DisableHWCursor310()\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0xBFFFFFFF; \ + MMIO_OUT32(pSiS->IOBase, CS(8), temp); \ + } + +#define sis301SetCursorBGColor310(color)\ + MMIO_OUT32(pSiS->IOBase, CS(9), (color)); +#define sis301SetCursorFGColor310(color)\ + MMIO_OUT32(pSiS->IOBase, CS(10), (color)); + +#define sis301SetCursorPositionX310(x,preset)\ + MMIO_OUT32(pSiS->IOBase, CS(11), ((x) | ((preset) << 16))); +#define sis301SetCursorPositionY310(y,preset)\ + MMIO_OUT32(pSiS->IOBase, CS(12), ((y) | ((preset) << 16))); + +#define sis301SetCursorAddress310(address)\ + { \ + unsigned long temp; \ + if(pSiS->sishw_ext.jChipType == SIS_315H) { \ + if(address & 0x10000) { \ + address &= ~0x10000; \ + orSISIDXREG(SISSR, 0x37, 0x80); \ + } else { \ + andSISIDXREG(SISSR, 0x37, 0x7f); \ + } \ + } \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0xFFF00000; \ + temp |= address; \ + MMIO_OUT32(pSiS->IOBase,CS(8),temp); \ + } + +#define sis301SetCursorPatternSelect310(pat_id)\ + { \ + unsigned long temp; \ + temp = MMIO_IN32(pSiS->IOBase, CS(8)); \ + temp &= 0xF0FFFFFF; \ + temp |= (pat_id) << 24; \ + MMIO_OUT32(pSiS->IOBase,CS(8),temp); \ + } + diff --git a/src/sis_dac.c b/src/sis_dac.c new file mode 100644 index 0000000..0ce8e74 --- /dev/null +++ b/src/sis_dac.c @@ -0,0 +1,2148 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_dac.c,v 1.30 2003/02/05 17:53:22 eich Exp $ */ +/* + * Copyright 1998,1999 by Alan Hourihane, Wigan, England. + * Parts Copyright 2001, 2002 by Thomas Winischhofer, Vienna, Austria. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the provider not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The provider makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE PROVIDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE PROVIDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane <alanh@fairlite.demon.co.uk> + * Mike Chapman <mike@paranoia.com>, + * Juanjo Santamarta <santamarta@ctv.es>, + * Mitani Hiroshi <hmitani@drl.mei.co.jp> + * David Thomas <davtom@dream.org.uk>. + * Thomas Winischhofer <thomas@winischhofer.net> + */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Version.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "xf86DDC.h" + +#include "sis.h" +#include "sis_dac.h" +#include "sis_regs.h" +#include "sis_vb.h" + +static void SiSSave(ScrnInfoPtr pScrn, SISRegPtr sisReg); +static void SiSRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg); + +static void SiS300Save(ScrnInfoPtr pScrn, SISRegPtr sisReg); +static void SiS310Save(ScrnInfoPtr pScrn, SISRegPtr sisReg); +static void SiS301Save(ScrnInfoPtr pScrn, SISRegPtr sisReg); +static void SiS301BSave(ScrnInfoPtr pScrn, SISRegPtr sisReg); +static void SiSLVDSChrontelSave(ScrnInfoPtr pScrn, SISRegPtr sisReg); +static void SiS300Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg); +static void SiS310Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg); +static void SiS301Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg); +static void SiS301BRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg); +static void SiSLVDSChrontelRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg); +static void SiS301LoadPalette(ScrnInfoPtr pScrn, int numColors, + int *indicies, LOCO *colors, VisualPtr pVisual); +static void SiSThreshold(ScrnInfoPtr pScrn, DisplayModePtr mode, + unsigned short *Low, unsigned short *High); +static void SetBlock(CARD16 port, CARD8 from, CARD8 to, CARD8 *DataPtr); +#if 0 +Bool SiSI2CInit(ScrnInfoPtr pScrn); +#endif + +static const unsigned short ch700xidx[] = { + 0x00,0x07,0x08,0x0a,0x0b,0x04,0x09,0x20,0x21,0x18,0x19,0x1a, + 0x1b,0x1c,0x1d,0x1e,0x1f, /* 0x0e, - TW: Don't save the power register */ + 0x01,0x03,0x06,0x0d,0x11,0x13,0x14,0x15,0x17,0x22,0x23,0x24 + }; + +static const unsigned short ch701xidx[] = { + 0x1c,0x5f,0x64,0x6f,0x70,0x71,0x72,0x73,0x74,0x76,0x78,0x7d, + 0x67,0x68,0x69,0x6a,0x6b,0x1e,0x00,0x01,0x02,0x04,0x03,0x05, + 0x06,0x07,0x08,0x15,0x1f,0x0c,0x0d,0x0e,0x0f,0x10 + }; + +int SiS_compute_vclk( + int Clock, + int *out_n, + int *out_dn, + int *out_div, + int *out_sbit, + int *out_scale) +{ + float f,x,y,t, error, min_error; + int n, dn, best_n=0, best_dn=0; + + /* + * Rules + * + * VCLK = 14.318 * (Divider/Post Scalar) * (Numerator/DeNumerator) + * Factor = (Divider/Post Scalar) + * Divider is 1 or 2 + * Post Scalar is 1, 2, 3, 4, 6 or 8 + * Numberator ranged from 1 to 128 + * DeNumerator ranged from 1 to 32 + * a. VCO = VCLK/Factor, suggest range is 150 to 250 Mhz + * b. Post Scalar selected from 1, 2, 4 or 8 first. + * c. DeNumerator selected from 2. + * + * According to rule a and b, the VCO ranges that can be scaled by + * rule b are: + * 150 - 250 (Factor = 1) + * 75 - 125 (Factor = 2) + * 37.5 - 62.5 (Factor = 4) + * 18.75 - 31.25 (Factor = 8) + * + * The following ranges use Post Scalar 3 or 6: + * 125 - 150 (Factor = 1.5) + * 62.5 - 75 (Factor = 3) + * 31.25 - 37.5 (Factor = 6) + * + * Steps: + * 1. divide the Clock by 2 until the Clock is less or equal to 31.25. + * 2. if the divided Clock is range from 18.25 to 31.25, than + * the Factor is 1, 2, 4 or 8. + * 3. if the divided Clock is range from 15.625 to 18.25, than + * the Factor is 1.5, 3 or 6. + * 4. select the Numberator and DeNumberator with minimum deviation. + * + * ** this function can select VCLK ranged from 18.75 to 250 Mhz + */ + f = (float) Clock; + f /= 1000.0; + if ((f > 250.0) || (f < 18.75)) + return 0; + + min_error = f; + y = 1.0; + x = f; + while (x > 31.25) { + y *= 2.0; + x /= 2.0; + } + if (x >= 18.25) { + x *= 8.0; + y = 8.0 / y; + } else if (x >= 15.625) { + x *= 12.0; + y = 12.0 / y; + } + + t = y; + if (t == (float) 1.5) { + *out_div = 2; + t *= 2.0; + } else { + *out_div = 1; + } + if (t > (float) 4.0) { + *out_sbit = 1; + t /= 2.0; + } else { + *out_sbit = 0; + } + + *out_scale = (int) t; + + for (dn=2;dn<=32;dn++) { + for (n=1;n<=128;n++) { + error = x; + error -= ((float) 14.318 * (float) n / (float) dn); + if (error < (float) 0) + error = -error; + if (error < min_error) { + min_error = error; + best_n = n; + best_dn = dn; + } + } + } + *out_n = best_n; + *out_dn = best_dn; + PDEBUG(ErrorF("SiS_compute_vclk: Clock=%d, n=%d, dn=%d, div=%d, sbit=%d," + " scale=%d\n", Clock, best_n, best_dn, *out_div, + *out_sbit, *out_scale)); + return 1; +} + + +void +SiSCalcClock(ScrnInfoPtr pScrn, int clock, int max_VLD, unsigned int *vclk) +{ + SISPtr pSiS = SISPTR(pScrn); + int M, N, P , PSN, VLD , PSNx ; + int bestM=0, bestN=0, bestP=0, bestPSN=0, bestVLD=0; + double bestError, abest = 42.0, bestFout; + double target; + double Fvco, Fout; + double error, aerror; + + /* + * fd = fref*(Numerator/Denumerator)*(Divider/PostScaler) + * + * M = Numerator [1:128] + * N = DeNumerator [1:32] + * VLD = Divider (Vco Loop Divider) : divide by 1, 2 + * P = Post Scaler : divide by 1, 2, 3, 4 + * PSN = Pre Scaler (Reference Divisor Select) + * + * result in vclk[] + */ +#define Midx 0 +#define Nidx 1 +#define VLDidx 2 +#define Pidx 3 +#define PSNidx 4 +#define Fref 14318180 +/* stability constraints for internal VCO -- MAX_VCO also determines + * the maximum Video pixel clock */ +#define MIN_VCO Fref +#define MAX_VCO 135000000 +#define MAX_VCO_5597 353000000 +#define MAX_PSN 0 /* no pre scaler for this chip */ +#define TOLERANCE 0.01 /* search smallest M and N in this tolerance */ + + int M_min = 2; + int M_max = 128; + +/* abest=10000.0; */ + + target = clock * 1000; + + if (pSiS->Chipset == PCI_CHIP_SIS5597 || pSiS->Chipset == PCI_CHIP_SIS6326){ + int low_N = 2; + int high_N = 5; + + PSN = 1; + P = 1; + if (target < MAX_VCO_5597 / 2) + P = 2; + if (target < MAX_VCO_5597 / 3) + P = 3; + if (target < MAX_VCO_5597 / 4) + P = 4; + if (target < MAX_VCO_5597 / 6) + P = 6; + if (target < MAX_VCO_5597 / 8) + P = 8; + + Fvco = P * target; + + for (N = low_N; N <= high_N; N++){ + double M_desired = Fvco / Fref * N; + if (M_desired > M_max * max_VLD) + continue; + + if ( M_desired > M_max ) { + M = M_desired / 2 + 0.5; + VLD = 2; + } else { + M = Fvco / Fref * N + 0.5; + VLD = 1; + } + + Fout = (double)Fref * (M * VLD)/(N * P); + + error = (target - Fout) / target; + aerror = (error < 0) ? -error : error; +/* if (aerror < abest && abest > TOLERANCE) */ + if (aerror < abest) { + abest = aerror; + bestError = error; + bestM = M; + bestN = N; + bestP = P; + bestPSN = PSN; + bestVLD = VLD; + bestFout = Fout; + } + } + } + else { + for (PSNx = 0; PSNx <= MAX_PSN ; PSNx++) { + int low_N, high_N; + double FrefVLDPSN; + + PSN = !PSNx ? 1 : 4; + + low_N = 2; + high_N = 32; + + for ( VLD = 1 ; VLD <= max_VLD ; VLD++ ) { + + FrefVLDPSN = (double)Fref * VLD / PSN; + for (N = low_N; N <= high_N; N++) { + double tmp = FrefVLDPSN / N; + + for (P = 1; P <= 4; P++) { + double Fvco_desired = target * ( P ); + double M_desired = Fvco_desired / tmp; + + /* Which way will M_desired be rounded? + * Do all three just to be safe. + */ + int M_low = M_desired - 1; + int M_hi = M_desired + 1; + + if (M_hi < M_min || M_low > M_max) + continue; + + if (M_low < M_min) + M_low = M_min; + if (M_hi > M_max) + M_hi = M_max; + + for (M = M_low; M <= M_hi; M++) { + Fvco = tmp * M; + if (Fvco <= MIN_VCO) + continue; + if (Fvco > MAX_VCO) + break; + + Fout = Fvco / ( P ); + + error = (target - Fout) / target; + aerror = (error < 0) ? -error : error; + if (aerror < abest) { + abest = aerror; + bestError = error; + bestM = M; + bestN = N; + bestP = P; + bestPSN = PSN; + bestVLD = VLD; + bestFout = Fout; + } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,3, + "Freq. selected: %.2f MHz, M=%d, N=%d, VLD=%d, P=%d, PSN=%d\n", + (float)(clock / 1000.), M, N, P, VLD, PSN); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,3, + "Freq. set: %.2f MHz\n", Fout / 1.0e6); + } + } + } + } + } + } + + vclk[Midx] = bestM; + vclk[Nidx] = bestN; + vclk[VLDidx] = bestVLD; + vclk[Pidx] = bestP; + vclk[PSNidx] = bestPSN; + + PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Freq. selected: %.2f MHz, M=%d, N=%d, VLD=%d, P=%d, PSN=%d\n", + (float)(clock / 1000.), vclk[Midx], vclk[Nidx], vclk[VLDidx], + vclk[Pidx], vclk[PSNidx])); + PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Freq. set: %.2f MHz\n", bestFout / 1.0e6)); + PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "VCO Freq.: %.2f MHz\n", bestFout*bestP / 1.0e6)); +} + + +static void +SiSSave(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + int i,max; + + PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "SiSSave(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n")); + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + switch (pSiS->Chipset) { + case PCI_CHIP_SIS5597: + max=0x3C; + break; + case PCI_CHIP_SIS6326: + case PCI_CHIP_SIS530: + max=0x3F; + break; + default: + max=0x37; + break; + } + + /* Save extended SR registers */ + for (i = 0x06; i <= max; i++) { + inSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]); +#ifdef DEBUG + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, + "XR%02X Contents - %02X \n", i, sisReg->sisRegs3C4[i]); +#endif +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "SR%02X - %02X \n", i,sisReg->sisRegs3C4[i]); +#endif + } + +#ifdef TWDEBUG + for (i = 0x00; i <= 0x3f; i++) { + inSISIDXREG(SISCR, i, max); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "CR%02X - %02X \n", i,max); + } +#endif + + /* Save lock (will not be restored in SiSRestore()!) */ + inSISIDXREG(SISCR, 0x80, sisReg->sisRegs3D4[0x80]); + + sisReg->sisRegs3C2 = inSISREG(SISMISCR); /* Misc */ + + /* TW: Save TV registers */ + if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { + outSISIDXREG(SISCR, 0x80, 0x86); + for(i = 0x00; i <= 0x44; i++) { + sisReg->sis6326tv[i] = SiS6326GetTVReg(pScrn, i); +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "VR%02X - %02X \n", i,sisReg->sis6326tv[i]); +#endif + } + } +} + +static void +SiSRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + int i,max; + unsigned char tmp; +#ifdef DEBUG + int temp; +#endif + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, + "SiSRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n"); + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + switch (pSiS->Chipset) { + case PCI_CHIP_SIS5597: + max = 0x3C; + break; + case PCI_CHIP_SIS6326: + case PCI_CHIP_SIS530: + max = 0x3F; + break; + default: + max = 0x37; + break; + } + + /* Disable TV on 6326 before restoring */ + if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { + outSISIDXREG(SISCR, 0x80, 0x86); + tmp = SiS6326GetTVReg(pScrn, 0x00); + tmp &= ~0x04; + SiS6326SetTVReg(pScrn, 0x00, tmp); + } + + /* Restore VCLKs */ +#if 0 /* TW: No, we didn't save SR2x-1 and SR2x-2! */ + andSISIDXREG(SISSR, 0x38, 0xfc); + inSISIDXREG(SISSR, 0x13, tmp); + tmp &= ~0x40; + tmp |= (sisReg->sisRegs3C4[0x13] & 0x40); + outSISIDXREG(SISSR, 0x13, tmp); + outSISIDXREG(SISSR, 0x2a, sisReg->sisRegs3C4[0x2a]); + outSISIDXREG(SISSR, 0x2b, sisReg->sisRegs3C4[0x2b]); + orSISIDXREG(SISSR, 0x38, 0x01); + inSISIDXREG(SISSR, 0x13, tmp); + tmp &= ~0x40; + tmp |= (sisReg->sisRegs3C4[0x13] & 0x40); + outSISIDXREG(SISSR, 0x13, tmp); + outSISIDXREG(SISSR, 0x2a, sisReg->sisRegs3C4[0x2a]); + outSISIDXREG(SISSR, 0x2b, sisReg->sisRegs3C4[0x2b]); + andSISIDXREG(SISSR, 0x38, 0xfc); + orSISIDXREG(SISSR, 0x38, 0x02); + inSISIDXREG(SISSR, 0x13, tmp); + tmp &= ~0x40; + tmp |= (sisReg->sisRegs3C4[0x13] & 0x40); + outSISIDXREG(SISSR, 0x13, tmp); + outSISIDXREG(SISSR, 0x2a, sisReg->sisRegs3C4[0x2a]); + outSISIDXREG(SISSR, 0x2b, sisReg->sisRegs3C4[0x2b]); + andSISIDXREG(SISSR, 0x38, 0xfc); +#endif + + /* Restore other extended SR registers */ + for (i = 0x06; i <= max; i++) { + if((i == 0x13) || (i == 0x2a) || (i == 0x2b)) continue; +#ifdef DEBUG + inSISIDXREG(SISSR, i, temp); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, + "SR%X Contents: %02X - ", i, temp); +#endif + outSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]); +#ifdef DEBUG + inSISIDXREG(SISSR, i, temp); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, + "Restored to %02X - Read: %02X\n", + sisReg->sisRegs3C4[i], temp); +#endif + } + + /* Now restore VCLK (with correct SR38 setting) */ + outSISIDXREG(SISSR, 0x13, sisReg->sisRegs3C4[0x13]); + outSISIDXREG(SISSR, 0x2a, sisReg->sisRegs3C4[0x2a]); + outSISIDXREG(SISSR, 0x2b, sisReg->sisRegs3C4[0x2b]); + + /* Misc */ + outSISREG(SISMISCW, sisReg->sisRegs3C2); + + /* MemClock needs this to take effect */ + outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ + usleep(10000); + outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ + + /* TW: Restore TV registers */ + pSiS->SiS6326Flags &= ~SIS6326_TVON; + if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { + for(i = 0x01; i <= 0x44; i++) { + SiS6326SetTVReg(pScrn, i, sisReg->sis6326tv[i]); +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "VR%02x restored to %02x\n", + i, sisReg->sis6326tv[i]); +#endif + } + tmp = SiS6326GetXXReg(pScrn, 0x13); + SiS6326SetXXReg(pScrn, 0x13, 0xfa); + tmp = SiS6326GetXXReg(pScrn, 0x14); + SiS6326SetXXReg(pScrn, 0x14, 0xc8); + if(!(sisReg->sisRegs3C4[0x0D] & 0x04)) { + tmp = SiS6326GetXXReg(pScrn, 0x13); + SiS6326SetXXReg(pScrn, 0x13, 0xf6); + tmp = SiS6326GetXXReg(pScrn, 0x14); + SiS6326SetXXReg(pScrn, 0x14, 0xbf); + } + if(sisReg->sis6326tv[0] & 0x04) pSiS->SiS6326Flags |= SIS6326_TVON; + } +} + +/* Save SiS 300 series register contents */ +static void +SiS300Save(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + int i; + + PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "SiS300Save(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n")); + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + /* Save SR registers */ + for (i = 0x00; i <= 0x3D; i++) { + inSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]); +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "SR%02X - %02X \n", i,sisReg->sisRegs3C4[i]); +#endif + } + + /* Save CR registers */ + for (i = 0x00; i < 0x40; i++) { + inSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]); +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "CR%02X Contents - %02X \n", i,sisReg->sisRegs3D4[i]); +#endif + } + + /* Save Misc register */ + sisReg->sisRegs3C2 = inSISREG(SISMISCR); + + /* Save FQBQ and GUI timer settings */ + if(pSiS->Chipset == PCI_CHIP_SIS630) { + sisReg->sisRegsPCI50 = pciReadLong(0x00000000, 0x50); + sisReg->sisRegsPCIA0 = pciReadLong(0x00000000, 0xA0); +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "PCI Config 50 = %lx\n", sisReg->sisRegsPCI50); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "PCI Config A0 = %lx\n", sisReg->sisRegsPCIA0); +#endif + } + + /* Save panel link/video bridge registers */ +#ifndef TWDEBUG + if(!pSiS->UseVESA) { +#endif + if (pSiS->VBFlags & (VB_LVDS|VB_CHRONTEL)) + (*pSiS->SiSSaveLVDSChrontel)(pScrn, sisReg); + if (pSiS->VBFlags & (VB_301|VB_303)) + (*pSiS->SiSSave2)(pScrn, sisReg); + if (pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) + (*pSiS->SiSSave3)(pScrn, sisReg); +#ifndef TWDEBUG + } +#endif + + /* Save Mode number */ +#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) + if(!(pSiS->UseVESA)) +#endif + pSiS->BIOSModeSave = SiS_GetSetModeID(pScrn,0xFF); + +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "BIOS mode ds:449 = 0x%x\n", pSiS->BIOSModeSave); +#endif +} + + +/* Restore SiS300 series register contents */ +static void +SiS300Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + int i,temp; + CARD32 temp1; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, + "SiS300Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n"); + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + /* TW: Wait for accelerator to finish on-going drawing operations. */ + inSISIDXREG(SISSR, 0x1E, temp); + if(temp & (0x40|0x10|0x02)) { + while ( (MMIO_IN16(pSiS->IOBase, 0x8242) & 0xE000) != 0xE000){}; + while ( (MMIO_IN16(pSiS->IOBase, 0x8242) & 0xE000) != 0xE000){}; + while ( (MMIO_IN16(pSiS->IOBase, 0x8242) & 0xE000) != 0xE000){}; + } + + if (!(pSiS->UseVESA)) { + if(pSiS->VBFlags & VB_LVDS) { + SiS_UnLockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + SiS_DisableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + } + } + + /* Restore extended CR registers */ + for(i = 0x19; i < 0x40; i++) { + outSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]); + } + + if(pSiS->Chipset != PCI_CHIP_SIS300) { + unsigned char val; + inSISIDXREG(SISCR, 0x1A, val); + if(val == sisReg->sisRegs3D4[0x19]) + outSISIDXREG(SISCR, 0x1A, sisReg->sisRegs3D4[0x19]); + inSISIDXREG(SISCR,0x19,val); + if(val == sisReg->sisRegs3D4[0x1A]) + outSISIDXREG(SISCR, 0x19, sisReg->sisRegs3D4[0x1A]); + } + + /* Set (and leave) PCI_IO_ENABLE on if accelerators are on */ + if(sisReg->sisRegs3C4[0x1e] & 0x50) { + sisReg->sisRegs3C4[0x20] |= 0x20; + outSISIDXREG(SISSR, 0x20, sisReg->sisRegs3C4[0x20]); + } + + /* TW: If TQ is switched on, don't switch it off ever again! + * Therefore, always restore registers with TQ enabled. + */ + if((!pSiS->NoAccel) && (pSiS->TurboQueue)) { + temp = (pScrn->videoRam/64) - 8; + sisReg->sisRegs3C4[0x26] = temp & 0xFF; + sisReg->sisRegs3C4[0x27] = ((temp >> 8) & 3) | 0xF0; + } + + /* Restore extended SR registers */ + for (i = 0x06; i <= 0x3D; i++) { + temp = sisReg->sisRegs3C4[i]; + if(!(pSiS->UseVESA)) { + if(pSiS->VBFlags & VB_LVDS) { + if(i == 0x11) { + inSISIDXREG(SISSR,0x11,temp); + temp &= 0x0c; + temp |= (sisReg->sisRegs3C4[i] & 0xf3); + } + } + } + outSISIDXREG(SISSR, i, temp); + } + + /* TW: Restore VCLK and ECLK */ + if(pSiS->VBFlags & (VB_LVDS | VB_301B)) { + outSISIDXREG(SISSR,0x31,0x20); + outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); + outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); + outSISIDXREG(SISSR,0x2d,0x80); + outSISIDXREG(SISSR,0x31,0x10); + outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); + outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); + outSISIDXREG(SISSR,0x2d,0x80); + } + outSISIDXREG(SISSR,0x31,0x00); + outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); + outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); + outSISIDXREG(SISSR,0x2d,0x80); + if(pSiS->VBFlags & (VB_LVDS | VB_301B)) { + outSISIDXREG(SISSR,0x31,0x20); + outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]); + outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]); + outSISIDXREG(SISSR,0x31,0x10); + outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]); + outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]); + outSISIDXREG(SISSR,0x31,0x00); + outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]); + outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]); + } + + /* Restore Misc register */ + outSISREG(SISMISCW, sisReg->sisRegs3C2); + + /* Restore FQBQ and GUI timer settings */ + if(pSiS->Chipset == PCI_CHIP_SIS630) { + temp1 = pciReadLong(0x00000000, 0x50); + if(pciReadLong(0x00000000, 0x00) == 0x06301039) { + temp1 &= 0xf0ffffff; + temp1 |= (sisReg->sisRegsPCI50 & ~0xf0ffffff); + } else { /* 730 */ + temp1 &= 0xfffff9ff; + temp1 |= (sisReg->sisRegsPCI50 & ~0xfffff9ff); + } + pciWriteLong(0x00000000, 0x50, temp1); + + temp1 = pciReadLong(0x00000000, 0xA0); + if(pciReadLong(0x00000000, 0x00) == 0x06301039) { + temp1 &= 0xf0ffffff; + temp1 |= (sisReg->sisRegsPCIA0 & ~0xf0ffffff); + } else { /* 730 */ + temp1 &= 0x00ffffff; + temp1 |= (sisReg->sisRegsPCIA0 & ~0x00ffffff); + } + pciWriteLong(0x00000000, 0xA0, temp1); + } + + /* Restore panel link/video bridge registers */ + if (!(pSiS->UseVESA)) { + if (pSiS->VBFlags & (VB_LVDS|VB_CHRONTEL)) + (*pSiS->SiSRestoreLVDSChrontel)(pScrn, sisReg); + if (pSiS->VBFlags & (VB_301|VB_303)) + (*pSiS->SiSRestore2)(pScrn, sisReg); + if (pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) + (*pSiS->SiSRestore3)(pScrn, sisReg); + } + + /* MemClock needs this to take effect */ + outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ + outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ + + /* Restore mode number */ +#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) + if(!(pSiS->UseVESA)) +#endif + SiS_GetSetModeID(pScrn,pSiS->BIOSModeSave); +} + +/* Save SiS310 series register contents */ +static void +SiS310Save(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + int i; + + PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "SiS310Save(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n")); + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + /* Save SR registers */ + for (i = 0x00; i <= 0x3F; i++) { + inSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]); +#ifdef DEBUG + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, + "SR%02X - %02X \n", i,sisReg->sisRegs3C4[i]); +#endif +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "SR%02X - %02X \n", i,sisReg->sisRegs3C4[i]); +#endif + } + + /* TW: Save command queue location */ + sisReg->sisMMIO85C0 = MMIO_IN32(pSiS->IOBase, 0x85C0); + + /* Save CR registers */ + for (i = 0x00; i <= 0x5f; i++) { + inSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]); +#ifdef DEBUG + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, + "CR%02X - %02X \n", i,sisReg->sisRegs3D4[i]); +#endif +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "CR%02X Contents - %02X \n", i,sisReg->sisRegs3D4[i]); +#endif + } + + /* Save Misc register */ + sisReg->sisRegs3C2 = inSISREG(SISMISCR); + + /* Save panel link/video bridge registers */ +#ifndef TWDEBUG + if (!pSiS->UseVESA) { +#endif + if (pSiS->VBFlags & (VB_LVDS|VB_CHRONTEL)) + (*pSiS->SiSSaveLVDSChrontel)(pScrn, sisReg); + if (pSiS->VBFlags & (VB_301|VB_303)) + (*pSiS->SiSSave2)(pScrn, sisReg); + if (pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) + (*pSiS->SiSSave3)(pScrn, sisReg); +#ifndef TWDEBUG + } +#endif + + /* Save mode number */ +#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) + if(!(pSiS->UseVESA)) +#endif + pSiS->BIOSModeSave = SiS_GetSetModeID(pScrn,0xFF); +} + +/* Restore SiS310 series register contents */ +static void +SiS310Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + int i,temp; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, + "SiS310Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg)\n"); + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + /* TW: Wait for accelerator to finish on-going drawing operations. */ + inSISIDXREG(SISSR, 0x1E, temp); + if (temp & (0x40|0x10|0x02)) { /* TW: 0x40 = 2D, 0x10 = 3D enabled*/ + while ( (MMIO_IN32(pSiS->IOBase, 0x85CC) & 0x80000000) != 0x80000000){}; + while ( (MMIO_IN32(pSiS->IOBase, 0x85CC) & 0x80000000) != 0x80000000){}; + while ( (MMIO_IN32(pSiS->IOBase, 0x85CC) & 0x80000000) != 0x80000000){}; + } + + /* Restore extended CR registers */ + for (i = 0x19; i < 0x5C; i++) { + outSISIDXREG(SISCR, i, sisReg->sisRegs3D4[i]); + } + + /* TW: Leave PCI_IO_ENABLE on if accelerators are on (Is this required?) */ + if (sisReg->sisRegs3C4[0x1e] & 0x50) { /*0x40=2D, 0x10=3D*/ + sisReg->sisRegs3C4[0x20] |= 0x20; + outSISIDXREG(SISSR, 0x20, sisReg->sisRegs3C4[0x20]); + } + + /* TW: We reset the command queue before restoring. + * This might be required because we never know what + * console driver (like the kernel framebuffer driver) + * or application is running and which queue mode it + * uses. + */ + outSISIDXREG(SISSR, 0x27, 0x1F); + outSISIDXREG(SISSR, 0x26, 0x01); + + /* Restore extended SR registers */ + for (i = 0x06; i <= 0x3F; i++) { +#ifdef DEBUG + inSISIDXREG(SISSR, i, temp); +#endif + outSISIDXREG(SISSR, i, sisReg->sisRegs3C4[i]); +#ifdef DEBUG + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, + "XR%X Contents %02X - ", i, temp); + inSISIDXREG(SISSR, i, temp); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, + "Restored to %02X - Read: %02X\n", + sisReg->sisRegs3C4[i], temp); +#endif + } + /* TW: Restore VCLK and ECLK */ + andSISIDXREG(SISSR,0x31,0xcf); + if(pSiS->VBFlags & VB_LVDS) { + orSISIDXREG(SISSR,0x31,0x20); + outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); + outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); + outSISIDXREG(SISSR,0x2d,0x80); + andSISIDXREG(SISSR,0x31,0xcf); + orSISIDXREG(SISSR,0x31,0x10); + outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); + outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); + outSISIDXREG(SISSR,0x2d,0x80); + andSISIDXREG(SISSR,0x31,0xcf); + outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); + outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); + outSISIDXREG(SISSR,0x2d,0x01); + outSISIDXREG(SISSR,0x31,0x20); + outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]); + outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]); + outSISIDXREG(SISSR,0x31,0x10); + outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]); + outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]); + outSISIDXREG(SISSR,0x31,0x00); + outSISIDXREG(SISSR,0x2e,sisReg->sisRegs3C4[0x2e]); + outSISIDXREG(SISSR,0x2f,sisReg->sisRegs3C4[0x2f]); + } else { + outSISIDXREG(SISSR,0x2b,sisReg->sisRegs3C4[0x2b]); + outSISIDXREG(SISSR,0x2c,sisReg->sisRegs3C4[0x2c]); + outSISIDXREG(SISSR,0x2d,0x01); + } + + /* TW: Initialize read/write pointer for command queue */ + MMIO_OUT32(pSiS->IOBase, 0x85C4, MMIO_IN32(pSiS->IOBase, 0x85C8)); + /* TW: Restore queue location */ + MMIO_OUT32(pSiS->IOBase, 0x85C0, sisReg->sisMMIO85C0); + + /* Restore Misc register */ + outSISREG(SISMISCW, sisReg->sisRegs3C2); + + /* Restore panel link/video bridge registers */ + if (!(pSiS->UseVESA)) { + if (pSiS->VBFlags & (VB_LVDS|VB_CHRONTEL)) + (*pSiS->SiSRestoreLVDSChrontel)(pScrn, sisReg); + if (pSiS->VBFlags & (VB_301|VB_303)) + (*pSiS->SiSRestore2)(pScrn, sisReg); + if (pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) + (*pSiS->SiSRestore3)(pScrn, sisReg); + } + + /* MemClock needs this to take effect */ + outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ + outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ + + /* Restore Mode number */ +#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) + if(!(pSiS->UseVESA)) +#endif + SiS_GetSetModeID(pScrn,pSiS->BIOSModeSave); +} + +/* Save SiS301 bridge register contents */ +static void +SiS301Save(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + int i; + int Part1max=0, Part2max=0, Part3max=0, Part4max=0; + + /* Highest register number to save/restore */ + switch (pSiS->VGAEngine) { + case SIS_300_VGA: + Part1max = 0x1d; + Part2max = 0x45; + Part3max = 0x3e; + Part4max = 0x1b; + break; + case SIS_315_VGA: + Part1max = 0x2e; /* 0x23, but we also need 2d-2e */ + Part2max = 0x45; + Part3max = 0x3e; + Part4max = 0x1b; + break; + } + + for (i=0; i<=Part1max; i++) { + inSISIDXREG(SISPART1, i, sisReg->VBPart1[i]); +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "301Save: Part1Port 0x%02x = 0x%02x\n", i, sisReg->VBPart1[i]); +#endif + } + for (i=0; i<=Part2max; i++) { + inSISIDXREG(SISPART2, i, sisReg->VBPart2[i]); +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "301Save: Part2Port 0x%02x = 0x%02x\n", i, sisReg->VBPart2[i]); +#endif + } + for (i=0; i<=Part3max; i++) { + inSISIDXREG(SISPART3, i, sisReg->VBPart3[i]); +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "301Save: Part3Port 0x%02x = 0x%02x\n", i, sisReg->VBPart3[i]); +#endif + } + for (i=0; i<=Part4max; i++) { + inSISIDXREG(SISPART4, i, sisReg->VBPart4[i]); +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "301Save: Part4Port 0x%02x = 0x%02x\n", i, sisReg->VBPart4[i]); +#endif + } + + sisReg->VBPart2[0] &= ~0x20; /* Disable VB Processor */ + sisReg->sisRegs3C4[0x32] &= ~0x20; /* Disable Lock Mode */ +} + +/* Restore SiS301 bridge register contents */ +static void +SiS301Restore(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + int Part1max=0, Part2max=0, Part3max=0, Part4max=0; + + /* Highest register number to save/restore */ + switch (pSiS->VGAEngine) { + case SIS_300_VGA: + Part1max = 0x1d; + Part2max = 0x45; + Part3max = 0x3e; + Part4max = 0x1b; + break; + case SIS_315_VGA: + Part1max = 0x23; + Part2max = 0x45; + Part3max = 0x3e; + Part4max = 0x1b; + break; + } + + SiS_DisableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + + SiS_UnLockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + + /* Pre-restore Part1 */ + outSISIDXREG(SISPART1, 0x04, 0x00); + outSISIDXREG(SISPART1, 0x05, 0x00); + outSISIDXREG(SISPART1, 0x06, 0x00); + outSISIDXREG(SISPART1, 0x00, sisReg->VBPart1[0]); + outSISIDXREG(SISPART1, 0x01, sisReg->VBPart1[1]); + + /* Pre-restore Part4 */ + outSISIDXREG(SISPART4, 0x0D, sisReg->VBPart4[0x0D]); + outSISIDXREG(SISPART4, 0x0C, sisReg->VBPart4[0x0C]); + + if (!(sisReg->sisRegs3D4[0x30] & 0x03) && + (sisReg->sisRegs3D4[0x31] & 0x20)) { /* disable CRT2 */ + SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + return; + } + + /* Restore Part1 */ + SetBlock(SISPART1, 0x02, Part1max, &(sisReg->VBPart1[0x02])); + switch (pSiS->VGAEngine) { + case SIS_300_VGA: + /* TW: Nothing special here. */ + break; + case SIS_315_VGA: + /* TW: Restore extra registers on 310 series */ + SetBlock(SISPART1, 0x2C, 0x2E, &(sisReg->VBPart1[0x2C])); + break; + } + + /* Restore Part2 */ + SetBlock(SISPART2, 0x00, Part2max, &(sisReg->VBPart2[0x00])); + + /* Restore Part3 */ + SetBlock(SISPART3, 0x00, Part3max, &(sisReg->VBPart3[0x00])); + + /* Restore Part4 */ + SetBlock(SISPART4, 0x0E, 0x11, &(sisReg->VBPart4[0x0E])); + SetBlock(SISPART4, 0x13, Part4max, &(sisReg->VBPart4[0x13])); + + /* Post-restore Part4 (CRT2VCLK) */ + outSISIDXREG(SISPART4, 0x0A, 0x01); + outSISIDXREG(SISPART4, 0x0B, sisReg->VBPart4[0x0B]); + outSISIDXREG(SISPART4, 0x0A, sisReg->VBPart4[0x0A]); + outSISIDXREG(SISPART4, 0x12, 0x00); + outSISIDXREG(SISPART4, 0x12, sisReg->VBPart4[0x12]); + + SiS_EnableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + SiS_DisplayOn(pSiS->SiS_Pr); + SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); +} + +/* Save SiS301B/302B/30xLV bridge register contents */ +static void +SiS301BSave(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + int i; + int Part1max=0, Part2max=0, Part3max=0, Part4max=0; + + switch (pSiS->VGAEngine) { + case SIS_300_VGA: + Part1max = 0x37; /* 0x1d, but we also need 2c-2e, 35-37 */ + Part2max = 0x4d; + Part3max = 0x3e; + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) + Part4max = 0x24; + else + Part4max = 0x23; + break; + case SIS_315_VGA: + Part1max = 0x37; /* 0x23, but we also need 2c-2e, 35-37 */ + Part2max = 0x4d; + Part3max = 0x3e; + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) + Part4max = 0x24; + else + Part4max = 0x23; + break; + } + + for (i=0; i<=Part1max; i++) { + inSISIDXREG(SISPART1, i, sisReg->VBPart1[i]); +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "301BSave: Part1Port 0x%02x = 0x%02x\n", i, sisReg->VBPart1[i]); +#endif + } + for (i=0; i<=Part2max; i++) { + inSISIDXREG(SISPART2, i, sisReg->VBPart2[i]); +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "301BSave: Part2Port 0x%02x = 0x%02x\n", i, sisReg->VBPart2[i]); +#endif + } + for (i=0; i<=Part3max; i++) { + inSISIDXREG(SISPART3, i, sisReg->VBPart3[i]); +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "301BSave: Part3Port 0x%02x = 0x%02x\n", i, sisReg->VBPart3[i]); +#endif + } + for (i=0; i<=Part4max; i++) { + inSISIDXREG(SISPART4, i, sisReg->VBPart4[i]); +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "301BSave: Part4Port 0x%02x = 0x%02x\n", i, sisReg->VBPart4[i]); +#endif + } + sisReg->VBPart2[0] &= ~0x20; /* Disable VB Processor */ + sisReg->sisRegs3C4[0x32] &= ~0x20; /* Disable Lock Mode */ +} + +/* Restore SiS301B/302B/301LV/302LV bridge register contents */ +static void +SiS301BRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + int Part1max=0, Part2max=0, Part3max=0, Part4max=0; + + switch (pSiS->VGAEngine) { + case SIS_300_VGA: + Part1max = 0x23; + Part2max = 0x4d; + Part3max = 0x3e; + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) + Part4max = 0x24; + else + Part4max = 0x22; + break; + case SIS_315_VGA: + Part1max = 0x23; + Part2max = 0x4d; + Part3max = 0x3e; + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) + Part4max = 0x24; + else + Part4max = 0x22; + break; + } + + SiS_DisableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + + SiS_UnLockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + + /* Pre-restore Part1 */ + outSISIDXREG(SISPART1, 0x04, 0x00); + outSISIDXREG(SISPART1, 0x05, 0x00); + outSISIDXREG(SISPART1, 0x06, 0x00); + outSISIDXREG(SISPART1, 0x00, sisReg->VBPart1[0x00]); + outSISIDXREG(SISPART1, 0x01, sisReg->VBPart1[0x01]); + /* Mode reg 0x01 became 0x2e on 310 series (0x01 still contains FIFO) */ + if(pSiS->VGAEngine == SIS_315_VGA) + outSISIDXREG(SISPART1, 0x2e, sisReg->VBPart1[0x2e]); + + /* Pre-restore Part4 */ + outSISIDXREG(SISPART4, 0x0D, sisReg->VBPart4[0x0D]); + outSISIDXREG(SISPART4, 0x0C, sisReg->VBPart4[0x0C]); + + if (!(sisReg->sisRegs3D4[0x30] & 0x03) && + (sisReg->sisRegs3D4[0x31] & 0x20)) { /* disable CRT2 */ + SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + return; + } + + /* Restore Part1 */ + SetBlock(SISPART1, 0x02, Part1max, &(sisReg->VBPart1[0x02])); + if(pSiS->VGAEngine == SIS_315_VGA) { + SetBlock(SISPART1, 0x2C, 0x2D, &(sisReg->VBPart1[0x2C])); + SetBlock(SISPART1, 0x35, 0x37, &(sisReg->VBPart1[0x35])); + } + + /* Restore Part2 */ + SetBlock(SISPART2, 0x00, Part2max, &(sisReg->VBPart2[0x00])); + + /* Restore Part3 */ + SetBlock(SISPART3, 0x00, Part3max, &(sisReg->VBPart3[0x00])); + + /* Restore Part4 */ + SetBlock(SISPART4, 0x0E, 0x11, &(sisReg->VBPart4[0x0E])); + SetBlock(SISPART4, 0x13, Part4max, &(sisReg->VBPart4[0x13])); + + /* Post-restore Part4 (CRT2VCLK) */ + outSISIDXREG(SISPART4, 0x0A, sisReg->VBPart4[0x0A]); + outSISIDXREG(SISPART4, 0x0B, sisReg->VBPart4[0x0B]); + outSISIDXREG(SISPART4, 0x12, 0x00); + outSISIDXREG(SISPART4, 0x12, sisReg->VBPart4[0x12]); + + SiS_EnableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + SiS_DisplayOn(pSiS->SiS_Pr); + SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); +} + +/* Save LVDS bridge (+ Chrontel) register contents */ +static void +SiSLVDSChrontelSave(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + int i; + + /* Save Part1 */ + for (i=0; i<0x46; i++) { + inSISIDXREG(SISPART1, i, sisReg->VBPart1[i]); +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "LVDSSave: Part1Port 0x%02x = 0x%02x\n", + i, sisReg->VBPart1[i]); +#endif + } + + /* Save Chrontel registers */ + if (pSiS->VBFlags & VB_CHRONTEL) { + if (pSiS->ChrontelType == CHRONTEL_700x) { + for (i=0; i<0x1D; i++) { + sisReg->ch70xx[i] = SiS_GetCH700x(pSiS->SiS_Pr, ch700xidx[i]); +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "LVDSSave: Chrontel 0x%02x = 0x%02x\n", + ch700xidx[i], sisReg->ch70xx[i]); +#endif + + } + } else { + for (i=0; i<34; i++) { + sisReg->ch70xx[i] = SiS_GetCH701x(pSiS->SiS_Pr, ch701xidx[i]); + } + } + } + + sisReg->sisRegs3C4[0x32] &= ~0x20; /* Disable Lock Mode */ +} + +/* Restore LVDS bridge (+ Chrontel) register contents */ +static void +SiSLVDSChrontelRestore(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + int i; + USHORT wtemp; + + SiS_DisableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + if(pSiS->sishw_ext.jChipType == SIS_730) { + outSISIDXREG(SISPART1, 0x00, 0x80); + } + + SiS_UnLockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + + if(pSiS->VBFlags & VB_CHRONTEL) { + /* Restore Chrontel registers */ + if(pSiS->ChrontelType == CHRONTEL_700x) { + for(i=0; i<0x11; i++) { + wtemp = ((sisReg->ch70xx[i]) << 8) | (ch700xidx[i] & 0x00FF); + SiS_SetCH700x(pSiS->SiS_Pr, wtemp); + } + } else { + for(i=0; i<34; i++) { + wtemp = ((sisReg->ch70xx[i]) << 8) | (ch701xidx[i] & 0x00FF); + SiS_SetCH701x(pSiS->SiS_Pr, wtemp); + } + } + } + + /* pre-restore Part1 */ + outSISIDXREG(SISPART1, 0x04, 0x00); + outSISIDXREG(SISPART1, 0x05, 0x00); + outSISIDXREG(SISPART1, 0x06, 0x00); + outSISIDXREG(SISPART1, 0x00, sisReg->VBPart1[0]); + if(pSiS->VGAEngine == SIS_300_VGA) { + outSISIDXREG(SISPART1, 0x01, (sisReg->VBPart1[1] | 0x80)); + } else { + outSISIDXREG(SISPART1, 0x01, sisReg->VBPart1[1]); + } + + if (!(sisReg->sisRegs3D4[0x30] & 0x03) && + (sisReg->sisRegs3D4[0x31] & 0x20)) { /* disable CRT2 */ + SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + return; + } + + /* Restore Part1 */ + if(pSiS->VGAEngine == SIS_300_VGA) { + outSISIDXREG(SISPART1, 0x02, (sisReg->VBPart1[2] | 0x40)); + } else { + outSISIDXREG(SISPART1, 0x02, sisReg->VBPart1[2]); + } + SetBlock(SISPART1, 0x03, 0x23, &(sisReg->VBPart1[0x03])); + if(pSiS->VGAEngine == SIS_315_VGA) { + SetBlock(SISPART1, 0x2C, 0x2E, &(sisReg->VBPart1[0x2C])); + SetBlock(SISPART1, 0x35, 0x37, &(sisReg->VBPart1[0x35])); /* Panel Link Scaler */ + } + + /* TW: For 550 DSTN registers */ + if (pSiS->DSTN) { + SetBlock(SISPART1, 0x25, 0x2E, &(sisReg->VBPart1[0x25])); + SetBlock(SISPART1, 0x30, 0x45, &(sisReg->VBPart1[0x30])); + } + + SiS_EnableBridge(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + SiS_DisplayOn(pSiS->SiS_Pr); + SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); +} + +/* TW: Restore output selection registers (CR30, 31, 33, 35/38) */ +void +SiSRestoreBridge(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char temp = 0; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + outSISIDXREG(SISCR, 0x30, sisReg->sisRegs3D4[0x30]); + outSISIDXREG(SISCR, 0x31, sisReg->sisRegs3D4[0x31]); + outSISIDXREG(SISCR, 0x33, sisReg->sisRegs3D4[0x33]); + if(pSiS->Chipset != PCI_CHIP_SIS300) { + switch(pSiS->VGAEngine) { + case SIS_300_VGA: temp = 0x35; break; + case SIS_315_VGA: temp = 0x38; break; + } + if(temp) { + outSISIDXREG(SISCR, temp, sisReg->sisRegs3D4[temp]); + } + } +} + +unsigned int +SiSddc1Read(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char temp; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + /* Wait until vertical retrace is in progress. */ + while(inSISREG(SISINPSTAT) & 0x08); + while(!(inSISREG(SISINPSTAT) & 0x08)); + + /* Get the result */ + inSISIDXREG(SISSR, 0x11, temp); + + return((temp & 0x02)>>1); +} + +#if 0 /* TW: I2C functions not in use */ +/* +static void +SiS_I2CGetBits(I2CBusPtr b, int *clock, int *data) +{ + SISPtr pSiS = SISPTR(xf86Screens[b->scrnIndex]); + unsigned char val; + + outSISIDXREG(SISSR, 0x05, 0x86); + inSISIDXREG(SISSR, pSiS->SiS_DDC2_Index, val); + *clock = (val & pSiS->SiS_DDC2_Clk) != 0; + *data = (val & pSiS->SiS_DDC2_Data) != 0; +} + +static void +SiS_I2CPutBits(I2CBusPtr b, int clock, int data) +{ + SISPtr pSiS = SISPTR(xf86Screens[b->scrnIndex]); + unsigned char temp; + + outSISIDXREG(SISSR, 0x05, 0x86); + inSISIDXREG(SISSR, pSiS->SiS_DDC2_Index, temp); + + temp &= ~(pSiS->SiS_DDC2_Clk | pSiS->SiS_DDC2_Data); + + temp |= ((clock ? pSiS->SiS_DDC2_Clk : 0) | (data ? pSiS->SiS_DDC2_Data : 0)); + + outSISIDXREG(SISSR, pSiS->SiS_DDC2_Index, temp); +} +*/ + +static Bool +SiS_I2CAddress(I2CDevPtr d, I2CSlaveAddr addr) +{ + I2CBusPtr b = d->pI2CBus; + SISPtr pSiS = SISPTR(xf86Screens[b->scrnIndex]); + SiS_SetSwitchDDC2(pSiS->SiS_Pr); + return(SiS_I2C_Address(pSiS->SiS_Pr, addr)); +} + +static void +SiS_I2CStop(I2CDevPtr d) +{ + I2CBusPtr b = d->pI2CBus; + SISPtr pSiS = SISPTR(xf86Screens[b->scrnIndex]); + SiS_I2C_Stop(pSiS->SiS_Pr); +} + +static Bool +SiS_I2CGetByte(I2CDevPtr d, I2CByte *data, Bool last) +{ + I2CBusPtr b = d->pI2CBus; + SISPtr pSiS = SISPTR(xf86Screens[b->scrnIndex]); + USHORT temp = SiS_I2C_GetByte(pSiS->SiS_Pr); + if(temp == 0xffff) return FALSE; + return TRUE; +} + +static Bool +SiS_I2CPutByte(I2CDevPtr d, I2CByte data) +{ + I2CBusPtr b = d->pI2CBus; + SISPtr pSiS = SISPTR(xf86Screens[b->scrnIndex]); + return(SiS_I2C_PutByte(pSiS->SiS_Pr, (USHORT)data)); +} + +Bool +SiSI2CInit(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + I2CBusPtr I2CPtr; + USHORT temp, i; + unsigned char buffer[256]; + xf86MonPtr pMonitor; + + I2CPtr = xf86CreateI2CBusRec(); + if(!I2CPtr) return FALSE; + + pSiS->I2C = I2CPtr; + + I2CPtr->BusName = "DDC"; + I2CPtr->scrnIndex = pScrn->scrnIndex; +/* + I2CPtr->I2CPutBits = SiS_I2CPutBits; + I2CPtr->I2CGetBits = SiS_I2CGetBits; +*/ + I2CPtr->I2CPutByte = SiS_I2CPutByte; + I2CPtr->I2CGetByte = SiS_I2CGetByte; + I2CPtr->I2CAddress = SiS_I2CAddress; + I2CPtr->I2CStop = SiS_I2CStop; + I2CPtr->AcknTimeout = 30; + + + + pSiS->SiS_Pr->SiS_DDC_Index = pSiS->SiS_DDC2_Index; + pSiS->SiS_Pr->SiS_DDC_Data = pSiS->SiS_DDC2_Data; + pSiS->SiS_Pr->SiS_DDC_Clk = pSiS->SiS_DDC2_Clk; + pSiS->SiS_Pr->SiS_DDC_DataShift = 0x00; + + if (!xf86I2CBusInit(I2CPtr)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not create I2C bus record\n"); + return FALSE; + } + + return TRUE; +} +#endif + +#if 0 /* TW: The following function should take a threshold value + * from predefined tables. This is only needed on some + * 530 boards, which have an ESS sound device on-board. + * However, I don't know how to calculate the index to + * be submitted to this function. + */ +unsigned short +SiS_CalcSpecial530Threshold(ScrnInfoPtr pScrn, DisplayModePtr mode, int index) +{ + SISPtr pSiS = SISPTR(pScrn); + static const unsigned char t640x480[3][24] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,A9, /* b4 - 9d - depth 8 */ + 0, 0,11,14,14, 0, 0, 0, 0, 0, 0,9D }, + { 0, 0, 0, 0, 0,12,15, 0, 0, 0,92,91, /* 9c - 85 - depth 16 */ + 0,31,31,31,31, 0, 0, 0, 0, 0, 0,85 }, + { 0, 0, 0, 0, 0,17,22,25, 0, 0, 0,79, /* 84 - ? - depth 32 */ + 0,31,31, 0, 0, 0, 0, 0, 0, 0, 0,6d } + } + static const unsigned char t800x600[3][24] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,61, + 0,18,25,30,27,31,31,31, 0, 0, 0, 0 }, + {55, 0, 0, 0, 0, 9,10,15,18,19, 0, 0, + ... to be continued + + depthindex = (pSiS->CurrentLayout.bitsPerPixel + 1) >> 3; + if(depthindex == 3) return(0); + if(depthindex == 4) depthindex--; + depthindex--; + + switch(mode->HDisplay) { + case 640: + if(mode->VDisplay == 480) { + return(t640x480[depthindex][index]; + } else return(0); + case 800: + if(mode->VDisplay == 600) { + return(t800x600[depthindex][index]; + } else return(0); + case 1024: + if(mode->VDisplay == 768) { + return(t1024x768[depthindex][index]; + } else return(0); + case 1280: + if(mode->VDisplay == 1024) { + return(t1280x1024[depthindex][index]; + } else return(0); + case 1600: + if(mode->VDisplay == 1200) { + return(t1600x1200[depthindex][index]; + } else return(0); + default: return(0); + } +} +#endif + +/* TW: Stub */ +static void +SiSThreshold(ScrnInfoPtr pScrn, DisplayModePtr mode, + unsigned short *Low, unsigned short *High) +{ + return; +} + + +/* Auxiliary function to find real memory clock (in Khz) */ +/* TW: Not for 530/620 if UMA (on these, the mclk is stored in SR10) */ +int +SiSMclk(SISPtr pSiS) +{ + int mclk; + unsigned char Num, Denum, Base; + + switch (pSiS->Chipset) { + case PCI_CHIP_SIS5597: + case PCI_CHIP_SIS6326: + case PCI_CHIP_SIS530: + /* Numerator */ + inSISIDXREG(SISSR, MemClock0, Num); + mclk = 14318 * ((Num & 0x7f) + 1); + + /* Denumerator */ + inSISIDXREG(SISSR, MemClock1, Denum); + mclk = mclk / ((Denum & 0x1f) + 1); + + /* Divider. Doesn't seem to work for mclk in older cards */ + if((Num & 0x80) != 0) mclk *= 2; + + /* Post-scaler. Values' meaning depends on SR13 bit 7 */ + inSISIDXREG(SISSR, ClockBase, Base); + if((Base & 0x80) == 0) { + mclk = mclk / (((Denum & 0x60) >> 5) + 1); + } else { + /* Values 00 and 01 are reserved */ + if ((Denum & 0x60) == 0x40) mclk /= 6; + if ((Denum & 0x60) == 0x60) mclk /= 8; + } + break; + case PCI_CHIP_SIS300: + case PCI_CHIP_SIS540: + case PCI_CHIP_SIS630: + case PCI_CHIP_SIS550: + case PCI_CHIP_SIS650: + case PCI_CHIP_SIS315: + case PCI_CHIP_SIS315H: + case PCI_CHIP_SIS315PRO: + case PCI_CHIP_SIS330: + /* Numerator */ + inSISIDXREG(SISSR, 0x28, Num); + mclk = 14318 * ((Num & 0x7f) + 1); + + /* Denumerator */ + inSISIDXREG(SISSR, 0x29, Denum); + mclk = mclk / ((Denum & 0x1f) + 1); + + /* Divider */ + if((Num & 0x80) != 0) mclk *= 2; + + /* Post-Scaler */ + if((Denum & 0x80) == 0) { + mclk = mclk / (((Denum & 0x60) >> 5) + 1); + } else { + mclk = mclk / ((((Denum & 0x60) >> 5) + 1) * 2); + } + break; + default: + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR, + "Internal error: SiSMClk() called with invalid chipset (0x%x)\n", + pSiS->Chipset); + mclk = 0; + } + + return(mclk); +} + +/* TW: This estimates the CRT2 clock we are going to use. + * The total bandwidth is to be reduced by the value + * returned here in order to get an idea of the maximum + * dotclock left for CRT1. + * Since we don't know yet, what mode the user chose, + * we return the maximum dotclock used by + * - either the LCD attached, or + * - TV + * For VGA2, we share the bandwith equally. + */ +static int +SiSEstimateCRT2Clock(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + + if(pSiS->VBFlags & CRT2_LCD) { + if(pSiS->VBLCDFlags & (VB_LCD_320x480 | VB_LCD_800x600 | VB_LCD_640x480)) + return 40000; + else if(pSiS->VBLCDFlags & (VB_LCD_1024x768 | VB_LCD_1024x600)) + return 65000; + else if(pSiS->VBLCDFlags & (VB_LCD_1152x768 | VB_LCD_1280x1024 | VB_LCD_1280x960)) + return 108000; + else if(pSiS->VBLCDFlags & VB_LCD_1400x1050) + return 122000; + else if(pSiS->VBLCDFlags & VB_LCD_1600x1200) + return 162000; + else + return 108000; + } else if(pSiS->VBFlags & CRT2_TV) { + if(pSiS->VBFlags & VB_CHRONTEL) { + switch(pSiS->VGAEngine) { + case SIS_300_VGA: + return 50000; + case SIS_315_VGA: + default: + return 70000; + } + } else if(pSiS->VBFlags & VB_SISBRIDGE) { + return 70000; + } + } + + return 0; +} + +/* Calculate the maximum dotclock */ +int SiSMemBandWidth(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + int bus = pSiS->BusWidth; + int mclk = pSiS->MemClock; + int bpp = pSiS->CurrentLayout.bitsPerPixel; + int bytesperpixel = (bpp + 7) / 8; + float magic=0.0, total, crt2used; + int crt2clock, max=0; + const float magic300[4] = { 1.2, 1.368421, 2.263158, 1.2}; + const float magic630[4] = { 1.441177, 1.441177, 2.588235, 1.441177 }; + const float magic315[4] = { 1.2, 1.368421, 1.368421, 1.2 }; + const float magic550[4] = { 1.441177, 1.441177, 2.588235, 1.441177 }; + + switch (pSiS->Chipset) { + + case PCI_CHIP_SIS5597: + total = ((mclk * (bus / 8)) * 0.7) / bytesperpixel; + if(total > 135000) total = 135000; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Maximum pixel clock at %d bpp is %g MHz\n", + bpp, total/1000); + return(int)(total); + + case PCI_CHIP_SIS6326: + total = ((mclk * (bus / 8)) * 0.7) / bytesperpixel; + if(total > 175500) total = 175500; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Maximum pixel clock at %d bpp is %g MHz\n", + bpp, total/1000); + return(int)(total); + + case PCI_CHIP_SIS530: + total = ((mclk * (bus / 8)) * 0.7) / bytesperpixel; + if(total > 230000) total = 230000; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Maximum pixel clock at %d bpp is %g MHz\n", + bpp, total/1000); + return(int)(total); + + case PCI_CHIP_SIS300: + case PCI_CHIP_SIS540: + case PCI_CHIP_SIS630: + case PCI_CHIP_SIS315: + case PCI_CHIP_SIS315H: + case PCI_CHIP_SIS315PRO: + case PCI_CHIP_SIS550: + case PCI_CHIP_SIS650: + case PCI_CHIP_SIS330: + switch(pSiS->Chipset) { + case PCI_CHIP_SIS300: + magic = magic300[bus/64]; + max = 540000; + break; + case PCI_CHIP_SIS540: + case PCI_CHIP_SIS630: + magic = magic630[bus/64]; + max = 540000; + break; + case PCI_CHIP_SIS315: + case PCI_CHIP_SIS315H: + case PCI_CHIP_SIS315PRO: + case PCI_CHIP_SIS330: + magic = magic315[bus/64]; + max = 780000; + break; + case PCI_CHIP_SIS550: + case PCI_CHIP_SIS650: + magic = magic550[bus/64]; + max = 780000; + } + + PDEBUG(ErrorF("mclk: %d, bus: %d, magic: %g, bpp: %d\n", + mclk, bus, magic, bpp)); + + total = mclk * bus / bpp; + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Memory bandwidth at %d bpp is %g MHz\n", bpp, total/1000); + + if(pSiS->VBFlags & CRT2_ENABLE) { + + crt2used = 0.0; + crt2clock = SiSEstimateCRT2Clock(pScrn); + if(crt2clock) { + crt2used = crt2clock + 2000; + } + +#ifdef SISDUALHEAD + if((pSiS->DualHeadMode) && (pSiSEnt)) { + + if(!pSiS->SecondHead) { + + /* TW: First head = CRT2 */ + + if(crt2clock) { + /* TW: We use the mem bandwidth as max clock; this + * might exceed the 70% limit a bit, but that + * does not matter; we take care of that limit + * when we calc CRT1. Overall, we might use up + * to 85% of the memory bandwidth, which seems + * enough to use accel and video. + * The "* macic" is just to compensate the + * calculation below. + */ + total = crt2used * magic; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Bandwidth reserved for CRT2 is %g Mhz\n", + crt2used/1000); + } else { + /* We don't know about the second head's + * depth yet. So we assume it uses the + * same. + */ + total /= 2; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Bandwidth reserved for CRT2 is %g Mhz\n", + total/1000); + } + + } else { + + /* TW: Second head = CRT1 */ + + /* Now We know about the first head's depth, + * so we can calculate more accurately. + */ + + if(crt2clock) { + total -= (crt2used * pSiSEnt->pScrn_1->bitsPerPixel / bpp); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Bandwidth reserved for CRT2 at %d bpp is %g Mhz\n", + bpp, + (crt2used * pSiSEnt->pScrn_1->bitsPerPixel / bpp)/1000); + } else { + total -= (pSiSEnt->maxUsedClock * pSiSEnt->pScrn_1->bitsPerPixel / bpp); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Bandwidth reserved for CRT2 at %d bpp is %d Mhz\n", + bpp, + (pSiSEnt->maxUsedClock * pSiSEnt->pScrn_1->bitsPerPixel / bpp)/1000); + } + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Bandwidth available for CRT1 is %g MHz\n", total/1000); + + } + + } else { +#endif + if(crt2clock) { + total -= crt2used; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Bandwidth reserved for CRT2 is %g Mhz\n", crt2used/1000); + } else { + total /= 2; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Bandwidth reserved for CRT2 is %g Mhz\n", total/1000); + } + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Bandwidth available for CRT1 is %g MHz\n", total/1000); +#ifdef SISDUALHEAD + } +#endif + + } + total /= magic; + if(total > (max / 2)) total = max / 2; + return (int)(total); + + default: + return 135000; /* guessed */ + } +} + +/* TW: Load the palette. We do this for all supported color depths + * in order to support gamma correction. We hereby convert the + * given colormap to a complete 24bit color palette and enable + * the correspoding bit in SR7 to enable the 24bit lookup table. + * Gamma correction is only supported on CRT1. + * Why are there 6-bit-RGB values submitted even if bpp is 16 and + * weight is 565? (Maybe because rgbBits is 6?) + */ +void +SISLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, + VisualPtr pVisual) +{ + SISPtr pSiS = SISPTR(pScrn); + int i, j, index; + + PDEBUG(ErrorF("SiSLoadPalette(%d)\n", numColors)); + +#ifdef SISDUALHEAD + /* TW: No palette changes on CRT2 if in dual head mode */ + if((pSiS->DualHeadMode) && (!pSiS->SecondHead)) return; +#endif + + switch(pSiS->CurrentLayout.depth) { +#ifdef SISGAMMA + case 15: + orSISIDXREG(SISSR, 0x07, 0x04); + for(i=0; i<numColors; i++) { + index = indices[i]; + if(index < 32) { /* Paranoia */ + for(j=0; j<8; j++) { + outSISREG(SISCOLIDX, (index * 8) + j); + outSISREG(SISCOLDATA, colors[index].red << (8- pScrn->rgbBits)); + outSISREG(SISCOLDATA, colors[index].green << (8 - pScrn->rgbBits)); + outSISREG(SISCOLDATA, colors[index].blue << (8 - pScrn->rgbBits)); + } + } + } + break; + case 16: + orSISIDXREG(SISSR, 0x07, 0x04); + for(i=0; i<numColors; i++) { + index = indices[i]; + if(index < 64) { /* Paranoia */ + for(j=0; j<4; j++) { + outSISREG(SISCOLIDX, (index * 4) + j); + outSISREG(SISCOLDATA, colors[index/2].red << (8 - pScrn->rgbBits)); + outSISREG(SISCOLDATA, colors[index].green << (8 - pScrn->rgbBits)); + outSISREG(SISCOLDATA, colors[index/2].blue << (8 - pScrn->rgbBits)); + } + } + } + break; + case 24: + orSISIDXREG(SISSR, 0x07, 0x04); + for(i=0; i<numColors; i++) { + index = indices[i]; + if(index < 256) { /* Paranoia */ + outSISREG(SISCOLIDX, index); + outSISREG(SISCOLDATA, colors[index].red); + outSISREG(SISCOLDATA, colors[index].green); + outSISREG(SISCOLDATA, colors[index].blue); + } + } + break; +#endif + default: + if(pScrn->rgbBits == 8) + orSISIDXREG(SISSR, 0x07, 0x04); + else + andSISIDXREG(SISSR, 0x07, ~0x04); + for(i=0; i<numColors; i++) { + index = indices[i]; + outSISREG(SISCOLIDX, index); + outSISREG(SISCOLDATA, colors[index].red >> (8 - pScrn->rgbBits)); + outSISREG(SISCOLDATA, colors[index].green >> (8 - pScrn->rgbBits)); + outSISREG(SISCOLDATA, colors[index].blue >> (8 - pScrn->rgbBits)); + } + } + + switch(pSiS->VGAEngine) { + case SIS_300_VGA: + case SIS_315_VGA: + if(pSiS->VBFlags & CRT2_ENABLE) { + /* TW: Only the SiS bridges support a CRT2 palette */ + if(pSiS->VBFlags & VB_SISBRIDGE) { + (*pSiS->LoadCRT2Palette)(pScrn, numColors, indices, + colors, pVisual); + } + } + break; + } + +} + +static void +SiS301LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO *colors, VisualPtr pVisual) +{ + SISPtr pSiS = SISPTR(pScrn); + int i, index; + + PDEBUG(ErrorF("SiS301LoadPalette(%d)\n", numColors)); + + for(i=0; i<numColors; i++) { + index = indices[i]; + outSISREG(SISCOL2IDX, index); + outSISREG(SISCOL2DATA, colors[index].red); + outSISREG(SISCOL2DATA, colors[index].green); + outSISREG(SISCOL2DATA, colors[index].blue); + } +} + + +#ifdef DEBUG +/* TW: Debug function to dump registers */ +void SiSIODump(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + int i, max3c4, min3d4, max3d4; + unsigned char temp; + + switch (pSiS->Chipset) { + case PCI_CHIP_SIS6326: + max3c4 = 0x3F; + max3d4 = 0x19; + min3d4 = 0x26; + break; + case PCI_CHIP_SIS530: + max3c4 = 0x3F; + max3d4 = 0x19; + min3d4 = 0x26; + break; + case PCI_CHIP_SIS300: + case PCI_CHIP_SIS630: + case PCI_CHIP_SIS540: + max3c4 = 0x3D; + max3d4 = 0x37; + min3d4 = 0x30; + break; + case PCI_CHIP_SIS550: + case PCI_CHIP_SIS650: + case PCI_CHIP_SIS315: + case PCI_CHIP_SIS315H: + case PCI_CHIP_SIS315PRO: + case PCI_CHIP_SIS330: + max3c4 = 0x3D; + max3d4 = 0x5f; + min3d4 = 0x30; + break; + default: + max3c4 = 0x38; + max3d4 = 0x19; + min3d4 = 0x26; + } + /* dump Misc Registers */ + temp = inb(pSiS->RelIO+0x4c); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Misc Output 3CC=%x\n", temp); + + temp = inb(pSiS->RelIO+0x4a); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Feature Control 3CA=%x\n", temp); + + /* Dump GR */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "-------------\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Registers 3CE\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "-------------\n"); + for (i=0; i<=8; i++) { + inSISIDXREG(SISGR, i, temp); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[%2x]=%2x\n", i, temp); + } + + /* dump SR0 ~ SR4 */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "-------------\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Registers 3C4\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "-------------\n"); + for (i=0; i<=4; i++) { + inSISIDXREG(SISSR, i, temp); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[%2x]=%2x\n", i, temp); + } + + /* dump extended SR */ +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + for (i=5; i<=max3c4; i++) { + inSISIDXREG(SISSR, i, temp); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[%2x]=%2x\n", i, temp); + } + + /* dump CR0 ~ CR18 */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "-------------\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Registers 3D4\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "-------------\n"); + for (i=0; i<=0x18; i++) { + inSISIDXREG(SISCR, i, temp); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[%2x]=%2x\n", i, temp); + } + /* dump extended CR */ + for (i=min3d4; i<=max3d4; i++) { + inSISIDXREG(SISCR, i, temp); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[%2x]=%2x\n", i, temp); + } +} +#endif + +void +SISDACPreInit(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + + switch (pSiS->Chipset) { + case PCI_CHIP_SIS550: + case PCI_CHIP_SIS650: + case PCI_CHIP_SIS315: + case PCI_CHIP_SIS315H: + case PCI_CHIP_SIS315PRO: + case PCI_CHIP_SIS330: + pSiS->MaxClock = SiSMemBandWidth(pScrn); + pSiS->SiSSave = SiS310Save; + pSiS->SiSSave2 = SiS301Save; + pSiS->SiSSave3 = SiS301BSave; + pSiS->SiSSaveLVDSChrontel = SiSLVDSChrontelSave; + pSiS->SiSRestore = SiS310Restore; + pSiS->SiSRestore2 = SiS301Restore; + pSiS->SiSRestore3 = SiS301BRestore; + pSiS->SiSRestoreLVDSChrontel = SiSLVDSChrontelRestore; + pSiS->LoadCRT2Palette = SiS301LoadPalette; + pSiS->SetThreshold = SiSThreshold; + pSiS->i2cInit = NULL; /* SiSI2CInit; */ + break; + case PCI_CHIP_SIS300: + case PCI_CHIP_SIS630: + case PCI_CHIP_SIS540: + pSiS->MaxClock = SiSMemBandWidth(pScrn); + pSiS->SiSSave = SiS300Save; + pSiS->SiSSave2 = SiS301Save; + pSiS->SiSSave3 = SiS301BSave; + pSiS->SiSSaveLVDSChrontel = SiSLVDSChrontelSave; + pSiS->SiSRestore = SiS300Restore; + pSiS->SiSRestore2 = SiS301Restore; + pSiS->SiSRestore3 = SiS301BRestore; + pSiS->SiSRestoreLVDSChrontel = SiSLVDSChrontelRestore; + pSiS->LoadCRT2Palette = SiS301LoadPalette; + pSiS->SetThreshold = SiSThreshold; + pSiS->i2cInit = NULL; /* SiSI2CInit; */ + break; + case PCI_CHIP_SIS5597: + case PCI_CHIP_SIS6326: + case PCI_CHIP_SIS530: + default: + pSiS->MaxClock = SiSMemBandWidth(pScrn); + pSiS->SiSRestore = SiSRestore; + pSiS->SiSSave = SiSSave; + pSiS->SetThreshold = SiSThreshold; + pSiS->i2cInit = NULL; + break; + } +} + +static void +SetBlock(CARD16 port, CARD8 from, CARD8 to, CARD8 *DataPtr) +{ + CARD8 index; + + for (index=from; index <= to; index++, DataPtr++) { + outSISIDXREG(port, index, *DataPtr); + } +} + +void +SiS6326SetTVReg(ScrnInfoPtr pScrn, CARD8 index, CARD8 data) +{ + SISPtr pSiS = SISPTR(pScrn); + outSISIDXREG(SISCR, 0xE0, index); + outSISIDXREG(SISCR, 0xE1, data); +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "SiS6326: Setting Tv %02x to %02x\n", index, data); +#endif +} + +unsigned char +SiS6326GetTVReg(ScrnInfoPtr pScrn, CARD8 index) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char data; + + outSISIDXREG(SISCR, 0xE0, index); + inSISIDXREG(SISCR, 0xE1, data); + return(data); +} + +void +SiS6326SetXXReg(ScrnInfoPtr pScrn, CARD8 index, CARD8 data) +{ + SISPtr pSiS = SISPTR(pScrn); + outSISIDXREG(SISCR, 0xE2, index); + outSISIDXREG(SISCR, 0xE3, data); +} + +unsigned char +SiS6326GetXXReg(ScrnInfoPtr pScrn, CARD8 index) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char data; + + outSISIDXREG(SISCR, 0xE2, index); + inSISIDXREG(SISCR, 0xE3, data); + return(data); +} diff --git a/src/sis_dac.h b/src/sis_dac.h new file mode 100644 index 0000000..907a990 --- /dev/null +++ b/src/sis_dac.h @@ -0,0 +1,53 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_dac.h,v 1.7 2003/01/29 15:42:17 eich Exp $ */ + +int SiS_compute_vclk(int Clock, int *out_n, int *out_dn, int *out_div, + int *out_sbit, int *out_scale); +void SISDACPreInit(ScrnInfoPtr pScrn); +unsigned int SiSddc1Read(ScrnInfoPtr pScrn); +void SISLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, + LOCO *colors, VisualPtr pVisual); +void SiSCalcClock(ScrnInfoPtr pScrn, int clock, int max_VLD, + unsigned int *vclk); + +void SiSIODump(ScrnInfoPtr pScrn); +int SiSMemBandWidth(ScrnInfoPtr pScrn); +int SiSMclk(SISPtr pSiS); +void SiSRestoreBridge(ScrnInfoPtr pScrn, SISRegPtr sisReg); + +extern void SiS6326SetTVReg(ScrnInfoPtr pScrn, CARD8 index, CARD8 data); +extern unsigned char SiS6326GetTVReg(ScrnInfoPtr pScrn, CARD8 index); +extern void SiS6326SetXXReg(ScrnInfoPtr pScrn, CARD8 index, CARD8 data); +extern unsigned char SiS6326GetXXReg(ScrnInfoPtr pScrn, CARD8 index); + +extern int SiSCalcVRate(DisplayModePtr mode); + +/* TW: Functions from init.c & init301.c */ +extern void SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO,USHORT BaseAddr); +extern void SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO,USHORT BaseAddr); +extern void SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO,USHORT BaseAddr); +extern void SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO,USHORT BaseAddr); +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 USHORT SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx); +extern void SiS_SetCH70xx(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 USHORT SiS_HandleDDC(SiS_Private *SiS_Pr, SISPtr pSiS, USHORT adaptnum, + USHORT DDCdatatype, unsigned char *buffer); +extern void SiS_WhatIsThis(SiS_Private *SiS_Pr, USHORT myvbinfo); +extern void SiS_DisplayOn(SiS_Private *SiS_Pr); +extern unsigned char SiS_GetSetModeID(ScrnInfoPtr pScrn, unsigned char id); +#if 0 +extern void SiS_SetSwitchDDC2(SiS_Private *SiS_Pr); +extern USHORT SiS_I2C_GetByte(SiS_Private *SiS_Pr); +extern Bool SiS_I2C_PutByte(SiS_Private *SiS_Pr, USHORT data); +extern Bool SiS_I2C_Address(SiS_Private *SiS_Pr, USHORT addr); +extern void SiS_I2C_Stop(SiS_Private *SiS_Pr); +#endif + + + + + diff --git a/src/sis_dga.c b/src/sis_dga.c new file mode 100644 index 0000000..d455679 --- /dev/null +++ b/src/sis_dga.c @@ -0,0 +1,412 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_dga.c,v 1.5 2003/01/29 15:42:17 eich Exp $ */ +/* + * Copyright 2000 by Alan Hourihane, Sychdyn, North Wales, UK. + * Copyright 2002 by Thomas Winischhofer, Vienna, Austria + * + * Portions from radeon_dga.c which is + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the providers not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The providers make no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE PROVIDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE PROVIDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + * Thomas Winischhofer <thomas@winischhofer.net> + */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Pci.h" +#include "xf86PciInfo.h" +#include "xaa.h" +#include "xaalocal.h" +#include "sis.h" +#include "sis_regs.h" +#include "dgaproc.h" + +static Bool SIS_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, + int *, int *, int *); +static Bool SIS_SetMode(ScrnInfoPtr, DGAModePtr); +static void SIS_Sync(ScrnInfoPtr); +static int SIS_GetViewport(ScrnInfoPtr); +static void SIS_SetViewport(ScrnInfoPtr, int, int, int); +static void SIS_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); +static void SIS_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); +static void SIS_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, + unsigned long); + +static +DGAFunctionRec SISDGAFuncs = { + SIS_OpenFramebuffer, + NULL, + SIS_SetMode, + SIS_SetViewport, + SIS_GetViewport, + SIS_Sync, + SIS_FillRect, + SIS_BlitRect, + NULL +}; + +static +DGAFunctionRec SISDGAFuncs3xx = { + SIS_OpenFramebuffer, + NULL, + SIS_SetMode, + SIS_SetViewport, + SIS_GetViewport, + SIS_Sync, + SIS_FillRect, + SIS_BlitRect, + SIS_BlitTransRect +}; + +static DGAModePtr +SISSetupDGAMode( + ScrnInfoPtr pScrn, + DGAModePtr modes, + int *num, + int bitsPerPixel, + int depth, + Bool pixmap, + int secondPitch, + unsigned long red, + unsigned long green, + unsigned long blue, + short visualClass +){ + SISPtr pSiS = SISPTR(pScrn); + DGAModePtr newmodes = NULL, currentMode; + DisplayModePtr pMode, firstMode; + int otherPitch, Bpp = bitsPerPixel >> 3; + Bool oneMore; + + pMode = firstMode = pScrn->modes; + + while (pMode) { + + otherPitch = secondPitch ? secondPitch : pMode->HDisplay; + + if(pMode->HDisplay != otherPitch) { + + newmodes = xrealloc(modes, (*num + 2) * sizeof(DGAModeRec)); + oneMore = TRUE; + + } else { + + newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec)); + oneMore = FALSE; + + } + + if(!newmodes) { + xfree(modes); + return NULL; + } + modes = newmodes; + +SECOND_PASS: + + currentMode = modes + *num; + (*num)++; + + currentMode->mode = pMode; + currentMode->flags = DGA_CONCURRENT_ACCESS; + if(pixmap) + currentMode->flags |= DGA_PIXMAP_AVAILABLE; + if(!pSiS->NoAccel) { + currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT; + if((pSiS->VGAEngine == SIS_300_VGA) || + (pSiS->VGAEngine == SIS_315_VGA) || + (pSiS->VGAEngine == SIS_530_VGA)) { + currentMode->flags |= DGA_BLIT_RECT_TRANS; + } + } + if (pMode->Flags & V_DBLSCAN) + currentMode->flags |= DGA_DOUBLESCAN; + if (pMode->Flags & V_INTERLACE) + currentMode->flags |= DGA_INTERLACED; + currentMode->byteOrder = pScrn->imageByteOrder; + currentMode->depth = depth; + currentMode->bitsPerPixel = bitsPerPixel; + currentMode->red_mask = red; + currentMode->green_mask = green; + currentMode->blue_mask = blue; + currentMode->visualClass = visualClass; + currentMode->viewportWidth = pMode->HDisplay; + currentMode->viewportHeight = pMode->VDisplay; + currentMode->xViewportStep = 1; + currentMode->yViewportStep = 1; + currentMode->viewportFlags = DGA_FLIP_RETRACE; + currentMode->offset = 0; + currentMode->address = pSiS->FbBase; + + if(oneMore) { + + /* first one is narrow width */ + currentMode->bytesPerScanline = (((pMode->HDisplay * Bpp) + 3) & ~3L); + currentMode->imageWidth = pMode->HDisplay; + currentMode->imageHeight = pMode->VDisplay; + currentMode->pixmapWidth = currentMode->imageWidth; + currentMode->pixmapHeight = currentMode->imageHeight; + currentMode->maxViewportX = currentMode->imageWidth - + currentMode->viewportWidth; + /* this might need to get clamped to some maximum */ + currentMode->maxViewportY = (currentMode->imageHeight - + currentMode->viewportHeight); + oneMore = FALSE; + goto SECOND_PASS; + + } else { + + currentMode->bytesPerScanline = ((otherPitch * Bpp) + 3) & ~3L; + currentMode->imageWidth = otherPitch; + currentMode->imageHeight = pMode->VDisplay; + currentMode->pixmapWidth = currentMode->imageWidth; + currentMode->pixmapHeight = currentMode->imageHeight; + currentMode->maxViewportX = (currentMode->imageWidth - + currentMode->viewportWidth); + /* this might need to get clamped to some maximum */ + currentMode->maxViewportY = (currentMode->imageHeight - + currentMode->viewportHeight); + } + + pMode = pMode->next; + if (pMode == firstMode) + break; + } + + return modes; +} + + +Bool +SISDGAInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + DGAModePtr modes = NULL; + int num = 0; + + /* 8 */ +#ifdef SISDUALHEAD + /* TW: We don't ever use 8bpp modes in dual head mode, + so don't offer them to DGA either + */ + if(!pSiS->DualHeadMode) { +#endif + modes = SISSetupDGAMode(pScrn, modes, &num, 8, 8, + (pScrn->bitsPerPixel == 8), + ((pScrn->bitsPerPixel != 8) + ? 0 : pScrn->displayWidth), + 0, 0, 0, PseudoColor); +#ifdef SISDUALHEAD + } +#endif + + /* 16 */ + modes = SISSetupDGAMode(pScrn, modes, &num, 16, 16, + (pScrn->bitsPerPixel == 16), + ((pScrn->depth != 16) + ? 0 : pScrn->displayWidth), + 0xf800, 0x07e0, 0x001f, TrueColor); + + if((pSiS->VGAEngine == SIS_530_VGA) || (pSiS->VGAEngine == SIS_OLD_VGA)) { + /* 24 */ + modes = SISSetupDGAMode(pScrn, modes, &num, 24, 24, + (pScrn->bitsPerPixel == 24), + ((pScrn->bitsPerPixel != 24) + ? 0 : pScrn->displayWidth), + 0xff0000, 0x00ff00, 0x0000ff, TrueColor); + } + + if(pSiS->VGAEngine != SIS_OLD_VGA) { + /* 32 */ + modes = SISSetupDGAMode(pScrn, modes, &num, 32, 24, + (pScrn->bitsPerPixel == 32), + ((pScrn->bitsPerPixel != 32) + ? 0 : pScrn->displayWidth), + 0xff0000, 0x00ff00, 0x0000ff, TrueColor); + } + + pSiS->numDGAModes = num; + pSiS->DGAModes = modes; + + if((pSiS->VGAEngine == SIS_300_VGA) || + (pSiS->VGAEngine == SIS_315_VGA) || + (pSiS->VGAEngine == SIS_530_VGA)) { + return DGAInit(pScreen, &SISDGAFuncs3xx, modes, num); + } else { + return DGAInit(pScreen, &SISDGAFuncs, modes, num); + } +} + + +static Bool +SIS_SetMode( + ScrnInfoPtr pScrn, + DGAModePtr pMode +){ + static SISFBLayout BackupLayouts[MAXSCREENS]; + int index = pScrn->pScreen->myNum; + SISPtr pSiS = SISPTR(pScrn); + + if(!pMode) { /* restore the original mode */ + + if(pSiS->DGAactive) { + /* put the ScreenParameters back */ + memcpy(&pSiS->CurrentLayout, &BackupLayouts[index], sizeof(SISFBLayout)); + } + + pScrn->currentMode = pSiS->CurrentLayout.mode; + + (*pScrn->SwitchMode)(index, pScrn->currentMode, 0); + (*pScrn->AdjustFrame)(index, pScrn->frameX0, pScrn->frameY0, 0); + pSiS->DGAactive = FALSE; + + } else { /* set new mode */ + + if(!pSiS->DGAactive) { + /* save the old parameters */ + memcpy(&BackupLayouts[index], &pSiS->CurrentLayout, sizeof(SISFBLayout)); + pSiS->DGAactive = TRUE; + } + + pSiS->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel; + pSiS->CurrentLayout.depth = pMode->depth; + pSiS->CurrentLayout.displayWidth = pMode->bytesPerScanline / (pMode->bitsPerPixel >> 3); + + (*pScrn->SwitchMode)(index, pMode->mode, 0); + /* TW: Adjust viewport to 0/0 after mode switch */ + /* This should fix the vmware-in-dualhead problems */ + (*pScrn->AdjustFrame)(index, 0, 0, 0); + } + + return TRUE; +} + +static int +SIS_GetViewport( + ScrnInfoPtr pScrn +){ + SISPtr pSiS = SISPTR(pScrn); + + return pSiS->DGAViewportStatus; +} + +static void +SIS_SetViewport( + ScrnInfoPtr pScrn, + int x, int y, + int flags +){ + SISPtr pSiS = SISPTR(pScrn); + + (*pScrn->AdjustFrame)(pScrn->pScreen->myNum, x, y, flags); + pSiS->DGAViewportStatus = 0; /* There are never pending Adjusts */ +} + +static void +SIS_FillRect ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned long color +){ + SISPtr pSiS = SISPTR(pScrn); + + if(pSiS->AccelInfoPtr) { + (*pSiS->AccelInfoPtr->SetupForSolidFill)(pScrn, color, GXcopy, ~0); + (*pSiS->AccelInfoPtr->SubsequentSolidFillRect)(pScrn, x, y, w, h); + SET_SYNC_FLAG(pSiS->AccelInfoPtr); + } +} + +static void +SIS_Sync( + ScrnInfoPtr pScrn +){ + SISPtr pSiS = SISPTR(pScrn); + + if(pSiS->AccelInfoPtr) { + (*pSiS->AccelInfoPtr->Sync)(pScrn); + } +} + +static void +SIS_BlitRect( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty +){ + SISPtr pSiS = SISPTR(pScrn); + + if(pSiS->AccelInfoPtr) { + int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; + int ydir = (srcy < dsty) ? -1 : 1; + + (*pSiS->AccelInfoPtr->SetupForScreenToScreenCopy)( + pScrn, xdir, ydir, GXcopy, (CARD32)~0, -1); + (*pSiS->AccelInfoPtr->SubsequentScreenToScreenCopy)( + pScrn, srcx, srcy, dstx, dsty, w, h); + SET_SYNC_FLAG(pSiS->AccelInfoPtr); + } +} + +static void +SIS_BlitTransRect( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty, + unsigned long color +){ + SISPtr pSiS = SISPTR(pScrn); + + if(pSiS->AccelInfoPtr) { + int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; + int ydir = (srcy < dsty) ? -1 : 1; + + (*pSiS->AccelInfoPtr->SetupForScreenToScreenCopy)( + pScrn, xdir, ydir, GXcopy, ~0, color); + (*pSiS->AccelInfoPtr->SubsequentScreenToScreenCopy)( + pScrn, srcx, srcy, dstx, dsty, w, h); + SET_SYNC_FLAG(pSiS->AccelInfoPtr); + } +} + +static Bool +SIS_OpenFramebuffer( + ScrnInfoPtr pScrn, + char **name, + unsigned char **mem, + int *size, + int *offset, + int *flags +){ + SISPtr pSiS = SISPTR(pScrn); + + *name = NULL; /* no special device */ + *mem = (unsigned char*)pSiS->FbAddress; + *size = pSiS->maxxfbmem; + *offset = 0; + *flags = DGA_NEED_ROOT; + + return TRUE; +} diff --git a/src/sis_dri.c b/src/sis_dri.c new file mode 100644 index 0000000..5eb43f5 --- /dev/null +++ b/src/sis_dri.c @@ -0,0 +1,616 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_dri.c,v 1.25 2003/01/29 15:42:17 eich Exp $ */ + +/* + * DRI wrapper for 300, 540, 630, 730 + * (310/325 series experimental and incomplete) + * + * taken and modified from tdfx_dri.c, mga_dri.c + */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Priv.h" + +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "fb.h" + +#include "GL/glxtokens.h" + +#include "sis.h" +#include "sis_dri.h" +#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) +#include "xf86drmCompat.h" +#endif + +/* TW: Idle function for 300 series */ +#define BR(x) (0x8200 | (x) << 2) +#define SiSIdle \ + while((MMIO_IN16(pSiS->IOBase, BR(16)+2) & 0xE000) != 0xE000){}; \ + while((MMIO_IN16(pSiS->IOBase, BR(16)+2) & 0xE000) != 0xE000){}; \ + MMIO_IN16(pSiS->IOBase, 0x8240); + +/* TW: Idle function for 310/325 series */ +#define Q_STATUS 0x85CC +#define SiS310Idle \ + { \ + while( (MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000){}; \ + while( (MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000){}; \ + while( (MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000){}; \ + MMIO_IN16(pSiS->IOBase, Q_STATUS); \ + } + + +extern void GlxSetVisualConfigs( + int nconfigs, + __GLXvisualConfig *configs, + void **configprivs +); + +#define AGP_PAGE_SIZE 4096 +#define AGP_PAGES 2048 +#define AGP_SIZE (AGP_PAGE_SIZE * AGP_PAGES) +#define AGP_CMDBUF_PAGES 256 +#define AGP_CMDBUF_SIZE (AGP_PAGE_SIZE * AGP_CMDBUF_PAGES) + +static char SISKernelDriverName[] = "sis"; +static char SISClientDriverName[] = "sis"; + +static Bool SISInitVisualConfigs(ScreenPtr pScreen); +static Bool SISCreateContext(ScreenPtr pScreen, VisualPtr visual, + drmContext hwContext, void *pVisualConfigPriv, + DRIContextType contextStore); +static void SISDestroyContext(ScreenPtr pScreen, drmContext hwContext, + DRIContextType contextStore); +static void SISDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, + DRIContextType readContextType, + void *readContextStore, + DRIContextType writeContextType, + void *writeContextStore); +static void SISDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index); +static void SISDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, + RegionPtr prgnSrc, CARD32 index); + +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) +extern Bool drmSiSAgpInit(int driSubFD, int offset, int size); +#endif + +static Bool +SISInitVisualConfigs(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSIS = SISPTR(pScrn); + int numConfigs = 0; + __GLXvisualConfig *pConfigs = 0; + SISConfigPrivPtr pSISConfigs = 0; + SISConfigPrivPtr *pSISConfigPtrs = 0; + int i, db, z_stencil, accum; + Bool useZ16 = FALSE; + + if(getenv("SIS_FORCE_Z16")){ + useZ16 = TRUE; + } + + switch (pScrn->bitsPerPixel) { + case 8: + case 24: + break; + case 16: + case 32: + numConfigs = (useZ16)?8:16; + + if (!(pConfigs = (__GLXvisualConfig*)xcalloc(sizeof(__GLXvisualConfig), + numConfigs))) { + return FALSE; + } + if (!(pSISConfigs = (SISConfigPrivPtr)xcalloc(sizeof(SISConfigPrivRec), + numConfigs))) { + xfree(pConfigs); + return FALSE; + } + if (!(pSISConfigPtrs = (SISConfigPrivPtr*)xcalloc(sizeof(SISConfigPrivPtr), + numConfigs))) { + xfree(pConfigs); + xfree(pSISConfigs); + return FALSE; + } + for (i=0; i<numConfigs; i++) + pSISConfigPtrs[i] = &pSISConfigs[i]; + + i = 0; + for (accum = 0; accum <= 1; accum++) { + for (z_stencil=0; z_stencil<(useZ16?2:4); z_stencil++) { + for (db = 0; db <= 1; db++) { + pConfigs[i].vid = -1; + pConfigs[i].class = -1; + pConfigs[i].rgba = TRUE; + pConfigs[i].redSize = -1; + pConfigs[i].greenSize = -1; + pConfigs[i].blueSize = -1; + pConfigs[i].redMask = -1; + pConfigs[i].greenMask = -1; + pConfigs[i].blueMask = -1; + pConfigs[i].alphaMask = 0; + if (accum) { + pConfigs[i].accumRedSize = 16; + pConfigs[i].accumGreenSize = 16; + pConfigs[i].accumBlueSize = 16; + pConfigs[i].accumAlphaSize = 16; + } else { + pConfigs[i].accumRedSize = 0; + pConfigs[i].accumGreenSize = 0; + pConfigs[i].accumBlueSize = 0; + pConfigs[i].accumAlphaSize = 0; + } + if (db) + pConfigs[i].doubleBuffer = TRUE; + else + pConfigs[i].doubleBuffer = FALSE; + pConfigs[i].stereo = FALSE; + pConfigs[i].bufferSize = -1; + switch (z_stencil){ + case 0: + pConfigs[i].depthSize = 0; + pConfigs[i].stencilSize = 0; + break; + case 1: + pConfigs[i].depthSize = 16; + pConfigs[i].stencilSize = 0; + break; + case 2: + pConfigs[i].depthSize = 32; + pConfigs[i].stencilSize = 0; + break; + case 3: + pConfigs[i].depthSize = 24; + pConfigs[i].stencilSize = 8; + break; + } + pConfigs[i].auxBuffers = 0; + pConfigs[i].level = 0; + pConfigs[i].visualRating = GLX_NONE_EXT; + pConfigs[i].transparentPixel = 0; + pConfigs[i].transparentRed = 0; + pConfigs[i].transparentGreen = 0; + pConfigs[i].transparentBlue = 0; + pConfigs[i].transparentAlpha = 0; + pConfigs[i].transparentIndex = 0; + i++; + } + } + } + if (i != numConfigs) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] Incorrect initialization of visuals. Disabling DRI.\n"); + return FALSE; + } + break; + } + + pSIS->numVisualConfigs = numConfigs; + pSIS->pVisualConfigs = pConfigs; + pSIS->pVisualConfigsPriv = pSISConfigs; + GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pSISConfigPtrs); + + return TRUE; +} + +Bool SISDRIScreenInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSIS = SISPTR(pScrn); + DRIInfoPtr pDRIInfo; + SISDRIPtr pSISDRI; +#if 000 + drmVersionPtr version; +#endif + + /* Check that the GLX, DRI, and DRM modules have been loaded by testing + * for canonical symbols in each module. */ + if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) return FALSE; + if (!xf86LoaderCheckSymbol("DRIScreenInit")) return FALSE; + if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE; + if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] SISDRIScreenInit failed (libdri.a too old)\n"); + return FALSE; + } + + /* Check the DRI version */ + { + int major, minor, patch; + DRIQueryVersion(&major, &minor, &patch); + if (major != 4 || minor < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] SISDRIScreenInit failed because of a version mismatch.\n" + "[dri] libDRI version is %d.%d.%d but version 4.0.x is needed.\n" + "[dri] Disabling DRI.\n", + major, minor, patch); + return FALSE; + } + } + + pDRIInfo = DRICreateInfoRec(); + if (!pDRIInfo) return FALSE; + pSIS->pDRIInfo = pDRIInfo; + + pDRIInfo->drmDriverName = SISKernelDriverName; + pDRIInfo->clientDriverName = SISClientDriverName; + pDRIInfo->busIdString = xalloc(64); + sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", + ((pciConfigPtr)pSIS->PciInfo->thisCard)->busnum, + ((pciConfigPtr)pSIS->PciInfo->thisCard)->devnum, + ((pciConfigPtr)pSIS->PciInfo->thisCard)->funcnum); + pDRIInfo->ddxDriverMajorVersion = 0; + pDRIInfo->ddxDriverMinorVersion = 1; + pDRIInfo->ddxDriverPatchVersion = 0; + + pDRIInfo->frameBufferPhysicalAddress = pSIS->FbAddress; + + /* TW: This was FbMapSize which is wrong as we must not + * ever overwrite HWCursor and TQ area. On the other + * hand, using availMem here causes MTRR allocation + * to fail ("base is not aligned to size"). Since + * DRI memory management is done via framebuffer + * device, I assume that the size given here + * is NOT used for eventual memory management. + */ + pDRIInfo->frameBufferSize = pSIS->FbMapSize; /* availMem; */ + + /* TW: scrnOffset is being calulated in sis_vga.c */ + pDRIInfo->frameBufferStride = pSIS->scrnOffset; + + pDRIInfo->ddxDrawableTableEntry = SIS_MAX_DRAWABLES; + + if (SAREA_MAX_DRAWABLES < SIS_MAX_DRAWABLES) + pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES; + else + pDRIInfo->maxDrawableTableEntry = SIS_MAX_DRAWABLES; + +#ifdef NOT_DONE + /* FIXME need to extend DRI protocol to pass this size back to client + * for SAREA mapping that includes a device private record + */ + pDRIInfo->SAREASize = + ((sizeof(XF86DRISAREARec) + getpagesize() - 1) & getpagesize()); /* round to page */ + /* ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); */ /* round to page */ + /* + shared memory device private rec */ +#else + /* For now the mapping works by using a fixed size defined + * in the SAREA header + */ + if (sizeof(XF86DRISAREARec)+sizeof(SISSAREAPriv) > SAREA_MAX) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Data does not fit in SAREA\n"); + return FALSE; + } + pDRIInfo->SAREASize = SAREA_MAX; +#endif + + if (!(pSISDRI = (SISDRIPtr)xcalloc(sizeof(SISDRIRec),1))) { + DRIDestroyInfoRec(pSIS->pDRIInfo); + pSIS->pDRIInfo=0; + return FALSE; + } + pDRIInfo->devPrivate = pSISDRI; + pDRIInfo->devPrivateSize = sizeof(SISDRIRec); + pDRIInfo->contextSize = sizeof(SISDRIContextRec); + + pDRIInfo->CreateContext = SISCreateContext; + pDRIInfo->DestroyContext = SISDestroyContext; + pDRIInfo->SwapContext = SISDRISwapContext; + pDRIInfo->InitBuffers = SISDRIInitBuffers; + pDRIInfo->MoveBuffers = SISDRIMoveBuffers; + pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; + + if (!DRIScreenInit(pScreen, pDRIInfo, &pSIS->drmSubFD)) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] DRIScreenInit failed. Disabling DRI.\n"); + xfree(pDRIInfo->devPrivate); + pDRIInfo->devPrivate=0; + DRIDestroyInfoRec(pSIS->pDRIInfo); + pSIS->pDRIInfo=0; + pSIS->drmSubFD = -1; + return FALSE; + } + +#if 000 + /* XXX Check DRM kernel version here */ + version = drmGetVersion(info->drmFD); + if (version) { + if (version->version_major != 1 || + version->version_minor < 0) { + /* incompatible drm version */ + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] SISDRIScreenInit failed because of a version mismatch.\n" + "[dri] sis.o kernel module version is %d.%d.%d but version 1.0.x is needed.\n" + "[dri] Disabling the DRI.\n", + version->version_major, + version->version_minor, + version->version_patchlevel); + drmFreeVersion(version); + R128DRICloseScreen(pScreen); + return FALSE; + } + drmFreeVersion(version); + } +#endif + + pSISDRI->regs.size = SISIOMAPSIZE; + pSISDRI->regs.map = 0; + if (drmAddMap(pSIS->drmSubFD, (drmHandle)pSIS->IOAddress, + pSISDRI->regs.size, DRM_REGISTERS, 0, + &pSISDRI->regs.handle)<0) + { + SISDRICloseScreen(pScreen); + return FALSE; + } + + xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08lx\n", + pSISDRI->regs.handle); + + /* AGP */ + do{ + pSIS->agpSize = 0; + pSIS->agpCmdBufSize = 0; + pSISDRI->AGPCmdBufSize = 0; + + if (drmAgpAcquire(pSIS->drmSubFD) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpAcquire failed\n"); + break; + } + + /* TODO: default value is 2x? */ + if (drmAgpEnable(pSIS->drmSubFD, drmAgpGetMode(pSIS->drmSubFD)&~0x0) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpEnable failed\n"); + break; + } + xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] drmAgpEnabled succeeded\n"); + + if (drmAgpAlloc(pSIS->drmSubFD, AGP_SIZE, 0, NULL, &pSIS->agpHandle) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] drmAgpAlloc failed\n"); + drmAgpRelease(pSIS->drmSubFD); + break; + } + + if (drmAgpBind(pSIS->drmSubFD, pSIS->agpHandle, 0) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] drmAgpBind failed\n"); + drmAgpFree(pSIS->drmSubFD, pSIS->agpHandle); + drmAgpRelease(pSIS->drmSubFD); + + break; + } + + pSIS->agpSize = AGP_SIZE; + pSIS->agpAddr = drmAgpBase(pSIS->drmSubFD); + /* pSIS->agpBase = */ + + pSISDRI->agp.size = pSIS->agpSize; + if (drmAddMap(pSIS->drmSubFD, (drmHandle)0, + pSISDRI->agp.size, DRM_AGP, 0, + &pSISDRI->agp.handle) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] Failed to map public agp area\n"); + pSISDRI->agp.size = 0; + break; + } + + pSIS->agpCmdBufSize = AGP_CMDBUF_SIZE; + pSIS->agpCmdBufAddr = pSIS->agpAddr; + pSIS->agpCmdBufBase = pSIS->agpCmdBufAddr - pSIS->agpAddr + + pSIS->agpBase; + pSIS->agpCmdBufFree = 0; + + pSISDRI->AGPCmdBufOffset = pSIS->agpCmdBufAddr - pSIS->agpAddr; + pSISDRI->AGPCmdBufSize = pSIS->agpCmdBufSize; + + drmSiSAgpInit(pSIS->drmSubFD, AGP_CMDBUF_SIZE,(AGP_SIZE - AGP_CMDBUF_SIZE)); + } + while(0); + + /* enable IRQ */ + pSIS->irq = drmGetInterruptFromBusID(pSIS->drmSubFD, + ((pciConfigPtr)pSIS->PciInfo->thisCard)->busnum, + ((pciConfigPtr)pSIS->PciInfo->thisCard)->devnum, + ((pciConfigPtr)pSIS->PciInfo->thisCard)->funcnum); + + if((drmCtlInstHandler(pSIS->drmSubFD, pSIS->irq)) != 0) + { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] failure adding irq %d handler, stereo disabled\n", + pSIS->irq); + pSIS->irqEnabled = FALSE; + } + else + { + pSIS->irqEnabled = TRUE; + } + + pSISDRI->irqEnabled = pSIS->irqEnabled; + + if (!(SISInitVisualConfigs(pScreen))) { + SISDRICloseScreen(pScreen); + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized.\n" ); + + return TRUE; +} + +void +SISDRICloseScreen(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSIS = SISPTR(pScrn); + + DRICloseScreen(pScreen); + + if (pSIS->pDRIInfo) { + if (pSIS->pDRIInfo->devPrivate) { + xfree(pSIS->pDRIInfo->devPrivate); + pSIS->pDRIInfo->devPrivate=0; + } + DRIDestroyInfoRec(pSIS->pDRIInfo); + pSIS->pDRIInfo=0; + } + if (pSIS->pVisualConfigs) xfree(pSIS->pVisualConfigs); + if (pSIS->pVisualConfigsPriv) xfree(pSIS->pVisualConfigsPriv); + + if(pSIS->agpSize){ + xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Freeing agp memory\n"); + drmAgpFree(pSIS->drmSubFD, pSIS->agpHandle); + xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Releasing agp module\n"); + drmAgpRelease(pSIS->drmSubFD); + } +} + +/* TODO: xserver receives driver's swapping event and do something + * according the data initialized in this function + */ +static Bool +SISCreateContext(ScreenPtr pScreen, VisualPtr visual, + drmContext hwContext, void *pVisualConfigPriv, + DRIContextType contextStore) +{ + return TRUE; +} + +static void +SISDestroyContext(ScreenPtr pScreen, drmContext hwContext, + DRIContextType contextStore) +{ +} + +Bool +SISDRIFinishScreenInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + SISDRIPtr pSISDRI; + + pSiS->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; + /* pSiS->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP; */ + + pSISDRI=(SISDRIPtr)pSiS->pDRIInfo->devPrivate; + pSISDRI->deviceID=pSiS->Chipset; + pSISDRI->width=pScrn->virtualX; + pSISDRI->height=pScrn->virtualY; + pSISDRI->mem=pScrn->videoRam*1024; + pSISDRI->bytesPerPixel= (pScrn->bitsPerPixel+7) / 8; + /* TODO */ + pSISDRI->scrnX=pSISDRI->width; + pSISDRI->scrnY=pSISDRI->height; + +/* + pSISDRI->textureOffset=pSiS->texOffset; + pSISDRI->textureSize=pSiS->texSize; + pSISDRI->fbOffset=pSiS->fbOffset; + pSISDRI->backOffset=pSiS->backOffset; + pSISDRI->depthOffset=pSiS->depthOffset; +*/ + + /* set SAREA value */ + { + SISSAREAPriv *saPriv; + + saPriv=(SISSAREAPriv*)DRIGetSAREAPrivate(pScreen); + + assert(saPriv); + + saPriv->CtxOwner = -1; + saPriv->QueueLength = 0; + pSiS->cmdQueueLenPtr = &(saPriv->QueueLength); + saPriv->AGPCmdBufNext = 0; + + /* frame control */ + saPriv->FrameCount = 0; + if (pSiS->VGAEngine == SIS_315_VGA) { /* 310/325 series */ +#if 0 + *(unsigned long *)(pSiS->IOBase+0x8a2c) = 0; /* FIXME: Where is this on the 310 series ? */ +#endif + SiS310Idle + } else { /* 300 series (and below) */ + *(unsigned long *)(pSiS->IOBase+0x8a2c) = 0; + SiSIdle + } + } + + return DRIFinishScreenInit(pScreen); +} + +static void +SISDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, + DRIContextType oldContextType, void *oldContext, + DRIContextType newContextType, void *newContext) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + +#if 0 + if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) && + (newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */ + SISSwapContextPrivate(pScreen); + } + if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) && + (newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */ + SISLostContext(pScreen); + } +#endif + + /* mEndPrimitive */ + /* + * TODO: do this only if X-Server get lock. If kernel supports delayed + * signal, needless to do this + */ + if (pSiS->VGAEngine == SIS_315_VGA) { +#if 0 + *(pSiS->IOBase + 0x8B50) = 0xff; /* FIXME: Where is this on 310 series */ + *(unsigned int *)(pSiS->IOBase + 0x8B60) = -1; /* FIXME: Where is this on 310 series */ +#endif + } else { + *(pSiS->IOBase + 0x8B50) = 0xff; + *(unsigned int *)(pSiS->IOBase + 0x8B60) = -1; + } +} + +static void +SISDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + + if (pSiS->VGAEngine == SIS_315_VGA) { + SiS310Idle /* 310/325 series */ + } else { + SiSIdle /* 300 series */ + } +} + +static void +SISDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, + RegionPtr prgnSrc, CARD32 index) +{ + ScreenPtr pScreen = pParent->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + + if (pSiS->VGAEngine == SIS_315_VGA) { + SiS310Idle /* 310/325 series */ + } else { + SiSIdle /* 300 series and below */ + } +} + +#if 0 +void SISLostContext(ScreenPtr pScreen) +{ +} + +void SISSwapContextPrivate(ScreenPtr pScreen) +{ +} +#endif diff --git a/src/sis_dri.h b/src/sis_dri.h new file mode 100644 index 0000000..55714d0 --- /dev/null +++ b/src/sis_dri.h @@ -0,0 +1,69 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_dri.h,v 1.6 2001/05/16 13:43:17 alanh Exp $ */ + +/* modified from tdfx_dri.h */ + +#ifndef _SIS_DRI_ +#define _SIS_DRI_ + +#include "xf86drm.h" + +#define SIS_MAX_DRAWABLES 256 +#define SISIOMAPSIZE (64*1024) + +typedef struct { + int CtxOwner; + int QueueLength; + unsigned int AGPCmdBufNext; + unsigned int FrameCount; +} SISSAREAPriv; + +#define SIS_FRONT 0 +#define SIS_BACK 1 +#define SIS_DEPTH 2 + +typedef struct { + drmHandle handle; + drmSize size; + drmAddress map; +} sisRegion, *sisRegionPtr; + +typedef struct { + sisRegion regs, agp; + int deviceID; + int width; + int height; + int mem; + int bytesPerPixel; + int priv1; + int priv2; + int fbOffset; + int backOffset; + int depthOffset; + int textureOffset; + int textureSize; + unsigned int AGPCmdBufOffset; + unsigned int AGPCmdBufSize; + int irqEnabled; + unsigned int scrnX, scrnY; +} SISDRIRec, *SISDRIPtr; + +typedef struct { + /* Nothing here yet */ + int dummy; +} SISConfigPrivRec, *SISConfigPrivPtr; + +typedef struct { + /* Nothing here yet */ + int dummy; +} SISDRIContextRec, *SISDRIContextPtr; + +#ifdef XFree86Server + +#include "screenint.h" + +Bool SISDRIScreenInit(ScreenPtr pScreen); +void SISDRICloseScreen(ScreenPtr pScreen); +Bool SISDRIFinishScreenInit(ScreenPtr pScreen); + +#endif +#endif diff --git a/src/sis_driver.c b/src/sis_driver.c new file mode 100644 index 0000000..eb89fe2 --- /dev/null +++ b/src/sis_driver.c @@ -0,0 +1,7648 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_driver.c,v 1.86 2003/02/04 02:44:29 dawes Exp $ */ +/* + * Copyright 1998,1999 by Alan Hourihane, Wigan, England. + * Parts Copyright 2001, 2002, 2003 by Thomas Winischhofer, Vienna, Austria. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holder not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The copyright holder makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk + * Mike Chapman <mike@paranoia.com>, + * Juanjo Santamarta <santamarta@ctv.es>, + * Mitani Hiroshi <hmitani@drl.mei.co.jp> + * David Thomas <davtom@dream.org.uk>. + * + * Thomas Winischhofer <thomas@winischhofer.net>: + * - 310/325 series (315/550/650/651/740/M650) support + * - (possibly incomplete) Xabre (SiS330) support + * - new mode switching code for 300, 310/325 and 330 series + * - many fixes for 300/540/630/730 chipsets, + * - many fixes for 5597/5598, 6326 and 530/620 chipsets, + * - VESA mode switching (deprecated), + * - extended CRT2/video bridge handling support, + * - dual head support on 300, 310/325 and 330 series + * - 650/LVDS (up to 1400x1050), 650/Chrontel 701x support + * - 30xB/30xLV/30xLVX video bridge support (300, 310/325, 330 series) + * - Xv support for 5597/5598, 6326, 530/620 and 310/325 series + * - video overlay enhancements for 300 series + * - TV and hi-res support for the 6326 + * - Color HW cursor support for 300(emulated), 310/325 and 330 series + * - etc. + */ + +#include "fb.h" +#include "xf1bpp.h" +#include "xf4bpp.h" +#include "mibank.h" +#include "micmap.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "dixstruct.h" +#include "xf86Version.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "xf86cmap.h" +#include "vgaHW.h" +#include "xf86RAC.h" +#include "shadowfb.h" +#include "vbe.h" + +#include "sis_shadow.h" + +#include "mipointer.h" +#include "mibstore.h" + +#include "sis.h" +#include "sis_regs.h" +#include "sis_vb.h" +#include "sis_dac.h" + +#include "sis_driver.h" + +#define _XF86DGA_SERVER_ +#include "extensions/xf86dgastr.h" + +#include "globals.h" +#define DPMS_SERVER +#include "extensions/dpms.h" + +#ifdef XvExtension +#include "xf86xv.h" +#include "Xv.h" +#endif + +#ifdef XF86DRI +#include "dri.h" +#endif + +/* Mandatory functions */ +static void SISIdentify(int flags); +static Bool SISProbe(DriverPtr drv, int flags); +static Bool SISPreInit(ScrnInfoPtr pScrn, int flags); +static Bool SISScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv); +static Bool SISEnterVT(int scrnIndex, int flags); +static void SISLeaveVT(int scrnIndex, int flags); +static Bool SISCloseScreen(int scrnIndex, ScreenPtr pScreen); +static Bool SISSaveScreen(ScreenPtr pScreen, int mode); +static Bool SISSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); +static void SISAdjustFrame(int scrnIndex, int x, int y, int flags); +#ifdef SISDUALHEAD +static Bool SISSaveScreenDH(ScreenPtr pScreen, int mode); +#endif + +/* Optional functions */ +static void SISFreeScreen(int scrnIndex, int flags); +static int SISValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, + int flags); + +/* Internally used functions */ +static Bool SISMapMem(ScrnInfoPtr pScrn); +static Bool SISUnmapMem(ScrnInfoPtr pScrn); +static void SISSave(ScrnInfoPtr pScrn); +static void SISRestore(ScrnInfoPtr pScrn); +static void SISVESARestore(ScrnInfoPtr pScrn); +static Bool SISModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); +static void SISModifyModeInfo(DisplayModePtr mode); +static void SiSPreSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode); +static void SiSPostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg); +static void SiS6326PostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg); +static Bool SiSSetVESAMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); +static void SiSBuildVesaModeList(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe); +static UShort SiSCalcVESAModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode); +static void SISVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function); +static void SISBridgeRestore(ScrnInfoPtr pScrn); +static void SiSEnableTurboQueue(ScrnInfoPtr pScrn); +unsigned char SISSearchCRT1Rate(ScrnInfoPtr pScrn, DisplayModePtr mode); +static void SISWaitVBRetrace(ScrnInfoPtr pScrn); + +void SISWaitRetraceCRT1(ScrnInfoPtr pScrn); +void SISWaitRetraceCRT2(ScrnInfoPtr pScrn); + +BOOLEAN SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn); +#ifdef CYCLECRT2 +Bool SISCycleCRT2Type(int scrnIndex, DisplayModePtr mode); +#endif + +#ifdef DEBUG +static void SiSDumpModeInfo(ScrnInfoPtr pScrn, DisplayModePtr mode); +#endif + +/* TW: New mode switching functions */ +extern BOOLEAN SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + ScrnInfoPtr pScrn, DisplayModePtr mode, BOOLEAN IsCustom); +extern BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch); +extern USHORT SiS_CalcModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode); +extern USHORT SiS_CheckCalcModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags); +extern void SiSRegInit(SiS_Private *SiS_Pr, USHORT BaseAddr); +extern DisplayModePtr SiSBuildBuiltInModeList(ScrnInfoPtr pScrn); +#ifdef SISDUALHEAD +extern BOOLEAN SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + ScrnInfoPtr pScrn, DisplayModePtr mode, BOOLEAN IsCustom); +extern BOOLEAN SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, + ScrnInfoPtr pScrn, DisplayModePtr mode); +#endif + +/* TW: For power management for 310/325 series */ +extern void SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr); +extern void SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr); +extern void SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); +extern void SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension); + +#ifdef SISDUALHEAD +static int SISEntityIndex = -1; +#endif + +/* + * This is intentionally screen-independent. It indicates the binding + * choice made in the first PreInit. + */ +static int pix24bpp = 0; + +/* + * This contains the functions needed by the server after loading the driver + * module. It must be supplied, and gets passed back by the SetupProc + * function in the dynamic case. In the static case, a reference to this + * is compiled in, and this requires that the name of this DriverRec be + * an upper-case version of the driver name. + */ + +DriverRec SIS = { + SIS_CURRENT_VERSION, + SIS_DRIVER_NAME, + SISIdentify, + SISProbe, + SISAvailableOptions, + NULL, + 0 +}; + +static SymTabRec SISChipsets[] = { + { PCI_CHIP_SIS5597, "SIS5597/5598" }, + { PCI_CHIP_SIS530, "SIS530/620" }, + { PCI_CHIP_SIS6326, "SIS6326/AGP/DVD" }, + { PCI_CHIP_SIS300, "SIS300/305" }, + { PCI_CHIP_SIS630, "SIS630/730" }, + { PCI_CHIP_SIS540, "SIS540" }, + { PCI_CHIP_SIS315, "SIS315" }, + { PCI_CHIP_SIS315H, "SIS315H" }, + { PCI_CHIP_SIS315PRO, "SIS315PRO" }, + { PCI_CHIP_SIS550, "SIS550" }, + { PCI_CHIP_SIS650, "SIS650/M650/651/740" }, +#ifdef INCL_SIS330 /* TW: New for SiS330 (untested) */ + { PCI_CHIP_SIS330, "SIS330(Xabre)" }, +#endif + { -1, NULL } +}; + +static PciChipsets SISPciChipsets[] = { + { PCI_CHIP_SIS5597, PCI_CHIP_SIS5597, RES_SHARED_VGA }, + { PCI_CHIP_SIS530, PCI_CHIP_SIS530, RES_SHARED_VGA }, + { PCI_CHIP_SIS6326, PCI_CHIP_SIS6326, RES_SHARED_VGA }, + { PCI_CHIP_SIS300, PCI_CHIP_SIS300, RES_SHARED_VGA }, + { PCI_CHIP_SIS630, PCI_CHIP_SIS630, RES_SHARED_VGA }, + { PCI_CHIP_SIS540, PCI_CHIP_SIS540, RES_SHARED_VGA }, + { PCI_CHIP_SIS550, PCI_CHIP_SIS550, RES_SHARED_VGA }, + { PCI_CHIP_SIS315, PCI_CHIP_SIS315, RES_SHARED_VGA }, + { PCI_CHIP_SIS315H, PCI_CHIP_SIS315H, RES_SHARED_VGA }, + { PCI_CHIP_SIS315PRO, PCI_CHIP_SIS315PRO, RES_SHARED_VGA }, + { PCI_CHIP_SIS650, PCI_CHIP_SIS650, RES_SHARED_VGA }, +#ifdef INCL_SIS330 /* TW: New for SiS330 */ + { PCI_CHIP_SIS330, PCI_CHIP_SIS330, RES_SHARED_VGA }, +#endif + { -1, -1, RES_UNDEFINED } +}; + +static const char *xaaSymbols[] = { + "XAACopyROP", + "XAACreateInfoRec", + "XAADestroyInfoRec", + "XAAFillSolidRects", + "XAAHelpPatternROP", + "XAAInit", + NULL +}; + +static const char *vgahwSymbols[] = { + "vgaHWFreeHWRec", + "vgaHWGetHWRec", + "vgaHWGetIOBase", + "vgaHWGetIndex", + "vgaHWInit", + "vgaHWLock", + "vgaHWMapMem", + "vgaHWProtect", + "vgaHWRestore", + "vgaHWSave", + "vgaHWSaveScreen", + "vgaHWUnlock", + NULL +}; + +static const char *miscfbSymbols[] = { + "xf1bppScreenInit", + "xf4bppScreenInit", + NULL +}; + +static const char *fbSymbols[] = { + "fbPictureInit", + "fbScreenInit", + NULL +}; + +static const char *shadowSymbols[] = { + "ShadowFBInit", + NULL +}; + +static const char *ramdacSymbols[] = { + "xf86CreateCursorInfoRec", + "xf86DestroyCursorInfoRec", + "xf86InitCursor", + NULL +}; + +static const char *ddcSymbols[] = { + "xf86PrintEDID", + "xf86SetDDCproperties", + "xf86InterpretEDID", + "xf86DoEDID_DDC1", +#ifdef SISI2C + "xf86DoEDID_DDC2", +#endif + NULL +}; + +static const char *i2cSymbols[] = { + "xf86I2CBusInit", + "xf86CreateI2CBusRec", + NULL +}; + +static const char *int10Symbols[] = { + "xf86FreeInt10", + "xf86InitInt10", + NULL +}; + +static const char *vbeSymbols[] = { +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) + "VBEInit", +#else + "VBEExtendedInit", +#endif + "vbeDoEDID", + "vbeFree", + "VBEGetVBEInfo", + "VBEFreeVBEInfo", + "VBEGetModeInfo", + "VBEFreeModeInfo", + "VBESaveRestore", + "VBESetVBEMode", + "VBEGetVBEMode", + "VBESetDisplayStart", + "VBESetGetLogicalScanlineLength", + NULL +}; + +#ifdef XF86DRI +static const char *drmSymbols[] = { + "drmAddMap", + "drmAgpAcquire", + "drmAgpAlloc", + "drmAgpBase", + "drmAgpBind", + "drmAgpEnable", + "drmAgpFree", + "drmAgpGetMode", + "drmAgpRelease", + "drmCtlInstHandler", + "drmGetInterruptFromBusID", + "drmSiSAgpInit", + NULL +}; + +static const char *driSymbols[] = { + "DRICloseScreen", + "DRICreateInfoRec", + "DRIDestroyInfoRec", + "DRIFinishScreenInit", + "DRIGetSAREAPrivate", + "DRILock", + "DRIQueryVersion", + "DRIScreenInit", + "DRIUnlock", + "GlxSetVisualConfigs", + NULL +}; +#endif + +#ifdef XFree86LOADER + +static MODULESETUPPROTO(sisSetup); + +static XF86ModuleVersionInfo sisVersRec = +{ + SIS_DRIVER_NAME, + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + SIS_MAJOR_VERSION, SIS_MINOR_VERSION, SIS_PATCHLEVEL, + ABI_CLASS_VIDEODRV, /* This is a video driver */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0,0,0,0} +}; + +XF86ModuleData sisModuleData = { &sisVersRec, sisSetup, NULL }; + +pointer +sisSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + if (!setupDone) { + setupDone = TRUE; + xf86AddDriver(&SIS, module, 0); + LoaderRefSymLists(vgahwSymbols, fbSymbols, i2cSymbols, xaaSymbols, + miscfbSymbols, shadowSymbols, ramdacSymbols, + vbeSymbols, int10Symbols, +#ifdef XF86DRI + drmSymbols, driSymbols, +#endif + NULL); + return (pointer)TRUE; + } + + if (errmaj) *errmaj = LDR_ONCEONLY; + return NULL; +} + +#endif /* XFree86LOADER */ + +static Bool +SISGetRec(ScrnInfoPtr pScrn) +{ + /* + * Allocate an SISRec, and hook it into pScrn->driverPrivate. + * pScrn->driverPrivate is initialised to NULL, so we can check if + * the allocation has already been done. + */ + if (pScrn->driverPrivate != NULL) + return TRUE; + + pScrn->driverPrivate = xnfcalloc(sizeof(SISRec), 1); + + /* Initialise it to 0 */ + memset(pScrn->driverPrivate, 0, sizeof(SISRec)); + + return TRUE; +} + +static void +SISFreeRec(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = NULL; +#endif + + /* TW: Just to make sure... */ + if(!pSiS) return; + + pSiSEnt = pSiS->entityPrivate; + + if(pSiS->pstate) xfree(pSiS->pstate); + pSiS->pstate = NULL; + if(pSiS->fonts) xfree(pSiS->fonts); + pSiS->fonts = NULL; +#ifdef SISDUALHEAD + if(pSiSEnt) { + if(!pSiS->SecondHead) { + /* TW: Free memory only if we are first head; in case of an error + * during init of the second head, the server will continue - + * and we need the BIOS image and SiS_Private for the first + * head. + */ + if(pSiSEnt->BIOS) xfree(pSiSEnt->BIOS); + pSiSEnt->BIOS = pSiS->BIOS = NULL; + if(pSiSEnt->SiS_Pr) xfree(pSiSEnt->SiS_Pr); + pSiSEnt->SiS_Pr = pSiS->SiS_Pr = NULL; + } else { + pSiS->BIOS = NULL; + pSiS->SiS_Pr = NULL; + } + } else { +#endif + if(pSiS->BIOS) xfree(pSiS->BIOS); + pSiS->BIOS = NULL; + if(pSiS->SiS_Pr) xfree(pSiS->SiS_Pr); + pSiS->SiS_Pr = NULL; +#ifdef SISDUALHEAD + } +#endif + if (pSiS->pVbe) vbeFree(pSiS->pVbe); + pSiS->pVbe = NULL; + if (pScrn->driverPrivate == NULL) + return; + xfree(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + +static void +SISDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char extDDC_PCR=0; + unsigned char crtc17, seq1; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "SISDisplayPowerManagementSet(%d)\n",PowerManagementMode); + + /* unlock registers */ +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + /* Read CR17 */ + inSISIDXREG(SISCR, 0x17, crtc17); + + /* Read SR1 */ + inSISIDXREG(SISSR, 0x01, seq1); + + if(pSiS->VBFlags & CRT2_LCD) { + if(((pSiS->VGAEngine == SIS_300_VGA) && + (!(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)))) || + ((pSiS->VGAEngine == SIS_315_VGA) && + ((pSiS->VBFlags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) { + /* Read Power Control Register (SR11) */ + inSISIDXREG(SISSR, 0x11, extDDC_PCR); + /* if not blanked, obtain state of LCD blank flags set by BIOS */ + if(!pSiS->Blank) { + pSiS->LCDon = extDDC_PCR; + } + /* erase LCD blank flags */ + extDDC_PCR &= ~0x0C; + } + } + + switch (PowerManagementMode) { + + case DPMSModeOn: /* HSync: On, VSync: On */ + + pSiS->Blank = FALSE; + seq1 &= ~0x20; + crtc17 |= 0x80; + if(pSiS->VBFlags & CRT2_LCD) { + if(pSiS->VGAEngine == SIS_315_VGA) { + if(pSiS->VBFlags & VB_CHRONTEL) { + SiS_Chrontel701xBLOn(pSiS->SiS_Pr); + } else if(pSiS->VBFlags & VB_LVDS) { + extDDC_PCR |= (pSiS->LCDon & 0x0C); + } else if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + SiS_SiS30xBLOn(pSiS->SiS_Pr,&pSiS->sishw_ext); + } + } else if(pSiS->VGAEngine == SIS_300_VGA) { + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + SiS_SiS30xBLOn(pSiS->SiS_Pr,&pSiS->sishw_ext); + } else { + extDDC_PCR |= (pSiS->LCDon & 0x0C); + } + } + } + break; + + case DPMSModeStandby: /* HSync: Off, VSync: On */ + case DPMSModeSuspend: /* HSync: On, VSync: Off */ + + pSiS->Blank = TRUE; + seq1 |= 0x20 ; + if(pSiS->VBFlags & CRT2_LCD) { + if(pSiS->VGAEngine == SIS_315_VGA) { + if(pSiS->VBFlags & VB_CHRONTEL) { + SiS_Chrontel701xBLOff(pSiS->SiS_Pr); + } else if(pSiS->VBFlags & VB_LVDS) { + extDDC_PCR |= 0x08; + } else if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + SiS_SiS30xBLOff(pSiS->SiS_Pr,&pSiS->sishw_ext); + } + } else if(pSiS->VGAEngine == SIS_300_VGA) { + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + SiS_SiS30xBLOff(pSiS->SiS_Pr,&pSiS->sishw_ext); + } else { + extDDC_PCR |= 0x08; + } + } + } + break; + + case DPMSModeOff: /* HSync: Off, VSync: Off */ + + pSiS->Blank = TRUE; + seq1 |= 0x20; + if(pSiS->VGAEngine == SIS_300_VGA || + pSiS->VGAEngine == SIS_315_VGA) { + /* TW: We can't switch off CRT1 if bridge is in slavemode */ + if(pSiS->VBFlags & CRT2_ENABLE) { + if(!(SiSBridgeIsInSlaveMode(pScrn))) crtc17 &= ~0x80; + } else crtc17 &= ~0x80; + } else { + crtc17 &= ~0x80; + } + if(pSiS->VBFlags & CRT2_LCD) { + if(pSiS->VGAEngine == SIS_315_VGA) { + if(pSiS->VBFlags & VB_CHRONTEL) { + SiS_Chrontel701xBLOff(pSiS->SiS_Pr); + } else if(pSiS->VBFlags & VB_LVDS) { + extDDC_PCR |= 0x0C; + } else if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + SiS_SiS30xBLOff(pSiS->SiS_Pr,&pSiS->sishw_ext); + } + } else if(pSiS->VGAEngine == SIS_300_VGA) { + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + SiS_SiS30xBLOff(pSiS->SiS_Pr,&pSiS->sishw_ext); + } else { + extDDC_PCR |= 0x0C; + } + } + } + break; + + } + + outSISIDXREG(SISSR, 0x01, seq1); /* Set/Clear "Display On" bit */ + + outSISIDXREG(SISCR, 0x17, crtc17); + + if(pSiS->VBFlags & CRT2_LCD) { + if(((pSiS->VGAEngine == SIS_300_VGA) && + (!(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)))) || + ((pSiS->VGAEngine == SIS_315_VGA) && + ((pSiS->VBFlags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) { + outSISIDXREG(SISSR, 0x11, extDDC_PCR); + } + } + + outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ + usleep(10000); + outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ + +} + +#ifdef SISDUALHEAD +/* TW: DPMS for dual head mode */ +static void +SISDisplayPowerManagementSetDH(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char crtc17 = 0; + unsigned char extDDC_PCR=0; + unsigned char seq1 = 0; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "SISDisplayPowerManagementSetDH(%d)\n",PowerManagementMode); + + /* unlock registers */ +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + if (pSiS->SecondHead) { + + /* TW: Second (slave) head is always CRT1 */ + + /* Read CR17 and SR01 */ + inSISIDXREG(SISCR, 0x17, crtc17); + inSISIDXREG(SISSR, 0x01, seq1); + + switch (PowerManagementMode) + { + case DPMSModeOn: /* HSync: On, VSync: On */ + seq1 &= ~0x20 ; + crtc17 |= 0x80; + pSiS->BlankCRT1 = FALSE; + break; + + case DPMSModeStandby: /* HSync: Off, VSync: On */ + case DPMSModeSuspend: /* HSync: On, VSync: Off */ + seq1 |= 0x20; + pSiS->BlankCRT1 = TRUE; + break; + + case DPMSModeOff: /* HSync: Off, VSync: Off */ + seq1 |= 0x20 ; + pSiS->BlankCRT1 = TRUE; + crtc17 &= ~0x80; + break; + } + outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ + + outSISIDXREG(SISSR, 0x01, seq1); /* Set/Clear "Display On" bit */ + + usleep(10000); + + outSISIDXREG(SISCR, 0x17, crtc17); + + outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ + + } else { + + /* TW: Master head is always CRT2 */ + + /* TV can not be managed */ + if(!(pSiS->VBFlags & CRT2_LCD)) return; + + if(((pSiS->VGAEngine == SIS_300_VGA) && + (!(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)))) || + ((pSiS->VGAEngine == SIS_315_VGA) && + ((pSiS->VBFlags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) { + /* Read Power Control Register (SR11) */ + inSISIDXREG(SISSR, 0x11, extDDC_PCR); + /* if not blanked obtain state of LCD blank flags set by BIOS */ + if(!pSiS->BlankCRT2) { + pSiS->LCDon = extDDC_PCR; + } + /* erase LCD blank flags */ + extDDC_PCR &= ~0xC; + } + + switch (PowerManagementMode) { + + case DPMSModeOn: + pSiS->BlankCRT2 = FALSE; + if(pSiS->VGAEngine == SIS_315_VGA) { + if(pSiS->VBFlags & VB_CHRONTEL) { + SiS_Chrontel701xBLOn(pSiS->SiS_Pr); + } else if(pSiS->VBFlags & VB_LVDS) { + extDDC_PCR |= (pSiS->LCDon & 0x0C); + } else if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + SiS_SiS30xBLOn(pSiS->SiS_Pr, &pSiS->sishw_ext); + } + } else if(pSiS->VGAEngine == SIS_300_VGA) { + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + SiS_SiS30xBLOn(pSiS->SiS_Pr, &pSiS->sishw_ext); + } else { + extDDC_PCR |= (pSiS->LCDon & 0x0C); + } + } + break; + + case DPMSModeStandby: + case DPMSModeSuspend: + pSiS->BlankCRT2 = TRUE; + if(pSiS->VGAEngine == SIS_315_VGA) { + if(pSiS->VBFlags & VB_CHRONTEL) { + SiS_Chrontel701xBLOff(pSiS->SiS_Pr); + } else if(pSiS->VBFlags & VB_LVDS) { + extDDC_PCR |= 0x08; + } else if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + SiS_SiS30xBLOff(pSiS->SiS_Pr, &pSiS->sishw_ext); + } + } else if(pSiS->VGAEngine == SIS_300_VGA) { + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + SiS_SiS30xBLOff(pSiS->SiS_Pr, &pSiS->sishw_ext); + } else { + extDDC_PCR |= 0x08; + } + } + break; + + case DPMSModeOff: + pSiS->BlankCRT2 = TRUE; + if(pSiS->VGAEngine == SIS_315_VGA) { + if(pSiS->VBFlags & VB_CHRONTEL) { + SiS_Chrontel701xBLOff(pSiS->SiS_Pr); + } else if(pSiS->VBFlags & VB_LVDS) { + extDDC_PCR |= 0x0C; + } else if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + SiS_SiS30xBLOff(pSiS->SiS_Pr, &pSiS->sishw_ext); + } + } else if(pSiS->VGAEngine == SIS_300_VGA) { + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + SiS_SiS30xBLOff(pSiS->SiS_Pr, &pSiS->sishw_ext); + } else { + extDDC_PCR |= 0x0C; + } + } + break; + } + + if(((pSiS->VGAEngine == SIS_300_VGA) && + (!(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)))) || + ((pSiS->VGAEngine == SIS_315_VGA) && + ((pSiS->VBFlags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) { + outSISIDXREG(SISSR, 0x11, extDDC_PCR); + } + + } +} +#endif + +/* Mandatory */ +static void +SISIdentify(int flags) +{ + xf86PrintChipsets(SIS_NAME, "driver for SiS chipsets", SISChipsets); +} + +static void +SIS1bppColorMap(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + + outSISREG(SISCOLIDX, 0x00); + outSISREG(SISCOLDATA, 0x00); + outSISREG(SISCOLDATA, 0x00); + outSISREG(SISCOLDATA, 0x00); + + outSISREG(SISCOLIDX, 0x3f); + outSISREG(SISCOLDATA, 0x3f); + outSISREG(SISCOLDATA, 0x3f); + outSISREG(SISCOLDATA, 0x3f); +} + +/* Mandatory */ +static Bool +SISProbe(DriverPtr drv, int flags) +{ + int i; + GDevPtr *devSections; + int *usedChips; + int numDevSections; + int numUsed; + Bool foundScreen = FALSE; + + /* + * The aim here is to find all cards that this driver can handle, + * and for the ones not already claimed by another driver, claim the + * slot, and allocate a ScrnInfoRec. + * + * This should be a minimal probe, and it should under no circumstances + * change the state of the hardware. Because a device is found, don't + * assume that it will be used. Don't do any initialisations other than + * the required ScrnInfoRec initialisations. Don't allocate any new + * data structures. + * + */ + + /* + * Next we check, if there has been a chipset override in the config file. + * For this we must find out if there is an active device section which + * is relevant, i.e., which has no driver specified or has THIS driver + * specified. + */ + + if ((numDevSections = xf86MatchDevice(SIS_DRIVER_NAME, + &devSections)) <= 0) { + /* + * There's no matching device section in the config file, so quit + * now. + */ + return FALSE; + } + + /* + * We need to probe the hardware first. We then need to see how this + * fits in with what is given in the config file, and allow the config + * file info to override any contradictions. + */ + + /* + * All of the cards this driver supports are PCI, so the "probing" just + * amounts to checking the PCI data that the server has already collected. + */ + if (xf86GetPciVideoInfo() == NULL) { + /* + * We won't let anything in the config file override finding no + * PCI video cards at all. This seems reasonable now, but we'll see. + */ + return FALSE; + } + + numUsed = xf86MatchPciInstances(SIS_NAME, PCI_VENDOR_SIS, + SISChipsets, SISPciChipsets, devSections, + numDevSections, drv, &usedChips); + + /* Free it since we don't need that list after this */ + xfree(devSections); + if (numUsed <= 0) + return FALSE; + + if (flags & PROBE_DETECT) + foundScreen = TRUE; + else for (i = 0; i < numUsed; i++) { + ScrnInfoPtr pScrn; +#ifdef SISDUALHEAD + EntityInfoPtr pEnt; +#endif + + /* Allocate a ScrnInfoRec and claim the slot */ + pScrn = NULL; + + if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], + SISPciChipsets, NULL, NULL, + NULL, NULL, NULL))) { + /* Fill in what we can of the ScrnInfoRec */ + pScrn->driverVersion = SIS_CURRENT_VERSION; + pScrn->driverName = SIS_DRIVER_NAME; + pScrn->name = SIS_NAME; + pScrn->Probe = SISProbe; + pScrn->PreInit = SISPreInit; + pScrn->ScreenInit = SISScreenInit; + pScrn->SwitchMode = SISSwitchMode; + pScrn->AdjustFrame = SISAdjustFrame; + pScrn->EnterVT = SISEnterVT; + pScrn->LeaveVT = SISLeaveVT; + pScrn->FreeScreen = SISFreeScreen; + pScrn->ValidMode = SISValidMode; + foundScreen = TRUE; + } +#ifdef SISDUALHEAD + pEnt = xf86GetEntityInfo(usedChips[i]); + + /* TW: I assume these chipsets as - basically - dual head capable. */ + if (pEnt->chipset == PCI_CHIP_SIS630 || pEnt->chipset == PCI_CHIP_SIS540 || + pEnt->chipset == PCI_CHIP_SIS650 || pEnt->chipset == PCI_CHIP_SIS550 || + pEnt->chipset == PCI_CHIP_SIS315 || pEnt->chipset == PCI_CHIP_SIS315H || + pEnt->chipset == PCI_CHIP_SIS315PRO || pEnt->chipset == PCI_CHIP_SIS330 || + pEnt->chipset == PCI_CHIP_SIS300) { + + SISEntPtr pSiSEnt = NULL; + DevUnion *pPriv; + + xf86SetEntitySharable(usedChips[i]); + if (SISEntityIndex < 0) + SISEntityIndex = xf86AllocateEntityPrivateIndex(); + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], SISEntityIndex); + if (!pPriv->ptr) { + pPriv->ptr = xnfcalloc(sizeof(SISEntRec), 1); + pSiSEnt = pPriv->ptr; + pSiSEnt->lastInstance = -1; + pSiSEnt->DisableDual = FALSE; + pSiSEnt->ErrorAfterFirst = FALSE; + pSiSEnt->MapCountIOBase = pSiSEnt->MapCountFbBase = 0; + pSiSEnt->FbBase = pSiSEnt->IOBase = NULL; + pSiSEnt->forceUnmapIOBase = FALSE; + pSiSEnt->forceUnmapFbBase = FALSE; +#ifdef __alpha__ + pSiSEnt->MapCountIOBaseDense = 0; + pSiSEnt->IOBaseDense = NULL; + pSiSEnt->forceUnmapIOBaseDense = FALSE; +#endif + } else { + pSiSEnt = pPriv->ptr; + } + pSiSEnt->lastInstance++; + xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0], + pSiSEnt->lastInstance); + } +#endif + } + xfree(usedChips); + return foundScreen; +} + + +/* TW: If monitor section has no HSync/VRefresh data, + * derive it from DDC data. + */ +static void +SiSSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) +{ + MonPtr mon = pScrn->monitor; + xf86MonPtr ddc = mon->DDC; + int i,j; + float myhhigh, myhlow; + int myvhigh, myvlow; + unsigned char temp; + const myhddctiming myhtiming[11] = { + { 1, 0x20, 31.6 }, /* rounded up by .1 */ + { 1, 0x02, 35.3 }, + { 1, 0x04, 37.6 }, + { 1, 0x08, 38.0 }, + { 1, 0x01, 38.0 }, + { 2, 0x40, 47.0 }, + { 2, 0x80, 48.2 }, + { 2, 0x08, 48.5 }, + { 2, 0x04, 56.6 }, + { 2, 0x02, 60.1 }, + { 2, 0x01, 80.1 } + }; + const myvddctiming myvtiming[10] = { + { 1, 0x02, 56 }, + { 1, 0x01, 60 }, + { 2, 0x08, 60 }, + { 2, 0x04, 70 }, + { 1, 0x08, 72 }, + { 2, 0x80, 72 }, + { 1, 0x04, 75 }, + { 2, 0x40, 75 }, + { 2, 0x02, 75 }, + { 2, 0x01, 75 } + }; + /* "Future modes"; we only check the really high ones */ + const myddcstdmodes mystdmodes[8] = { + { 1280, 1024, 85, 91.1 }, + { 1600, 1200, 60, 75.0 }, + { 1600, 1200, 65, 81.3 }, + { 1600, 1200, 70, 87.5 }, + { 1600, 1200, 75, 93.8 }, + { 1600, 1200, 85, 106.3 }, + { 1920, 1440, 60, 90.0 }, + { 1920, 1440, 75, 112.5 } + }; + + if(flag) { /* HSync */ + for (i = 0; i < 4; i++) { + if (ddc->det_mon[i].type == DS_RANGES) { + mon->nHsync = 1; + mon->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h; + mon->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h; + return; + } + } + /* If no sync ranges detected in detailed timing table, we + * derive them from supported VESA modes. */ + myhlow = myhhigh = 0.0; + for(i=0; i<11; i++) { + if(myhtiming[i].whichone == 1) temp = ddc->timings1.t1; + else temp = ddc->timings1.t2; + if(temp & myhtiming[i].mask) { + if((i==0) || (myhlow > myhtiming[i].rate)) + myhlow = myhtiming[i].rate; + } + if(myhtiming[10-i].whichone == 1) temp = ddc->timings1.t1; + else temp = ddc->timings1.t2; + if(temp & myhtiming[10-i].mask) { + if((i==0) || (myhhigh < myhtiming[10-i].rate)) + myhhigh = myhtiming[10-i].rate; + } + } + for(i=0;i<STD_TIMINGS;i++) { + if(ddc->timings2[i].hsize > 256) { + for(j=0; j<8; j++) { + if((ddc->timings2[i].hsize == mystdmodes[j].hsize) && + (ddc->timings2[i].vsize == mystdmodes[j].vsize) && + (ddc->timings2[i].refresh == mystdmodes[j].refresh)) { + if(mystdmodes[j].hsync > myhhigh) + myhhigh = mystdmodes[j].hsync; + } + } + } + } + if((myhhigh) && (myhlow)) { + mon->nHsync = 1; + mon->hsync[0].lo = myhlow - 0.1; + mon->hsync[0].hi = myhhigh; + } + + + } else { /* Vrefresh */ + + for (i = 0; i < 4; i++) { + if (ddc->det_mon[i].type == DS_RANGES) { + mon->nVrefresh = 1; + mon->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v; + mon->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v; + return; + } + } + + myvlow = myvhigh = 0; + for(i=0; i<10; i++) { + if(myvtiming[i].whichone == 1) temp = ddc->timings1.t1; + else temp = ddc->timings1.t2; + if(temp & myvtiming[i].mask) { + if((i==0) || (myvlow > myvtiming[i].rate)) + myvlow = myvtiming[i].rate; + } + if(myvtiming[9-i].whichone == 1) temp = ddc->timings1.t1; + else temp = ddc->timings1.t2; + if(temp & myvtiming[9-i].mask) { + if((i==0) || (myvhigh < myvtiming[9-i].rate)) + myvhigh = myvtiming[9-i].rate; + } + } + for(i=0;i<STD_TIMINGS;i++) { + if(ddc->timings2[i].hsize > 256) { + for(j=0; j<8; j++) { + if((ddc->timings2[i].hsize == mystdmodes[j].hsize) && + (ddc->timings2[i].vsize == mystdmodes[j].vsize) && + (ddc->timings2[i].refresh == mystdmodes[j].refresh)) { + if(mystdmodes[j].refresh > myvhigh) + myvhigh = mystdmodes[j].refresh; + } + } + } + } + if((myvhigh) && (myvlow)) { + mon->nVrefresh = 1; + mon->vrefresh[0].lo = myvlow; + mon->vrefresh[0].hi = myvhigh; + } + + } +} + +static xf86MonPtr +SiSInternalDDC(ScrnInfoPtr pScrn, int crtno) +{ + SISPtr pSiS = SISPTR(pScrn); + USHORT temp, i; + unsigned char buffer[256]; + xf86MonPtr pMonitor = NULL; + + /* TW: If CRT1 is off, skip DDC */ + if((pSiS->CRT1off) && (!crtno)) return NULL; + + temp = SiS_HandleDDC(pSiS->SiS_Pr, pSiS, crtno, 0, &buffer[0]); + if((!temp) || (temp == 0xffff)) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "CRT%d DDC probing failed, now trying via VBE\n", crtno + 1); + return(NULL); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC supported\n", crtno + 1); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT%d DDC level: %s%s%s%s\n", + crtno + 1, + (temp & 0x1a) ? "" : "[none of the supported]", + (temp & 0x02) ? "2 " : "", + (temp & 0x08) ? "3 " : "", + (temp & 0x10) ? "4" : ""); + if(temp & 0x02) { + i = 3; /* Number of retrys */ + do { + temp = SiS_HandleDDC(pSiS->SiS_Pr, pSiS, crtno, 1, &buffer[0]); + } while((temp) && i--); + if(!temp) { + if((pMonitor = xf86InterpretEDID(pScrn->scrnIndex, &buffer[0]))) { + return(pMonitor); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "CRT%d DDC EDID corrupt\n", crtno + 1); + return(NULL); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "CRT%d DDC reading failed\n", crtno + 1); + return(NULL); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "DDC levels 3 and 4 not supported by this driver yet.\n"); + return(NULL); + } + } +} + +static xf86MonPtr +SiSDoPrivateDDC(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + +#ifdef SISDUALHEAD + if((pSiS->DualHeadMode) && (!pSiS->SecondHead)) + return(SiSInternalDDC(pScrn, 1)); + else +#endif + return(SiSInternalDDC(pScrn, 0)); +} + +/* Mandatory */ +static Bool +SISPreInit(ScrnInfoPtr pScrn, int flags) +{ + SISPtr pSiS; + MessageType from; + unsigned char usScratchCR17, CR5F; + unsigned char usScratchCR32; + unsigned long int i; + int temp; + ClockRangePtr clockRanges; + char *mod = NULL; + const char *Sym = NULL; + int pix24flags; +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = NULL; +#endif + DisplayModePtr first, p, n; + DisplayModePtr tempmode, delmode, mymodes; + unsigned char srlockReg,crlockReg; + unsigned char tempreg; + xf86MonPtr pMonitor = NULL; + Bool didddc2; + + vbeInfoPtr pVbe; + VbeInfoBlock *vbe; + + if (flags & PROBE_DETECT) { + if (xf86LoadSubModule(pScrn, "vbe")) { + int index = xf86GetEntityInfo(pScrn->entityList[0])->index; + +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) + if((pVbe = VBEInit(NULL,index))) { +#else + if((pVbe = VBEExtendedInit(NULL,index,0))) { +#endif + ConfiguredMonitor = vbeDoEDID(pVbe, NULL); + vbeFree(pVbe); + } + } + return TRUE; + } + + /* + * Note: This function is only called once at server startup, and + * not at the start of each server generation. This means that + * only things that are persistent across server generations can + * be initialised here. xf86Screens[] is the array of all screens, + * (pScrn is a pointer to one of these). Privates allocated using + * xf86AllocateScrnInfoPrivateIndex() are too, and should be used + * for data that must persist across server generations. + * + * Per-generation data should be allocated with + * AllocateScreenPrivateIndex() from the ScreenInit() function. + */ + + /* Check the number of entities, and fail if it isn't one. */ + if(pScrn->numEntities != 1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Number of entities is not 1\n"); + return FALSE; + } + + /* The vgahw module should be loaded here when needed */ + if(!xf86LoadSubModule(pScrn, "vgahw")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not load vgahw module\n"); + return FALSE; + } + + xf86LoaderReqSymLists(vgahwSymbols, NULL); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "SiS driver (31/01/03-1) by " + "Thomas Winischhofer <thomas@winischhofer.net>\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "See http://www.winischhofer.net/linuxsisvga.shtml " + "for documentation and updates\n"); + + /* Allocate a vgaHWRec */ + if(!vgaHWGetHWRec(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not allocate VGA private\n"); + return FALSE; + } + + /* Allocate the SISRec driverPrivate */ + if(!SISGetRec(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not allocate memory for pSiS private\n"); + return FALSE; + } + pSiS = SISPTR(pScrn); + pSiS->pScrn = pScrn; + +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) + pSiS->IODBase = 0; +#else + pSiS->IODBase = pScrn->domainIOBase; +#endif + + /* Get the entity, and make sure it is PCI. */ + pSiS->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + if(pSiS->pEnt->location.type != BUS_PCI) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Entity's bus type is not PCI\n"); + SISFreeRec(pScrn); + return FALSE; + } + +#ifdef SISDUALHEAD + /* TW: Allocate an entity private if necessary */ + if(xf86IsEntityShared(pScrn->entityList[0])) { + pSiSEnt = xf86GetEntityPrivate(pScrn->entityList[0], + SISEntityIndex)->ptr; + pSiS->entityPrivate = pSiSEnt; + + /* TW: If something went wrong, quit here */ + if ((pSiSEnt->DisableDual) || (pSiSEnt->ErrorAfterFirst)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "First head encountered fatal error, can't continue\n"); + SISFreeRec(pScrn); + return FALSE; + } + } +#endif + + /* Find the PCI info for this screen */ + pSiS->PciInfo = xf86GetPciInfoForEntity(pSiS->pEnt->index); + pSiS->PciTag = pSiS->sishw_ext.PciTag = pciTag(pSiS->PciInfo->bus, + pSiS->PciInfo->device, pSiS->PciInfo->func); + + pSiS->Primary = xf86IsPrimaryPci(pSiS->PciInfo); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "This adapter is %s display adapter\n", + (pSiS->Primary ? "primary" : "secondary")); + + if(pSiS->Primary) { + VGAHWPTR(pScrn)->MapSize = 0x10000; /* Standard 64k VGA window */ + if(!vgaHWMapMem(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not map VGA memory\n"); + SISFreeRec(pScrn); + return FALSE; + } + } + vgaHWGetIOBase(VGAHWPTR(pScrn)); + + /* TW: We "patch" the PIOOffset inside vgaHW in order to force + * the vgaHW module to use our relocated i/o ports. + */ + VGAHWPTR(pScrn)->PIOOffset = pSiS->IODBase + (pSiS->PciInfo->ioBase[2] & 0xFFFC) - 0x380; + + pSiS->pInt = NULL; + if(!pSiS->Primary) { +#if !defined(__alpha__) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Initializing display adapter through int10\n"); +#endif + if(xf86LoadSubModule(pScrn, "int10")) { + xf86LoaderReqSymLists(int10Symbols, NULL); +#if !defined(__alpha__) + pSiS->pInt = xf86InitInt10(pSiS->pEnt->index); +#endif + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not load int10 module\n"); + } + } + +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) + { + resRange vgamem[] = { {ResShrMemBlock,0xA0000,0xAFFFF}, + {ResShrMemBlock,0xB0000,0xB7FFF}, + {ResShrMemBlock,0xB8000,0xBFFFF}, + _END }; + xf86SetOperatingState(vgamem, pSiS->pEnt->index, ResUnusedOpr); + } +#else + xf86SetOperatingState(resVgaMem, pSiS->pEnt->index, ResUnusedOpr); +#endif + + /* Operations for which memory access is required */ + pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; + /* Operations for which I/O access is required */ + pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; + + /* The ramdac module should be loaded here when needed */ + if(!xf86LoadSubModule(pScrn, "ramdac")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not load ramdac module\n"); +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + SISFreeRec(pScrn); + return FALSE; + } + + xf86LoaderReqSymLists(ramdacSymbols, NULL); + + /* Set pScrn->monitor */ + pScrn->monitor = pScrn->confScreen->monitor; + + /* + * Set the Chipset and ChipRev, allowing config file entries to + * override. DANGEROUS! + */ + if (pSiS->pEnt->device->chipset && *pSiS->pEnt->device->chipset) { + pScrn->chipset = pSiS->pEnt->device->chipset; + pSiS->Chipset = xf86StringToToken(SISChipsets, pScrn->chipset); + from = X_CONFIG; + } else if (pSiS->pEnt->device->chipID >= 0) { + pSiS->Chipset = pSiS->pEnt->device->chipID; + pScrn->chipset = (char *)xf86TokenToString(SISChipsets, pSiS->Chipset); + + from = X_CONFIG; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", + pSiS->Chipset); + } else { + from = X_PROBED; + pSiS->Chipset = pSiS->PciInfo->chipType; + pScrn->chipset = (char *)xf86TokenToString(SISChipsets, pSiS->Chipset); + } + if (pSiS->pEnt->device->chipRev >= 0) { + pSiS->ChipRev = pSiS->pEnt->device->chipRev; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", + pSiS->ChipRev); + } else { + pSiS->ChipRev = pSiS->PciInfo->chipRev; + } + pSiS->sishw_ext.jChipRevision = pSiS->ChipRev; + + /* TW: Determine SiS6326 chiprevision. This is not yet used for + * anything, but it will as soon as I found out on which revisions + * the hardware video overlay really works. + * According to SiS the only differences are: + * Chip name Chip type TV-Out MPEG II decoder + * 6326 AGP Rev. G0/H0 no no + * 6326 DVD Rev. D2 yes yes + * 6326 Rev. Cx yes yes + */ + pSiS->SiS6326Flags = 0; + if(pSiS->Chipset == PCI_CHIP_SIS6326) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Chipset is SiS6326 %s (revision 0x%02x)\n", + (pSiS->ChipRev == 0xaf) ? "(Ax)" : + ((pSiS->ChipRev == 0x0a) ? "AGP (G0)" : + ((pSiS->ChipRev == 0x0b) ? "AGP (H0)" : + (((pSiS->ChipRev & 0xf0) == 0xd0) ? "DVD (Dx)" : + (((pSiS->ChipRev & 0xf0) == 0x90) ? "(9x)" : + (((pSiS->ChipRev & 0xf0) == 0xc0) ? "(Cx)" : + "(unknown)"))))), + pSiS->ChipRev); + if((pSiS->ChipRev != 0x0a) && (pSiS->ChipRev != 0x0b)) { + pSiS->SiS6326Flags |= SIS6326_HASTV; + } + } + + + /* + * This shouldn't happen because such problems should be caught in + * SISProbe(), but check it just in case. + */ + if (pScrn->chipset == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ChipID 0x%04X is not recognised\n", pSiS->Chipset); +#ifdef SISDUALHEAD + if (pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + SISFreeRec(pScrn); + return FALSE; + } + if (pSiS->Chipset < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Chipset \"%s\" is not recognised\n", pScrn->chipset); +#ifdef SISDUALHEAD + if (pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + SISFreeRec(pScrn); + return FALSE; + } + + /* TW: Determine chipset and VGA engine type for new mode switching code */ + switch(pSiS->Chipset) { + case PCI_CHIP_SIS300: + pSiS->sishw_ext.jChipType = SIS_300; + pSiS->VGAEngine = SIS_300_VGA; + break; + case PCI_CHIP_SIS630: /* 630 + 730 */ + pSiS->sishw_ext.jChipType = SIS_630; + if(pciReadLong(0x00000000, 0x00) == 0x07301039) { + pSiS->sishw_ext.jChipType = SIS_730; + } + pSiS->VGAEngine = SIS_300_VGA; + break; + case PCI_CHIP_SIS540: + pSiS->sishw_ext.jChipType = SIS_540; + pSiS->VGAEngine = SIS_300_VGA; + break; + case PCI_CHIP_SIS315H: + pSiS->sishw_ext.jChipType = SIS_315H; + pSiS->VGAEngine = SIS_315_VGA; + break; + case PCI_CHIP_SIS315: + /* TW: Override for simplicity */ + pSiS->Chipset = PCI_CHIP_SIS315H; + pSiS->sishw_ext.jChipType = SIS_315; + pSiS->VGAEngine = SIS_315_VGA; + break; + case PCI_CHIP_SIS315PRO: + /* TW: Override for simplicity */ + pSiS->Chipset = PCI_CHIP_SIS315H; + pSiS->sishw_ext.jChipType = SIS_315PRO; + pSiS->VGAEngine = SIS_315_VGA; + break; + case PCI_CHIP_SIS550: + pSiS->sishw_ext.jChipType = SIS_550; + pSiS->VGAEngine = SIS_315_VGA; + break; + case PCI_CHIP_SIS650: /* 650 + 740 */ + pSiS->sishw_ext.jChipType = SIS_650; + pSiS->VGAEngine = SIS_315_VGA; + break; + case PCI_CHIP_SIS330: + pSiS->sishw_ext.jChipType = SIS_330; + pSiS->VGAEngine = SIS_315_VGA; + break; + case PCI_CHIP_SIS530: + pSiS->sishw_ext.jChipType = SIS_530; + pSiS->VGAEngine = SIS_530_VGA; + break; + default: + pSiS->sishw_ext.jChipType = SIS_OLD; + pSiS->VGAEngine = SIS_OLD_VGA; + break; + } + + /* TW: Now check if sisfb is loaded. Since sisfb only supports + * the 300 and 310/325 series, we only do this for these chips. + * We use this for checking where sisfb starts its memory + * heap in order to automatically detect the correct MaxXFBMem + * setting (which normally is given by the option of the same name). + * That only works if sisfb is completely running, ie with + * a video mode (because the fbdev will not be installed otherwise.) + */ + + pSiS->donttrustpdc = FALSE; + pSiS->sisfbpdc = 0; + + if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { + + int fd, i; + sisfb_info mysisfbinfo; + BOOL found = FALSE; + char name[10]; + + i=0; + do { + sprintf(name, "/dev/fb%1d", i); + if((fd = open(name, 'r'))) { + + if(!ioctl(fd, SISFB_GET_INFO, &mysisfbinfo)) { + + if(mysisfbinfo.sisfb_id == SISFB_ID) { + + if((mysisfbinfo.sisfb_version >= 1) && + (mysisfbinfo.sisfb_revision >=5) && + (mysisfbinfo.sisfb_patchlevel >= 8)) { + /* TW: Added PCI bus/slot/func into in sisfb Version 1.5.08. + Check this to make sure we run on the same card as sisfb + */ + if((mysisfbinfo.sisfb_pcibus == pSiS->PciInfo->bus) && + (mysisfbinfo.sisfb_pcislot == pSiS->PciInfo->device) && + (mysisfbinfo.sisfb_pcifunc == pSiS->PciInfo->func) ) { + found = TRUE; + } + } else found = TRUE; + + if(found) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "%s: SiS kernel fb driver (sisfb) %d.%d.%d detected (PCI: %02d:%02d.%d)\n", + &name[5], + mysisfbinfo.sisfb_version, + mysisfbinfo.sisfb_revision, + mysisfbinfo.sisfb_patchlevel, + pSiS->PciInfo->bus, + pSiS->PciInfo->device, + pSiS->PciInfo->func); + /* TW: Added version/rev/pl in sisfb 1.4.0 */ + if(mysisfbinfo.sisfb_version == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Old version of sisfb found. Please update\n"); + } + pSiS->sisfbMem = mysisfbinfo.heapstart; + /* TW: Basically, we can't trust the pdc register if sisfb is loaded */ + pSiS->donttrustpdc = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "sisfb: memory heap starts at %dKB\n", pSiS->sisfbMem); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "sisfb: using video mode 0x%02x\n", mysisfbinfo.fbvidmode); + if((mysisfbinfo.sisfb_version >= 1) && + (mysisfbinfo.sisfb_revision >=5) && + (mysisfbinfo.sisfb_patchlevel >= 6)) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "sisfb: %sreserved hardware cursor, using %s command queue\n", + (mysisfbinfo.sisfb_caps & 0x80) ? "" : "not ", + (mysisfbinfo.sisfb_caps & 0x40) ? "SiS300 series Turbo" : + (mysisfbinfo.sisfb_caps & 0x20) ? "SiS310/325 series AGP" : + (mysisfbinfo.sisfb_caps & 0x10) ? "SiS310/325 series VRAM" : + (mysisfbinfo.sisfb_caps & 0x08) ? "SiS310/325 series MMIO" : + "no"); + } + if((mysisfbinfo.sisfb_version >= 1) && + (mysisfbinfo.sisfb_revision >=5) && + (mysisfbinfo.sisfb_patchlevel >= 10)) { + /* TW: We can trust the pdc value if sisfb is of recent version */ + pSiS->donttrustpdc = FALSE; + if(mysisfbinfo.sisfb_patchlevel >= 11) { + pSiS->sisfbpdc = mysisfbinfo.sisfb_lcdpdc; + } + } + } + } + } + close (fd); + } + i++; + + } while((i <= 7) && (!found)); + } + + /* + * The first thing we should figure out is the depth, bpp, etc. + * TW: Additionally, determine the size of the HWCursor memory + * area. + */ + switch (pSiS->VGAEngine) { + case SIS_300_VGA: + pSiS->CursorSize = 4096; + pix24flags = Support32bppFb | + SupportConvert24to32; + break; + case SIS_315_VGA: + pSiS->CursorSize = 16384; + pix24flags = Support32bppFb | + SupportConvert24to32; + break; + case SIS_530_VGA: + pSiS->CursorSize = 2048; + pix24flags = Support32bppFb | + Support24bppFb | + SupportConvert24to32 | + SupportConvert32to24; + break; + default: + pSiS->CursorSize = 2048; + pix24flags = Support24bppFb | + SupportConvert32to24 | + PreferConvert32to24; + break; + } + +#ifdef SISDUALHEAD + /* TW: In case of Dual Head, we need to determine if we are the "master" head or + * the "slave" head. In order to do that, we set PrimInit to DONE in the + * shared entity at the end of the first initialization. The second + * initialization then knows that some things have already been done. THIS + * ALWAYS ASSUMES THAT THE FIRST DEVICE INITIALIZED IS THE MASTER! + */ + + if(xf86IsEntityShared(pScrn->entityList[0])) { + if(pSiSEnt->lastInstance > 0) { + if(!xf86IsPrimInitDone(pScrn->entityList[0])) { + /* First Head (always CRT2) */ + pSiS->SecondHead = FALSE; + pSiSEnt->pScrn_1 = pScrn; + pSiSEnt->CRT1ModeNo = pSiSEnt->CRT2ModeNo = -1; + pSiS->DualHeadMode = TRUE; + pSiSEnt->DisableDual = FALSE; + pSiSEnt->BIOS = NULL; + pSiSEnt->SiS_Pr = NULL; + } else { + /* Second Head (always CRT1) */ + pSiS->SecondHead = TRUE; + pSiSEnt->pScrn_2 = pScrn; + pSiS->DualHeadMode = TRUE; + } + } else { + /* TW: Only one screen in config file - disable dual head mode */ + pSiS->SecondHead = FALSE; + pSiS->DualHeadMode = FALSE; + pSiSEnt->DisableDual = TRUE; + } + } else { + /* TW: Entity is not shared - disable dual head mode */ + pSiS->SecondHead = FALSE; + pSiS->DualHeadMode = FALSE; + } +#endif + + pSiS->ForceCursorOff = FALSE; + + /* TW: Allocate SiS_Private (for mode switching code) and initialize it */ + pSiS->SiS_Pr = NULL; +#ifdef SISDUALHEAD + if(pSiSEnt) { + if(pSiSEnt->SiS_Pr) pSiS->SiS_Pr = pSiSEnt->SiS_Pr; + } +#endif + if(!pSiS->SiS_Pr) { + if(!(pSiS->SiS_Pr = xnfcalloc(sizeof(SiS_Private), 1))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not allocate memory for SiS_Pr private\n"); +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + SISFreeRec(pScrn); + return FALSE; + } +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->SiS_Pr = pSiS->SiS_Pr; +#endif + memset(pSiS->SiS_Pr, 0, sizeof(SiS_Private)); + } + pSiS->SiS_Pr->SiS_Backup70xx = 0xff; + pSiS->SiS_Pr->SiS_CHOverScan = -1; + pSiS->SiS_Pr->SiS_ChSW = FALSE; + pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; + + /* TW: Get our relocated IO registers */ + pSiS->RelIO = (pSiS->PciInfo->ioBase[2] & 0xFFFC) + pSiS->IODBase; + pSiS->sishw_ext.ulIOAddress = pSiS->RelIO + 0x30; + xf86DrvMsg(pScrn->scrnIndex, from, "Relocated IO registers at 0x%lX\n", + (unsigned long)pSiS->RelIO); + + /* TW: Initialize SiS Port Reg definitions for externally used + * BIOS emulation (init.c/init301.c) functions. + */ + SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO + 0x30); + + /* TW: The following identifies the old chipsets. This is only + * partly used since the really old chips are not supported, + * but I keep it here for future use. + */ + if(pSiS->VGAEngine == SIS_OLD_VGA || pSiS->VGAEngine == SIS_530_VGA) { + switch(pSiS->Chipset) { + case PCI_CHIP_SG86C205: /* Just for making it complete */ + { + unsigned char temp; + sisSaveUnlockExtRegisterLock(pSiS, &srlockReg, &crlockReg); + inSISIDXREG(SISSR, 0x10, temp); + if(temp & 0x80) pSiS->oldChipset = OC_SIS6205B; + else pSiS->oldChipset = (pSiS->ChipRev == 0x11) ? + OC_SIS6205C : OC_SIS6205A; + break; + } + case PCI_CHIP_SIS82C204: /* Just for making it complete */ + pSiS->oldChipset = OC_SIS82204; break; + case 0x6225: /* Just for making it complete */ + pSiS->oldChipset = OC_SIS6225; break; + case PCI_CHIP_SIS5597: + pSiS->oldChipset = OC_SIS5597; break; + case PCI_CHIP_SIS6326: + pSiS->oldChipset = OC_SIS6326; break; + case PCI_CHIP_SIS530: + if((pSiS->ChipRev & 0x0f) < 0x0a) + pSiS->oldChipset = OC_SIS530A; + else pSiS->oldChipset = OC_SIS530B; + break; + default: + pSiS->oldChipset = OC_UNKNOWN; + } + } + + if(!xf86SetDepthBpp(pScrn, 8, 8, 8, pix24flags)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "xf86SetDepthBpp() error\n"); +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + SISFreeRec(pScrn); + return FALSE; + } + + /* Check that the returned depth is one we support */ + temp = 0; + switch(pScrn->depth) { + case 8: + case 16: + case 24: + break; + case 15: + if((pSiS->VGAEngine == SIS_300_VGA) || + (pSiS->VGAEngine == SIS_315_VGA)) + temp = 1; + break; + default: + temp = 1; + } + + if(temp) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by this driver/chipset\n", + pScrn->depth); + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + SISFreeRec(pScrn); + return FALSE; + } + + xf86PrintDepthBpp(pScrn); + + /* Get the depth24 pixmap format */ + if(pScrn->depth == 24 && pix24bpp == 0) + pix24bpp = xf86GetBppFromDepth(pScrn, 24); + + /* + * This must happen after pScrn->display has been set because + * xf86SetWeight references it. + */ + if(pScrn->depth > 8) { + /* The defaults are OK for us */ + rgb zeros = {0, 0, 0}; + + if(!xf86SetWeight(pScrn, zeros, zeros)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "xf86SetWeight() error\n"); +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + SISFreeRec(pScrn); + return FALSE; + } else { + Bool ret = FALSE; + switch(pScrn->depth) { + case 15: + if((pScrn->weight.red != 5) || + (pScrn->weight.green != 5) || + (pScrn->weight.blue != 5)) ret = TRUE; + break; + case 16: + if((pScrn->weight.red != 5) || + (pScrn->weight.green != 6) || + (pScrn->weight.blue != 5)) ret = TRUE; + break; + case 24: + if((pScrn->weight.red != 8) || + (pScrn->weight.green != 8) || + (pScrn->weight.blue != 8)) ret = TRUE; + break; + } + if(ret) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RGB Weight %d%d%d at depth %d not supported by hardware\n", + pScrn->weight.red, pScrn->weight.green, + pScrn->weight.blue, pScrn->depth); +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + SISFreeRec(pScrn); + return FALSE; + } + } + } + + /* TW: Set the current layout parameters */ + pSiS->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; + pSiS->CurrentLayout.depth = pScrn->depth; + /* (Inside this function, we can use pScrn's contents anyway) */ + + if(!xf86SetDefaultVisual(pScrn, -1)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "xf86SetDefaultVisual() error\n"); +#ifdef SISDUALHEAD + if (pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + SISFreeRec(pScrn); + return FALSE; + } else { + /* We don't support DirectColor at > 8bpp */ + if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual " + "(%s) is not supported at depth %d\n", + xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); +#ifdef SISDUALHEAD + if (pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + SISFreeRec(pScrn); + return FALSE; + } + } + + /* + * The cmap layer needs this to be initialised. + */ + { + Gamma zeros = {0.0, 0.0, 0.0}; + + if(!xf86SetGamma(pScrn, zeros)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "xf86SetGamma() error\n"); +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + SISFreeRec(pScrn); + return FALSE; + } + } + + /* We use a programamble clock */ + pScrn->progClock = TRUE; + + /* Set the bits per RGB for 8bpp mode */ + if(pScrn->depth == 8) { + pScrn->rgbBits = 6; + } + + pSiS->ddc1Read = SiSddc1Read; + + from = X_DEFAULT; + + /* Unlock registers */ + sisSaveUnlockExtRegisterLock(pSiS, &srlockReg, &crlockReg); + + /* TW: We need no backup area (300/310/325 new mode switching code) */ + pSiS->sishw_ext.pSR = NULL; + pSiS->sishw_ext.pCR = NULL; + + /* TW: Read BIOS for 300 and 310/325 series customization */ + pSiS->sishw_ext.pjVirtualRomBase = NULL; + pSiS->BIOS = NULL; + pSiS->sishw_ext.UseROM = FALSE; + + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { +#ifdef SISDUALHEAD + if(pSiSEnt) { + if(pSiSEnt->BIOS) { + pSiS->BIOS = pSiSEnt->BIOS; + pSiS->sishw_ext.pjVirtualRomBase = pSiS->BIOS; + } + } +#endif + if(!pSiS->BIOS) { + if(!(pSiS->BIOS = xcalloc(1, BIOS_SIZE))) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Could not allocate memory for video BIOS image\n"); + } else { + unsigned long segstart; + unsigned short romptr; + BOOLEAN found; + int i; + static const char sis_rom_sig[] = "Silicon Integrated Systems"; + static const char *sis_sig[10] = { + "300", "540", "630", "730", + "315", "315", "315", "5315", "6325", + "Xabre" + }; + static const unsigned short sis_nums[10] = { + SIS_300, SIS_540, SIS_630, SIS_730, + SIS_315PRO, SIS_315H, SIS_315, SIS_550, SIS_650, + SIS_330 + }; + + found = FALSE; + for(segstart=BIOS_BASE; segstart<0x000f0000; segstart+=0x00001000) { + +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) + if(xf86ReadBIOS(segstart, 0, pSiS->BIOS, BIOS_SIZE) != BIOS_SIZE) continue; +#else + if(xf86ReadDomainMemory(pSiS->PciTag, segstart, BIOS_SIZE, pSiS->BIOS) != BIOS_SIZE) continue; +#endif + + if((pSiS->BIOS[0] != 0x55) || (pSiS->BIOS[1] != 0xaa)) continue; + + romptr = pSiS->BIOS[0x12] | (pSiS->BIOS[0x13] << 8); + if(romptr > (BIOS_SIZE - strlen(sis_rom_sig))) continue; + if(strncmp(sis_rom_sig, (char *)&pSiS->BIOS[romptr], strlen(sis_rom_sig)) != 0) continue; + + romptr = pSiS->BIOS[0x14] | (pSiS->BIOS[0x15] << 8); + if(romptr > (BIOS_SIZE - 5)) continue; + for(i = 0; (i < 10) && (!found); i++) { + if(strncmp(sis_sig[i], (char *)&pSiS->BIOS[romptr], strlen(sis_sig[i])) == 0) { + if(sis_nums[i] == pSiS->sishw_ext.jChipType) { + found = TRUE; + break; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Ignoring BIOS for SiS %s at %p\n", sis_sig[i], segstart); + } + } + } + if(found) break; + } + + if(!found) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Could not find/read video BIOS\n"); + xfree(pSiS->BIOS); + pSiS->BIOS = NULL; + } else { +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->BIOS = pSiS->BIOS; +#endif + pSiS->sishw_ext.pjVirtualRomBase = pSiS->BIOS; + romptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Video BIOS version \"%7s\" found at %p\n", + &pSiS->BIOS[romptr], segstart); + } + + } + } + if(pSiS->BIOS) pSiS->sishw_ext.UseROM = TRUE; + else pSiS->sishw_ext.UseROM = FALSE; + } + + /* Evaluate options */ + SiSOptions(pScrn); + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(!pSiS->SecondHead) { + /* TW: Copy some option settings to entity private */ + pSiSEnt->HWCursor = pSiS->HWCursor; + pSiSEnt->ForceCRT2Type = pSiS->ForceCRT2Type; + pSiSEnt->ForceTVType = pSiS->ForceTVType; + pSiSEnt->TurboQueue = pSiS->TurboQueue; + pSiSEnt->PDC = pSiS->PDC; + pSiSEnt->OptTVStand = pSiS->OptTVStand; + pSiSEnt->NonDefaultPAL = pSiS->NonDefaultPAL; + pSiSEnt->OptTVOver = pSiS->OptTVOver; + pSiSEnt->OptTVSOver = pSiS->OptTVSOver; + pSiSEnt->OptROMUsage = pSiS->OptROMUsage; + pSiSEnt->DSTN = pSiS->DSTN; + pSiSEnt->XvOnCRT2 = pSiS->XvOnCRT2; + pSiSEnt->NoAccel = pSiS->NoAccel; + pSiSEnt->NoXvideo = pSiS->NoXvideo; + pSiSEnt->forceCRT1 = pSiS->forceCRT1; + pSiSEnt->chtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; + pSiSEnt->chtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; + pSiSEnt->chtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; + pSiSEnt->chtvchromabandwidth = pSiS->chtvchromabandwidth; + pSiSEnt->chtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; + pSiSEnt->chtvtextenhance = pSiS->chtvtextenhance; + pSiSEnt->chtvcontrast = pSiS->chtvcontrast; + pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; + pSiSEnt->sistvedgeenhance = pSiS->sistvedgeenhance; + pSiSEnt->sistvantiflicker = pSiS->sistvantiflicker; + pSiSEnt->sistvsaturation = pSiS->sistvsaturation; + pSiSEnt->tvxpos = pSiS->tvxpos; + pSiSEnt->tvypos = pSiS->tvypos; + pSiSEnt->restorebyset = pSiS->restorebyset; + } else { + /* We always use same cursor type on both screens */ + if(pSiS->HWCursor != pSiSEnt->HWCursor) { + pSiS->HWCursor = pSiSEnt->HWCursor; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent HWCursor setting\n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Master head ruled: HWCursor shall be %s\n", + pSiS->HWCursor ? "enabled" : "disabled"); + } + /* We need to use identical CRT2 Type setting */ + if(pSiS->ForceCRT2Type != pSiSEnt->ForceCRT2Type) { + if(pSiS->ForceCRT2Type != CRT2_DEFAULT) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Ignoring inconsistent ForceCRT2Type setting. Master head rules\n"); + } + pSiS->ForceCRT2Type = pSiSEnt->ForceCRT2Type; + } + if(pSiS->ForceTVType != pSiSEnt->ForceTVType) { + if(pSiS->ForceTVType != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Ignoring inconsistent ForceTVType setting. Master head rules\n"); + } + pSiS->ForceTVType = pSiSEnt->ForceTVType; + } + /* We need identical TurboQueue setting */ + if(pSiS->TurboQueue != pSiSEnt->TurboQueue) { + pSiS->TurboQueue = pSiSEnt->TurboQueue; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent TurboQueue setting\n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Master head ruled: Turboqueue shall be %s\n", + pSiS->TurboQueue ? "enabled" : "disabled"); + } + /* We need identical PDC setting */ + if(pSiS->PDC != pSiSEnt->PDC) { + pSiS->PDC = pSiSEnt->PDC; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent PanelDelayCompensation setting\n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Master head ruled: PanelDelayCompensation shall be %d%s\n", + pSiS->PDC, + (pSiS->PDC == -1) ? " (autodetected)" : ""); + } + /* We need identical TVStandard setting */ + if( (pSiS->OptTVStand != pSiSEnt->OptTVStand) || + (pSiS->NonDefaultPAL != pSiSEnt->NonDefaultPAL) ) { + if(pSiS->OptTVStand != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent TVStandard setting\n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Master head ruled: TVStandard shall be %s\n", + (pSiSEnt->OptTVStand ? + ( (pSiSEnt->NonDefaultPAL == -1) ? "PAL" : + ((pSiSEnt->NonDefaultPAL) ? "PALM" : "PALN") ) + : "NTSC")); + } + pSiS->OptTVStand = pSiSEnt->OptTVStand; + pSiS->NonDefaultPAL = pSiSEnt->NonDefaultPAL; + } + /* We need identical UseROMData setting */ + if(pSiS->OptROMUsage != pSiSEnt->OptROMUsage) { + if(pSiS->OptROMUsage != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent UseROMData setting\n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Master head ruled: Video ROM data usage shall be %s\n", + pSiSEnt->OptROMUsage ? "enabled" : "disabled"); + } + pSiS->OptROMUsage = pSiSEnt->OptROMUsage; + } + /* We need identical DSTN setting */ + if(pSiS->DSTN != pSiSEnt->DSTN) { + pSiS->DSTN = pSiSEnt->DSTN; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent DSTN setting\n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Master head ruled: DSTN shall be %s\n", + pSiS->DSTN ? "enabled" : "disabled"); + } + /* We need identical XvOnCRT2 setting */ + if(pSiS->XvOnCRT2 != pSiSEnt->XvOnCRT2) { + pSiS->XvOnCRT2 = pSiSEnt->XvOnCRT2; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent XvOnCRT2 setting\n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Master head ruled: Xv shall be used on CRT%d\n", + pSiS->XvOnCRT2 ? 2 : 1); + } + /* We need identical NoAccel setting */ + if(pSiS->NoAccel != pSiSEnt->NoAccel) { + pSiS->NoAccel = pSiSEnt->NoAccel; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent NoAccel setting\n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Master head ruled: Acceleration shall be %s\n", + pSiS->NoAccel ? "disabled" : "enabled"); + } + /* We need identical ForceCRT1 setting */ + if(pSiS->forceCRT1 != pSiSEnt->forceCRT1) { + if(pSiS->forceCRT1 != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent ForceCRT1 setting\n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Master head ruled: CRT1 shall be %s\n", + pSiSEnt->forceCRT1 ? "enabled" : "disabled"); + } + pSiS->forceCRT1 = pSiSEnt->forceCRT1; + } + /* We need identical TVOverscan setting */ + if(pSiS->OptTVOver != pSiSEnt->OptTVOver) { + if(pSiS->OptTVOver != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent CHTVOverscan setting\n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Master head ruled: CHTVOverscan shall be %s\n", + pSiSEnt->OptTVOver ? "true (=overscan)" : "false (=underscan)"); + } + pSiS->OptTVOver = pSiSEnt->OptTVOver; + } + /* We need identical TVSOverscan setting */ + if(pSiS->OptTVSOver != pSiSEnt->OptTVSOver) { + if(pSiS->OptTVSOver != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent CHTVSuperOverscan setting\n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Master head ruled: CHTVSuperOverscan shall be %s\n", + pSiSEnt->OptTVSOver ? "true" : "false"); + } + pSiS->OptTVSOver = pSiSEnt->OptTVSOver; + } + /* We need identical TV settings */ + if(pSiS->chtvtype != pSiSEnt->chtvtype) { + if(pSiS->chtvtype != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent CHTVType setting; set to %s\n", + (pSiSEnt->chtvtype) ? "SCART" : "HDTV"); + } + pSiS->chtvtype = pSiSEnt->chtvtype; + } + if(pSiS->chtvlumabandwidthcvbs != pSiSEnt->chtvlumabandwidthcvbs) { + if(pSiS->chtvlumabandwidthcvbs != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent CHTVLumaBandWidthCVBS setting; set to %d\n", + pSiSEnt->chtvlumabandwidthcvbs); + } + pSiS->chtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; + } + if(pSiS->chtvlumabandwidthsvideo != pSiSEnt->chtvlumabandwidthsvideo) { + if(pSiS->chtvlumabandwidthsvideo != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent CHTVLumaBandWidthSVIDEO setting; set to %d\n", + pSiSEnt->chtvlumabandwidthsvideo); + } + pSiS->chtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; + } + if(pSiS->chtvlumaflickerfilter != pSiSEnt->chtvlumaflickerfilter) { + if(pSiS->chtvlumaflickerfilter != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent CHTVLumaFlickerFilter setting; set to %d\n", + pSiSEnt->chtvlumaflickerfilter); + } + pSiS->chtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; + } + if(pSiS->chtvchromabandwidth != pSiSEnt->chtvchromabandwidth) { + if(pSiS->chtvchromabandwidth != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent CHTVChromaBandWidth setting; set to %d\n", + pSiSEnt->chtvchromabandwidth); + } + pSiS->chtvchromabandwidth = pSiSEnt->chtvchromabandwidth; + } + if(pSiS->chtvchromaflickerfilter != pSiSEnt->chtvchromaflickerfilter) { + if(pSiS->chtvchromaflickerfilter != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent CHTVChromaFlickerFilter setting; set to %d\n", + pSiSEnt->chtvchromaflickerfilter); + } + pSiS->chtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; + } + if(pSiS->chtvcvbscolor != pSiSEnt->chtvcvbscolor) { + if(pSiS->chtvcvbscolor != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent CHTVCVBSColor setting; set to %s\n", + pSiSEnt->chtvcvbscolor ? "true" : "false"); + } + pSiS->chtvcvbscolor = pSiSEnt->chtvcvbscolor; + } + if(pSiS->chtvtextenhance != pSiSEnt->chtvtextenhance) { + if(pSiS->chtvtextenhance != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent CHTVTextEnhance setting; set to %d\n", + pSiSEnt->chtvtextenhance); + } + pSiS->chtvtextenhance = pSiSEnt->chtvtextenhance; + } + if(pSiS->chtvcontrast != pSiSEnt->chtvcontrast) { + if(pSiS->chtvcontrast != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent CHTVContrast setting; set to %d\n", + pSiSEnt->chtvcontrast); + } + pSiS->chtvcontrast = pSiSEnt->chtvcontrast; + } + if(pSiS->sistvedgeenhance != pSiSEnt->sistvedgeenhance) { + if(pSiS->sistvedgeenhance != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent SISTVEdgeEnhance setting; set to %d\n", + pSiSEnt->sistvedgeenhance); + } + pSiS->sistvedgeenhance = pSiSEnt->sistvedgeenhance; + } + if(pSiS->sistvantiflicker != pSiSEnt->sistvantiflicker) { + if(pSiS->sistvantiflicker != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent SISTVAntiFlicker setting; set to %d\n", + pSiSEnt->sistvantiflicker); + } + pSiS->sistvantiflicker = pSiSEnt->sistvantiflicker; + } + if(pSiS->sistvsaturation != pSiSEnt->sistvsaturation) { + if(pSiS->sistvsaturation != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent SISTVSaturation setting; set to %d\n", + pSiSEnt->sistvsaturation); + } + pSiS->sistvsaturation = pSiSEnt->sistvsaturation; + } + if(pSiS->tvxpos != pSiSEnt->tvxpos) { + if(pSiS->tvxpos != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent TVXPosOffset setting; set to %d\n", + pSiSEnt->tvxpos); + } + pSiS->tvxpos = pSiSEnt->tvxpos; + } + if(pSiS->tvypos != pSiSEnt->tvypos) { + if(pSiS->tvypos != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Ignoring inconsistent TVYPosOffset setting; set to %d\n", + pSiSEnt->tvypos); + } + pSiS->tvypos = pSiSEnt->tvypos; + } + if(pSiS->restorebyset != pSiSEnt->restorebyset) { + pSiS->restorebyset = pSiSEnt->restorebyset; + } + } + } +#endif + /* TW: Handle UseROMData and NoOEM options */ + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + from = X_PROBED; + if(pSiS->OptROMUsage == 0) { + pSiS->sishw_ext.UseROM = FALSE; + from = X_CONFIG; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Video ROM data usage is %s\n", + pSiS->sishw_ext.UseROM ? "enabled" : "disabled"); + + if(!pSiS->OptUseOEM) + xf86DrvMsg(pScrn->scrnIndex, from, "Internal OEM LCD/TV data usage is disabled\n"); + + if(pSiS->sbiosn) { + if(pSiS->BIOS) { + FILE *fd = NULL; + int i; + if((fd = fopen(pSiS->sbiosn, "w" ))) { + i = fwrite(pSiS->BIOS, 65536, 1, fd); + fclose(fd); + } + } + xfree(pSiS->sbiosn); + } + } + + /* Do basic configuration */ + SiSSetup(pScrn); + + from = X_PROBED; + if (pSiS->pEnt->device->MemBase != 0) { + /* + * XXX Should check that the config file value matches one of the + * PCI base address values. + */ + pSiS->FbAddress = pSiS->pEnt->device->MemBase; + from = X_CONFIG; + } else { + pSiS->FbAddress = pSiS->PciInfo->memBase[0] & 0xFFFFFFF0; + } + + pSiS->realFbAddress = pSiS->FbAddress; + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) + xf86DrvMsg(pScrn->scrnIndex, from, "Global linear framebuffer at 0x%lX\n", + (unsigned long)pSiS->FbAddress); + else +#endif + xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", + (unsigned long)pSiS->FbAddress); + + if (pSiS->pEnt->device->IOBase != 0) { + /* + * XXX Should check that the config file value matches one of the + * PCI base address values. + */ + pSiS->IOAddress = pSiS->pEnt->device->IOBase; + from = X_CONFIG; + } else { + pSiS->IOAddress = pSiS->PciInfo->memBase[1] & 0xFFFFFFF0; + } + + xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n", + (unsigned long)pSiS->IOAddress); + pSiS->sishw_ext.bIntegratedMMEnabled = TRUE; + + /* Register the PCI-assigned resources. */ + if(xf86RegisterResources(pSiS->pEnt->index, NULL, ResExclusive)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "xf86RegisterResources() found resource conflicts\n"); +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); + SISFreeRec(pScrn); + return FALSE; + } + + from = X_PROBED; + if (pSiS->pEnt->device->videoRam != 0) { + pScrn->videoRam = pSiS->pEnt->device->videoRam; + from = X_CONFIG; + } + + pSiS->RealVideoRam = pScrn->videoRam; + if((pSiS->Chipset == PCI_CHIP_SIS6326) + && (pScrn->videoRam > 4096) + && (from != X_CONFIG)) { + pScrn->videoRam = 4096; + xf86DrvMsg(pScrn->scrnIndex, from, + "SiS6326: Detected %d KB VideoRAM, limiting to %d KB\n", + pSiS->RealVideoRam, pScrn->videoRam); + } else + xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d KB\n", + pScrn->videoRam); + + if((pSiS->Chipset == PCI_CHIP_SIS6326) && + (pScrn->videoRam > 4096)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "SiS6326 engines do not support more than 4096KB RAM, therefore\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "TurboQueue, HWCursor, 2D acceleration and XVideo are disabled.\n"); + pSiS->TurboQueue = FALSE; + pSiS->HWCursor = FALSE; + pSiS->NoXvideo = TRUE; + pSiS->NoAccel = TRUE; + } + + pSiS->FbMapSize = pSiS->availMem = pScrn->videoRam * 1024; + pSiS->sishw_ext.ulVideoMemorySize = pScrn->videoRam * 1024; + pSiS->sishw_ext.bSkipDramSizing = TRUE; + + /* TW: Calculate real availMem according to Accel/TurboQueue and + * HWCursur setting. Also, initialize some variables used + * in other modules. + */ + pSiS->cursorOffset = 0; + switch (pSiS->VGAEngine) { + case SIS_300_VGA: + pSiS->TurboQueueLen = 512; + if(pSiS->TurboQueue) { + pSiS->availMem -= (pSiS->TurboQueueLen*1024); + pSiS->cursorOffset = 512; + } + if(pSiS->HWCursor) { + pSiS->availMem -= pSiS->CursorSize; + if(pSiS->OptUseColorCursor) pSiS->availMem -= pSiS->CursorSize; + } + pSiS->CmdQueLenMask = 0xFFFF; + pSiS->CmdQueLenFix = 0; + pSiS->cursorBufferNum = 0; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; +#endif + break; + case SIS_315_VGA: + if(pSiS->TurboQueue) { + pSiS->availMem -= (512*1024); /* Command Queue is 512k */ + pSiS->cursorOffset = 512; + } + if(pSiS->HWCursor) { + pSiS->availMem -= pSiS->CursorSize; + if(pSiS->OptUseColorCursor) pSiS->availMem -= pSiS->CursorSize; + } + pSiS->cursorBufferNum = 0; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->cursorBufferNum = 0; +#endif + break; + default: + /* TW: cursorOffset not used in cursor functions for 530 and + * older chips, because the cursor is *above* the TQ. + * On 5597 and older revisions of the 6326, the TQ is + * max 32K, on newer 6326 revisions and the 530 either 30 + * (or 32?) or 62K (or 64?). However, to make sure, we + * use only 30K (or 32?), but reduce the available memory + * by 64, and locate the TQ at the beginning of this last + * 64K block. (We do this that way even when using the + * HWCursor, because the cursor only takes 2K, and the queue + * does not seem to last that far anyway.) + * The TQ must be located at 32KB boundaries. + */ + if(pSiS->RealVideoRam < 3072) { + if(pSiS->TurboQueue) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not enough video RAM for TurboQueue. TurboQueue disabled\n"); + } + pSiS->TurboQueue = FALSE; + } + pSiS->CmdQueMaxLen = 32; + if(pSiS->TurboQueue) { + pSiS->availMem -= (64*1024); + pSiS->CmdQueMaxLen = 900; /* TW: To make sure; should be 992 */ + } else if (pSiS->HWCursor) { + pSiS->availMem -= pSiS->CursorSize; + } + if(pSiS->Chipset == PCI_CHIP_SIS530) { + /* TW: Check if Flat Panel is enabled */ + inSISIDXREG(SISSR, 0x0e, tempreg); + if(!tempreg & 0x04) pSiS->availMem -= pSiS->CursorSize; + + /* TW: Set up mask for MMIO register */ + pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x1FFF : 0x00FF; + } else { + /* TW: TQ is never used on 6326/5597, because the accelerator + * always Syncs. So this is just cosmentic work. (And I + * am not even sure that 0x7fff is correct. MMIO 0x83a8 + * holds 0xec0 if (30k) TQ is enabled, 0x20 if TQ disabled. + * The datasheet has no real explanation on the queue length + * if the TQ is enabled. Not syncing and waiting for a + * suitable queue length instead does not work. + */ + pSiS->CmdQueLenMask = (pSiS->TurboQueue) ? 0x7FFF : 0x003F; + } + + /* TW: This is to be subtracted from MMIO queue length register contents + * for getting the real Queue length. + */ + pSiS->CmdQueLenFix = (pSiS->TurboQueue) ? 32 : 0; + } + +#ifdef SISDUALHEAD + /* TW: In dual head mode, we share availMem equally - so align it + * to 8KB; this way, the address of the FB of the second + * head is aligned to 4KB for mapping. + */ + if (pSiS->DualHeadMode) + pSiS->availMem &= 0xFFFFE000; +#endif + + /* TW: Check MaxXFBMem setting */ +#ifdef SISDUALHEAD + /* TW: Since DRI is not supported in dual head mode, we + don't need MaxXFBMem setting. */ + if (pSiS->DualHeadMode) { + if(pSiS->maxxfbmem) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "MaxXFBMem not used in Dual Head mode. Using all VideoRAM.\n"); + } + pSiS->maxxfbmem = pSiS->availMem; + } else +#endif + if (pSiS->maxxfbmem) { + if (pSiS->maxxfbmem > pSiS->availMem) { + if (pSiS->sisfbMem) { + pSiS->maxxfbmem = pSiS->sisfbMem * 1024; + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Invalid MaxXFBMem setting. Using sisfb heap start information\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Invalid MaxXFBMem setting. Using all VideoRAM for framebuffer\n"); + pSiS->maxxfbmem = pSiS->availMem; + } + } else if (pSiS->sisfbMem) { + if (pSiS->maxxfbmem > pSiS->sisfbMem * 1024) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "MaxXFBMem beyond sisfb heap start. Using sisfb heap start information\n"); + pSiS->maxxfbmem = pSiS->sisfbMem * 1024; + } + } + } else if (pSiS->sisfbMem) { + pSiS->maxxfbmem = pSiS->sisfbMem * 1024; + } + else pSiS->maxxfbmem = pSiS->availMem; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %dK of framebuffer memory\n", + pSiS->maxxfbmem / 1024); + + /* TW: Check if the chipset supports two video overlays */ + pSiS->Flags650 = 0; + if ( (!pSiS->NoXvideo) && + ( pSiS->VGAEngine == SIS_300_VGA || + pSiS->VGAEngine == SIS_315_VGA || + pSiS->Chipset == PCI_CHIP_SIS530 || + pSiS->Chipset == PCI_CHIP_SIS6326 || + pSiS->Chipset == PCI_CHIP_SIS5597 ) ) { + pSiS->hasTwoOverlays = FALSE; + switch (pSiS->Chipset) { + case PCI_CHIP_SIS300: + case PCI_CHIP_SIS630: + case PCI_CHIP_SIS550: + case PCI_CHIP_SIS330: /* ? */ + pSiS->hasTwoOverlays = TRUE; + break; + case PCI_CHIP_SIS650: + { + static const char *id650str[] = { + "0", "0", "0", "0", + "0 A0 AA", "0 A2 CA", "0", "0", + "0M A0", "0M A1 AA", "1 A0 AA", "1 A1 AA" + "0", "0", "0", "0" + }; + inSISIDXREG(SISCR, 0x5F, CR5F); + CR5F &= 0xf0; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "SiS650 revision ID %x (SiS65%s)\n", CR5F, id650str[CR5F >> 4]); + if((CR5F == 0x80) || (CR5F == 0x90) || (CR5F == 0xa0) || (CR5F == 0xb0)) { + pSiS->hasTwoOverlays = TRUE; /* TW: This is an M650 or 651 */ + pSiS->Flags650 |= SiS650_LARGEOVERLAY; + } + break; + } + } + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Hardware supports %s video overlay%s\n", + pSiS->hasTwoOverlays ? "two" : "one", + pSiS->hasTwoOverlays ? "s" : ""); + } + + /* TW: Backup VB connection and CRT1 on/off register */ + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + inSISIDXREG(SISCR, 0x32, pSiS->oldCR32); + inSISIDXREG(SISCR, 0x17, pSiS->oldCR17); + pSiS->postVBCR32 = pSiS->oldCR32; + } + + if(pSiS->forceCRT1 != -1) { + if(pSiS->forceCRT1) pSiS->CRT1off = 0; + else pSiS->CRT1off = 1; + } else pSiS->CRT1off = -1; + + /* TW: There are some strange machines out there which require a special + * manupulation of ISA bridge registers in order to make the Chrontel + * work. Try to find out if we're running on such a machine. + */ + pSiS->SiS_Pr->SiS_ChSW = FALSE; + if(pSiS->Chipset == PCI_CHIP_SIS630) { + int i=0; + do { + if(mychswtable[i].subsysVendor == pSiS->PciInfo->subsysVendor && + mychswtable[i].subsysCard == pSiS->PciInfo->subsysCard) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "PCI card/vendor found in list for Chrontel/ISA bridge poking\n"); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Vendor: %s (ID %04x)\n", + mychswtable[i].vendorName, pSiS->PciInfo->subsysCard); + pSiS->SiS_Pr->SiS_ChSW = TRUE; + } + i++; + } while(mychswtable[i].subsysVendor != 0); + } + + /* TW: Detect video bridge and sense connected devices */ + SISVGAPreInit(pScrn); + /* TW: Detect CRT1 */ + SISCRT1PreInit(pScrn); + /* TW: Detect CRT2-LCD and LCD size */ + SISLCDPreInit(pScrn); + /* TW: Detect CRT2-TV and PAL/NTSC mode */ + SISTVPreInit(pScrn); + /* TW: Detect CRT2-VGA */ + SISCRT2PreInit(pScrn); + + /* TW: Backup detected CRT2 devices */ + pSiS->detectedCRT2Devices = pSiS->VBFlags & (CRT2_LCD | CRT2_TV | CRT2_VGA); + + /* TW: Eventually overrule detected CRT2 type */ + if(pSiS->ForceCRT2Type == CRT2_DEFAULT) { + if(pSiS->VBFlags & CRT2_VGA) + pSiS->ForceCRT2Type = CRT2_VGA; + else if(pSiS->VBFlags & CRT2_LCD) + pSiS->ForceCRT2Type = CRT2_LCD; + else if(pSiS->VBFlags & CRT2_TV) + pSiS->ForceCRT2Type = CRT2_TV; + } + + switch(pSiS->ForceCRT2Type) { + case CRT2_TV: + pSiS->VBFlags = pSiS->VBFlags & ~(CRT2_LCD | CRT2_VGA); + if(pSiS->VBFlags & VB_VIDEOBRIDGE) + pSiS->VBFlags = pSiS->VBFlags | CRT2_TV; + else + pSiS->VBFlags = pSiS->VBFlags & ~(CRT2_TV); + break; + case CRT2_LCD: + pSiS->VBFlags = pSiS->VBFlags & ~(CRT2_TV | CRT2_VGA); + if((pSiS->VBFlags & VB_VIDEOBRIDGE) && (pSiS->VBLCDFlags)) + pSiS->VBFlags = pSiS->VBFlags | CRT2_LCD; + else { + pSiS->VBFlags = pSiS->VBFlags & ~(CRT2_LCD); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Can't force CRT2 to LCD, no panel detected\n"); + } + break; + case CRT2_VGA: + if(pSiS->VBFlags & VB_LVDS) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "LVDS does not support secondary VGA\n"); + break; + } + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "SiS30xLV bridge does not support secondary VGA\n"); + break; + } + pSiS->VBFlags = pSiS->VBFlags & ~(CRT2_TV | CRT2_LCD); + if(pSiS->VBFlags & VB_VIDEOBRIDGE) + pSiS->VBFlags = pSiS->VBFlags | CRT2_VGA; + else + pSiS->VBFlags = pSiS->VBFlags & ~(CRT2_VGA); + break; + default: + pSiS->VBFlags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA); + } + + /* TW: Eventually overrule TV Type (SVIDEO, COMPOSITE, SCART) */ + if(pSiS->ForceTVType != -1) { + if(pSiS->VBFlags & VB_SISBRIDGE) { + pSiS->VBFlags &= ~(TV_INTERFACE); + pSiS->VBFlags |= pSiS->ForceTVType; + } + } + + /* TW: Handle ForceCRT1 option */ + pSiS->CRT1changed = FALSE; + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + usScratchCR17 = pSiS->oldCR17; + usScratchCR32 = pSiS->postVBCR32; + if(pSiS->VESA != 1) { + /* TW: Copy forceCRT1 option to CRT1off if option is given */ +#ifdef SISDUALHEAD + /* TW: In DHM, handle this option only for master head, not the slave */ + if( (pSiS->forceCRT1 != -1) && + (!(pSiS->DualHeadMode && pSiS->SecondHead)) ) { +#else + if(pSiS->forceCRT1 != -1) { +#endif + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "CRT1 detection overruled by ForceCRT1 option\n"); + if(pSiS->forceCRT1) { + pSiS->CRT1off = 0; + if (!(usScratchCR17 & 0x80)) pSiS->CRT1changed = TRUE; + usScratchCR17 |= 0x80; + usScratchCR32 |= 0x20; + } else { + if( ! ( (pScrn->bitsPerPixel == 8) && + ( (pSiS->VBFlags & VB_LVDS) || + ((pSiS->VGAEngine == SIS_300_VGA) && (pSiS->VBFlags & VB_301B)) ) ) ) { + pSiS->CRT1off = 1; + if (usScratchCR17 & 0x80) pSiS->CRT1changed = TRUE; + usScratchCR32 &= ~0x20; + /* TW: We must not actually switch off CRT1 before we changed the mode! */ + } + } + outSISIDXREG(SISCR, 0x17, usScratchCR17); + outSISIDXREG(SISCR, 0x32, usScratchCR32); + if(pSiS->CRT1changed) { + outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ + usleep(10000); + outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "CRT1 status changed by ForceCRT1 option\n"); + } + } + } + /* TW: Store the new VB connection register contents for later mode changes */ + pSiS->newCR32 = usScratchCR32; + } + + /* TW: Check if CRT1 used (or needed; this eg. if no CRT2 detected) */ + if (pSiS->VBFlags & VB_VIDEOBRIDGE) { + + /* TW: No CRT2 output? Then we NEED CRT1! + * We also need CRT1 if depth = 8 and bridge=LVDS|630+301B + */ + if ( (!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) || + ( (pScrn->bitsPerPixel == 8) && + ( (pSiS->VBFlags & (VB_LVDS | VB_CHRONTEL)) || + ((pSiS->VGAEngine == SIS_300_VGA) && (pSiS->VBFlags & VB_301B)) ) ) ) { + pSiS->CRT1off = 0; + } + /* TW: No CRT2 output? Then we can't use Xv on CRT2 */ + if (!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) + pSiS->XvOnCRT2 = FALSE; + + } else { /* TW: no video bridge? */ + + /* Then we NEED CRT1... */ + pSiS->CRT1off = 0; + /* ... and can't use CRT2 for Xv output */ + pSiS->XvOnCRT2 = FALSE; + } + + /* TW: Handle TVStandard option */ + if(pSiS->NonDefaultPAL != -1) { + if( (!(pSiS->VBFlags & VB_SISBRIDGE)) && + (!((pSiS->VBFlags & VB_CHRONTEL)) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "PALM and PALN only supported on Chrontel 701x and SiS30x/B/LV\n"); + pSiS->NonDefaultPAL = -1; + pSiS->VBFlags &= ~(TV_PALN | TV_PALM); + } + } + if(pSiS->NonDefaultPAL != -1) { + if((pSiS->Chipset == PCI_CHIP_SIS300) || (pSiS->Chipset == PCI_CHIP_SIS540)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "PALM and PALN not supported on SiS300 and SiS540\n"); + pSiS->NonDefaultPAL = -1; + pSiS->VBFlags &= ~(TV_PALN | TV_PALM); + } + } + if(pSiS->OptTVStand != -1) { + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + if(!(pSiS->Flags & (TV_CHSCART | TV_CHHDTV))) { + pSiS->VBFlags &= ~(TV_PAL | TV_NTSC | TV_PALN | TV_PALM); + if(pSiS->OptTVStand) pSiS->VBFlags |= TV_PAL; + else pSiS->VBFlags |= TV_NTSC; + if(pSiS->NonDefaultPAL == 1) pSiS->VBFlags |= TV_PALM; + else if(!pSiS->NonDefaultPAL) pSiS->VBFlags |= TV_PALN; + } else { + pSiS->OptTVStand = pSiS->NonDefaultPAL = -1; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Option TVStandard ignored for SCART and 480i HDTV\n"); + } + } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { + pSiS->SiS6326Flags &= ~SIS6326_TVPAL; + if(pSiS->OptTVStand) pSiS->SiS6326Flags |= SIS6326_TVPAL; + } + } + + /* TW: Do some checks */ + if(pSiS->OptTVOver != -1) { + if(pSiS->VBFlags & VB_CHRONTEL) { + pSiS->UseCHOverScan = pSiS->OptTVOver; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "CHTVOverscan option only supported on CHRONTEL 70xx\n"); + pSiS->UseCHOverScan = -1; + } + } else pSiS->UseCHOverScan = -1; + + if(pSiS->sistvedgeenhance != -1) { + if(!(pSiS->VBFlags & VB_301)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "SISTVEdgeEnhance option only supported on SiS301\n"); + pSiS->sistvedgeenhance = -1; + } + } + + /* TW: Determine CRT1<>CRT2 mode + * Note: When using VESA or if the bridge is in slavemode, display + * is ALWAYS in MIRROR_MODE! + * This requires extra checks in functions using this flag! + * (see sis_video.c for example) + */ + if(pSiS->VBFlags & DISPTYPE_DISP2) { + if(pSiS->CRT1off) { /* TW: CRT2 only ------------------------------- */ +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "CRT1 not detected or forced off. Dual Head mode can't initialize.\n"); + if(pSiSEnt) pSiSEnt->DisableDual = TRUE; + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); + SISFreeRec(pScrn); + return FALSE; + } +#endif + pSiS->VBFlags |= VB_DISPMODE_SINGLE; + /* TW: No CRT1? Then we use the video overlay on CRT2 */ + pSiS->XvOnCRT2 = TRUE; + } else /* TW: CRT1 and CRT2 - mirror or dual head ----- */ +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + pSiS->VBFlags |= (VB_DISPMODE_DUAL | DISPTYPE_CRT1); + if(pSiS->VESA != -1) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "VESA option not used in Dual Head mode. VESA disabled.\n"); + } + if (pSiSEnt) pSiSEnt->DisableDual = FALSE; + pSiS->VESA = 0; + } else +#endif + pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1); + } else { /* TW: CRT1 only ------------------------------- */ +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No CRT2 output selected or no bridge detected. " + "Dual Head mode can't initialize.\n"); + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); + SISFreeRec(pScrn); + return FALSE; + } +#endif + pSiS->VBFlags |= (VB_DISPMODE_SINGLE | DISPTYPE_CRT1); + } + + if( (pSiS->VGAEngine == SIS_315_VGA) || + (pSiS->VGAEngine == SIS_300_VGA) ) { + if ( (!pSiS->NoXvideo) && + (!pSiS->hasTwoOverlays) ) { + xf86DrvMsg(pScrn->scrnIndex, from, + "Using Xv overlay on CRT%d\n", + pSiS->XvOnCRT2 ? 2 : 1); + } + } + + /* TW: Init Ptrs for Save/Restore functions and calc MaxClock */ + SISDACPreInit(pScrn); + + /* ********** end of VBFlags setup ********** */ + + /* TW: VBFlags are initialized now. Back them up for SlaveMode modes. */ + pSiS->VBFlags_backup = pSiS->VBFlags; + + /* TW: Find out about paneldelaycompensation and evaluate option */ + pSiS->sishw_ext.pdc = 0; + + if(pSiS->VGAEngine == SIS_300_VGA) { + + if(pSiS->VBFlags & (VB_LVDS | VB_301B | VB_302B)) { + /* TW: Save the current PDC if the panel is used at the moment. + * This seems by far the safest way to find out about it. + * If the system is using an old version of sisfb, we can't + * trust the pdc register value. If sisfb saved the pdc for + * us, use it. + */ + if(pSiS->sisfbpdc) { + pSiS->sishw_ext.pdc = pSiS->sisfbpdc; + } else { + if(!(pSiS->donttrustpdc)) { + unsigned char tmp; + inSISIDXREG(SISCR, 0x30, tmp); + if(tmp & 0x20) { + inSISIDXREG(SISPART1, 0x13, pSiS->sishw_ext.pdc); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Unable to detect LCD PanelDelayCompensation, LCD is not active\n"); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Unable to detect LCD PanelDelayCompensation, please update sisfb\n"); + } + } + pSiS->sishw_ext.pdc &= 0x3c; + if(pSiS->sishw_ext.pdc) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected LCD PanelDelayCompensation %d\n", + pSiS->sishw_ext.pdc); + } + + /* If we haven't been able to find out, use our other methods */ + if(pSiS->sishw_ext.pdc == 0) { + + int i=0; + do { + if(mypdctable[i].subsysVendor == pSiS->PciInfo->subsysVendor && + mypdctable[i].subsysCard == pSiS->PciInfo->subsysCard) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "PCI card/vendor found in list for non-default PanelDelayCompensation\n"); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Vendor: %s, card: %s (ID %04x), PanelDelayCompensation: %d\n", + mypdctable[i].vendorName, mypdctable[i].cardName, + pSiS->PciInfo->subsysCard, mypdctable[i].pdc); + if(pSiS->PDC == -1) { + pSiS->PDC = mypdctable[i].pdc; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "PanelDelayCompensation overruled by option\n"); + } + break; + } + i++; + } while(mypdctable[i].subsysVendor != 0); + + } + + if(pSiS->PDC != -1) { + if(pSiS->BIOS) { + if(pSiS->VBFlags & VB_LVDS) { + if(pSiS->BIOS[0x220] & 0x80) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "BIOS contains custom LCD Panel Delay Compensation %d\n", + pSiS->BIOS[0x220] & 0x3c); + pSiS->BIOS[0x220] &= 0x7f; + } + } + if(pSiS->VBFlags & (VB_301B|VB_302B)) { + if(pSiS->BIOS[0x220] & 0x80) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "BIOS contains custom LCD Panel Delay Compensation %d\n", + ( (pSiS->VBLCDFlags & VB_LCD_1280x1024) ? + pSiS->BIOS[0x223] : pSiS->BIOS[0x224] ) & 0x3c); + pSiS->BIOS[0x220] &= 0x7f; + } + } + } + pSiS->sishw_ext.pdc = (pSiS->PDC & 0x3c); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using LCD Panel Delay Compensation %d\n", pSiS->PDC); + } + } + } + +#ifdef SISDUALHEAD + /* TW: In dual head mode, both heads (currently) share the maxxfbmem equally. + * If memory sharing is done differently, the following has to be changed; + * the other modules (eg. accel and Xv) use dhmOffset for hardware + * pointer settings relative to VideoRAM start and won't need to be changed. + */ + if (pSiS->DualHeadMode) { + if (pSiS->SecondHead == FALSE) { + /* ===== First head (always CRT2) ===== */ + /* We use only half of the memory available */ + pSiS->maxxfbmem /= 2; + /* Initialize dhmOffset */ + pSiS->dhmOffset = 0; + /* Copy framebuffer addresses & sizes to entity */ + pSiSEnt->masterFbAddress = pSiS->FbAddress; + pSiSEnt->masterFbSize = pSiS->maxxfbmem; + pSiSEnt->slaveFbAddress = pSiS->FbAddress + pSiS->maxxfbmem; + pSiSEnt->slaveFbSize = pSiS->maxxfbmem; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "%dKB video RAM at 0x%lx available for master head (CRT2)\n", + pSiS->maxxfbmem/1024, pSiS->FbAddress); + } else { + /* ===== Second head (always CRT1) ===== */ + /* We use only half of the memory available */ + pSiS->maxxfbmem /= 2; + /* Adapt FBAddress */ + pSiS->FbAddress += pSiS->maxxfbmem; + /* Initialize dhmOffset */ + pSiS->dhmOffset = pSiS->availMem - pSiS->maxxfbmem; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "%dKB video RAM at 0x%lx available for slave head (CRT1)\n", + pSiS->maxxfbmem/1024, pSiS->FbAddress); + } + } else + pSiS->dhmOffset = 0; +#endif + + /* TW: Note: Do not use availMem for anything from now. Use + * maxxfbmem instead. (availMem does not take dual head + * mode into account.) + */ + + /* TW: Now for something completely different: DDC. + For 300 and 310/325 series, we provide our + own functions (in order to probe CRT2 as well) + If these fail, use the VBE. + All other chipsets will use VBE. No need to re-invent + the wheel there. + */ + + pSiS->pVbe = NULL; + didddc2 = FALSE; + + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + if(xf86LoadSubModule(pScrn, "ddc")) { + xf86LoaderReqSymLists(ddcSymbols, NULL); + if((pMonitor = SiSDoPrivateDDC(pScrn))) { + didddc2 = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "DDC monitor info:\n"); + xf86PrintEDID(pMonitor); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "End of DDC monitor info\n"); + xf86SetDDCproperties(pScrn, pMonitor); + pScrn->monitor->DDC = pMonitor; + } + } + } + +#ifdef SISDUALHEAD + /* TW: In dual head mode, probe DDC using VBE only for CRT1 (second head) */ + if((pSiS->DualHeadMode) && (!didddc2) && (!pSiS->SecondHead)) + didddc2 = TRUE; +#endif + + /* TW: If CRT1 is off (eventually forced), skip DDC */ + if((!didddc2) && (pSiS->CRT1off)) didddc2 = TRUE; + + /* TW: Now (re-)load and initialize the DDC module */ + if(!didddc2) { + + if(xf86LoadSubModule(pScrn, "ddc")) { + + xf86LoaderReqSymLists(ddcSymbols, NULL); + + /* TW: Now load and initialize VBE module. */ + if(xf86LoadSubModule(pScrn, "vbe")) { + xf86LoaderReqSymLists(vbeSymbols, NULL); +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) + pSiS->pVbe = VBEInit(pSiS->pInt,pSiS->pEnt->index); +#else + pSiS->pVbe = VBEExtendedInit(pSiS->pInt,pSiS->pEnt->index, + SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); +#endif + if(!pSiS->pVbe) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Could not initialize VBE module for DDC\n"); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Could not load VBE module for DDC\n"); + } + + if(pSiS->pVbe) { + if((pMonitor = vbeDoEDID(pSiS->pVbe,NULL))) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "VBE DDC monitor info:\n"); + xf86SetDDCproperties(pScrn, xf86PrintEDID(pMonitor)); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "End of VBE DDC monitor info:\n"); + pScrn->monitor->DDC = pMonitor; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Could not retrieve DDC data\n"); + } + } + } + +#if 0 /* TW: DDC1 obviously no longer supported by SiS chipsets */ + if (!ret && pSiS->ddc1Read) + xf86SetDDCproperties(pScrn, xf86PrintEDID(xf86DoEDID_DDC1( + pScrn->scrnIndex,vgaHWddc1SetSpeed,pSiS->ddc1Read ))); +#endif + + /* end of DDC */ + + /* Set the min pixel clock */ + pSiS->MinClock = 12000; /* XXX Guess, need to check this (TW: good for even 50Hz interlace) */ + xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", + pSiS->MinClock / 1000); + + from = X_PROBED; + /* + * If the user has specified ramdac speed in the XF86Config + * file, we respect that setting. + */ + if(pSiS->pEnt->device->dacSpeeds[0]) { + int speed = 0; + switch(pScrn->bitsPerPixel) { + case 8: + speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP8]; + break; + case 16: + speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP16]; + break; + case 24: + speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP24]; + break; + case 32: + speed = pSiS->pEnt->device->dacSpeeds[DAC_BPP32]; + break; + } + if(speed == 0) + pSiS->MaxClock = pSiS->pEnt->device->dacSpeeds[0]; + else + pSiS->MaxClock = speed; + from = X_CONFIG; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", + pSiS->MaxClock / 1000); + + /* + * Setup the ClockRanges, which describe what clock ranges are available, + * and what sort of modes they can be used for. + */ + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + clockRanges->minClock = pSiS->MinClock; + clockRanges->maxClock = pSiS->MaxClock; + clockRanges->clockIndex = -1; /* programmable */ + clockRanges->interlaceAllowed = TRUE; + clockRanges->doubleScanAllowed = TRUE; + + /* TW: If there is no HSync or VRefresh data for the monitor, + derive it from DDC data. (Idea taken from radeon driver) + */ + if(pScrn->monitor->DDC) { + if(pScrn->monitor->nHsync <= 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Substituting missing monitor HSync data by DDC data\n"); + SiSSetSyncRangeFromEdid(pScrn, 1); + } + if(pScrn->monitor->nVrefresh <= 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Substituting missing monitor VRefresh data by DDC data\n"); + SiSSetSyncRangeFromEdid(pScrn, 0); + } + } + + /* + * TW: Since we have lots of built-in modes for 300/310/325/330 series + * with vb support, we replace the given default mode list with our + * own. In case the video bridge is to be used, no other than our + * built-in modes are supported; therefore, delete the entire modelist + * given. + */ + + pSiS->HaveCustomModes = FALSE; + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + if(!(pSiS->noInternalModes)) { + if((mymodes = SiSBuildBuiltInModeList(pScrn))) { +#ifdef SISDUALHEAD + if( (pSiS->UseVESA) || + ((pSiS->DualHeadMode) && (!pSiS->SecondHead)) || + ((!pSiS->DualHeadMode) && (pSiS->VBFlags & DISPTYPE_DISP2)) ) { +#else + if((pSiS->UseVESA) || (pSiS->VBFlags & DISPTYPE_DISP2)) { +#endif + while(pScrn->monitor->Modes) + xf86DeleteMode(&pScrn->monitor->Modes, pScrn->monitor->Modes); + pScrn->monitor->Modes = mymodes; + } else { + delmode = pScrn->monitor->Modes; + while(delmode) { + if(delmode->type & M_T_DEFAULT) { + tempmode = delmode->next; + xf86DeleteMode(&pScrn->monitor->Modes, delmode); + delmode = tempmode; + } else { + delmode = delmode->next; + } + } + tempmode = pScrn->monitor->Modes; + if(tempmode) pSiS->HaveCustomModes = TRUE; + pScrn->monitor->Modes = mymodes; + while(mymodes) { + if(!mymodes->next) break; + else mymodes = mymodes->next; + } + mymodes->next = tempmode; + if(tempmode) { + tempmode->prev = mymodes; + } + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Replaced %s mode list with built-in modes\n", + pSiS->HaveCustomModes ? "default" : "entire"); +#ifdef TWDEBUG + pScrn->modes = pScrn->monitor->Modes; + xf86PrintModes(pScrn); + pScrn->modes = NULL; +#endif + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Building list of built-in modes failed, using XFree86 defaults\n"); + } + } + } + + /* + * TW: Add our built-in modes for TV on the 6326 + */ + if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { + if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Adding %s TV modes for 6326 to mode list:\n", + (pSiS->SiS6326Flags & SIS6326_TVPAL) ? "PAL" : "NTSC"); + if(pSiS->SiS6326Flags & SIS6326_TVPAL) { + SiS6326PAL800x600Mode.next = pScrn->monitor->Modes; + pScrn->monitor->Modes = &SiS6326PAL640x480Mode; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "\"PAL800x600\" \"PAL800x600U\" \"PAL720x540\" \"PAL640x480\"\n"); + } else { + SiS6326NTSC640x480Mode.next = pScrn->monitor->Modes; + pScrn->monitor->Modes = &SiS6326NTSC640x400Mode; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "\"NTSC640x480\" \"NTSC640x480U\" \"NTSC640x400\"\n"); + } + } + } + + /* + * TW: Add our built-in hi-res modes on the 6326 + */ + if(pSiS->Chipset == PCI_CHIP_SIS6326) { + if(pScrn->bitsPerPixel == 8) { + SiS6326SIS1600x1200_60Mode.next = pScrn->monitor->Modes; + pScrn->monitor->Modes = &SiS6326SIS1600x1200_60Mode; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Adding mode \"SIS1600x1200-60\" (depth 8 only)\n"); + } + if(pScrn->bitsPerPixel <= 16) { + SiS6326SIS1280x1024_75Mode.next = pScrn->monitor->Modes; + pScrn->monitor->Modes = &SiS6326SIS1280x1024_75Mode; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Adding mode \"SIS1280x1024-75\" (depth 8, 15 and 16 only)\n"); + } + } + + if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "\"Unknown reason\" in the following list means that the mode\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "is not supported on the chipset/bridge/current output device.\n"); + } + + /* + * xf86ValidateModes will check that the mode HTotal and VTotal values + * don't exceed the chipset's limit if pScrn->maxHValue and + * pScrn->maxVValue are set. Since our SISValidMode() already takes + * care of this, we don't worry about setting them here. + */ + + /* Select valid modes from those available */ + /* + * Assuming min pitch 256, max 4096 ==> 8192 + * Assuming min height 128, max 4096 + */ + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, + NULL, 256, 8192, + pScrn->bitsPerPixel * 8, 128, 4096, + pScrn->display->virtualX, + pScrn->display->virtualY, + pSiS->maxxfbmem, + LOOKUP_BEST_REFRESH); + + if(i == -1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "xf86ValidateModes() error\n"); +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); + SISFreeRec(pScrn); + return FALSE; + } + + /* TW: Go through mode list and mark all those modes as bad, + * - which are unsuitable for dual head mode (if running dhm), + * - which exceed the LCD panels specs (if running on LCD) + * - TODO: which exceed TV capabilities (if running on TV) + * Also, find the highest used pixelclock on the master head. + */ +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(!pSiS->SecondHead) pSiSEnt->maxUsedClock = 0; + } +#endif + if((p = first = pScrn->modes)) { + do { + n = p->next; + + /* TW: Check the modes if they comply with our built-in tables. + * This is of practical use only if the user disabled the + * usage of the internal (built-in) modes. + */ + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + if(p->type & M_T_DEFAULT) { + if( ( (strcmp(p->name, "320x200") != 0) && + (strcmp(p->name, "320x240") != 0) && + (strcmp(p->name, "400x300") != 0) && + (strcmp(p->name, "512x384") != 0) ) && + (p->Flags & V_DBLSCAN) ) { + p->status = MODE_NO_DBLESCAN; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using mode \"%s\" (mode not supported as doublescan)\n", p->name); + } + if( ( (strcmp(p->name, "1024x768") != 0) && + (strcmp(p->name, "1280x1024") != 0) && + (strcmp(p->name, "848x480") != 0) && + (strcmp(p->name, "856x480") != 0)) && + (p->Flags & V_INTERLACE) ) { + p->status = MODE_NO_INTERLACE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using mode \"%s\" (mode not supported as interlaced)\n", p->name); + } + if( ( (strcmp(p->name, "320x200") == 0) || + (strcmp(p->name, "320x240") == 0) || + (strcmp(p->name, "400x300") == 0) || + (strcmp(p->name, "512x384") == 0) ) && + (!(p->Flags & V_DBLSCAN)) ) { + p->status = MODE_CLOCK_RANGE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using mode \"%s\" (only supported as doublescan)\n", p->name); + } + } + } +#ifdef SISDUALHEAD + /* TW: Modes that require the bridge to operate in SlaveMode + * are not suitable for Dual Head mode. Also check for + * modes that exceed panel dimension. + */ + if(pSiS->DualHeadMode) { + if(pSiS->SecondHead == FALSE) { + if( (strcmp(p->name, "320x200") == 0) || + (strcmp(p->name, "320x240") == 0) || + (strcmp(p->name, "400x300") == 0) || + (strcmp(p->name, "512x384") == 0) || + (strcmp(p->name, "640x400") == 0) ) { + p->status = MODE_BAD; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using mode \"%s\" (not suitable for dual head mode)\n", + p->name); + } + } + if(pSiS->VBFlags & DISPTYPE_DISP2) { + if(pSiS->VBFlags & CRT2_LCD) { + if(pSiS->SecondHead == FALSE) { + if((p->HDisplay > pSiS->LCDwidth) || (p->VDisplay > pSiS->LCDheight)) { + p->status = MODE_PANEL; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using mode \"%s\" (exceeds LCD panel dimension)\n", p->name); + } + if(p->Flags & V_INTERLACE) { + p->status = MODE_BAD; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using mode \"%s\" (interlace on LCD not supported)\n", + p->name); + } + } + } + /* TO DO: TV */ + } + /* TW: Search for the highest clock on first head in order to calculate + * max clock for second head (CRT1) + */ + if(!pSiS->SecondHead) { + if((p->status == MODE_OK) && (p->Clock > pSiSEnt->maxUsedClock)) { + pSiSEnt->maxUsedClock = p->Clock; + } + } + } else { +#endif + if(pSiS->VBFlags & DISPTYPE_DISP2) { + if(pSiS->VBFlags & CRT2_LCD) { + if((p->HDisplay > pSiS->LCDwidth) || (p->VDisplay > pSiS->LCDheight)) { + p->status = MODE_PANEL; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using mode \"%s\" (exceeds LCD panel dimension)\n", p->name); + } + if(p->Flags & V_INTERLACE) { + p->status = MODE_BAD; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using mode \"%s\" (interlace on LCD not supported)\n", + p->name); + } + } + } +#ifdef SISDUALHEAD + } +#endif + p = n; + } while (p != NULL && p != first); + } + + /* Prune the modes marked as invalid */ + xf86PruneDriverModes(pScrn); + + if(i == 0 || pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); + SISFreeRec(pScrn); + return FALSE; + } + + xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); + + /* Set the current mode to the first in the list */ + pScrn->currentMode = pScrn->modes; + + /* TW: Copy to CurrentLayout */ + pSiS->CurrentLayout.mode = pScrn->currentMode; + pSiS->CurrentLayout.displayWidth = pScrn->displayWidth; + + /* Print the list of modes being used */ + xf86PrintModes(pScrn); + +#ifdef SISDUALHEAD + /* TW: Due to palette & timing problems we don't support 8bpp in DHM */ + if((pSiS->DualHeadMode) && (pScrn->bitsPerPixel == 8)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Colordepth 8 not supported in Dual Head mode.\n"); + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); + SISFreeRec(pScrn); + return FALSE; + } +#endif + + /* Set display resolution */ + xf86SetDpi(pScrn, 0, 0); + + /* Load bpp-specific modules */ + switch(pScrn->bitsPerPixel) { + case 1: + mod = "xf1bpp"; + Sym = "xf1bppScreenInit"; + break; + case 4: + mod = "xf4bpp"; + Sym = "xf4bppScreenInit"; + break; + case 8: + case 16: + case 24: + case 32: + mod = "fb"; + break; + } + + if(mod && xf86LoadSubModule(pScrn, mod) == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not load %s module", mod); +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); + SISFreeRec(pScrn); + return FALSE; + } + + if(mod) { + if(Sym) { + xf86LoaderReqSymbols(Sym, NULL); + } else { + xf86LoaderReqSymLists(fbSymbols, NULL); + } + } + + /* Load XAA if needed */ + if(!pSiS->NoAccel) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Accel enabled\n"); + if(!xf86LoadSubModule(pScrn, "xaa")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not load xaa module\n"); +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); + SISFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(xaaSymbols, NULL); + } + + /* Load shadowfb if needed */ + if(pSiS->ShadowFB) { + if(!xf86LoadSubModule(pScrn, "shadowfb")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not load shadowfb module\n"); +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->ErrorAfterFirst = TRUE; +#endif + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); + SISFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(shadowSymbols, NULL); + } + + + /* TW: Now load and initialize VBE module for VESA. */ + pSiS->UseVESA = 0; + if(pSiS->VESA == 1) { + if(!pSiS->pVbe) { + if(xf86LoadSubModule(pScrn, "vbe")) { + xf86LoaderReqSymLists(vbeSymbols, NULL); +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) + pSiS->pVbe = VBEInit(pSiS->pInt,pSiS->pEnt->index); +#else + pSiS->pVbe = VBEExtendedInit(pSiS->pInt,pSiS->pEnt->index, + SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); +#endif + } + } + if(pSiS->pVbe) { + vbe = VBEGetVBEInfo(pSiS->pVbe); + pSiS->vesamajor = (unsigned)(vbe->VESAVersion >> 8); + pSiS->vesaminor = vbe->VESAVersion & 0xff; + pSiS->vbeInfo = vbe; + SiSBuildVesaModeList(pScrn, pSiS->pVbe, vbe); + VBEFreeVBEInfo(vbe); + pSiS->UseVESA = 1; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Could not load and initialize VBE module. VESA disabled.\n"); + } + } + + if(pSiS->pVbe) { + vbeFree(pSiS->pVbe); + pSiS->pVbe = NULL; + } + +#ifdef SISDUALHEAD + xf86SetPrimInitDone(pScrn->entityList[0]); +#endif + + sisRestoreExtRegisterLock(pSiS,srlockReg,crlockReg); + + if(pSiS->pInt) xf86FreeInt10(pSiS->pInt); + pSiS->pInt = NULL; + + return TRUE; +} + + +/* + * Map the framebuffer and MMIO memory. + */ + +static Bool +SISMapMem(ScrnInfoPtr pScrn) +{ + SISPtr pSiS; + int mmioFlags; +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = NULL; +#endif + pSiS = SISPTR(pScrn); + +#ifdef SISDUALHEAD + pSiSEnt = pSiS->entityPrivate; +#endif + + /* + * Map IO registers to virtual address space + */ +#if !defined(__alpha__) + mmioFlags = VIDMEM_MMIO; +#else + /* + * For Alpha, we need to map SPARSE memory, since we need + * byte/short access. + */ + mmioFlags = VIDMEM_MMIO | VIDMEM_SPARSE; +#endif + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + pSiSEnt->MapCountIOBase++; + if(!(pSiSEnt->IOBase)) { + /* TW: Only map if not mapped previously */ + pSiSEnt->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, + pSiS->PciTag, pSiS->IOAddress, 0x10000); + } + pSiS->IOBase = pSiSEnt->IOBase; + } else +#endif + pSiS->IOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, + pSiS->PciTag, pSiS->IOAddress, 0x10000); + + if(pSiS->IOBase == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not map MMIO area\n"); + return FALSE; + } + +#ifdef __alpha__ + /* + * for Alpha, we need to map DENSE memory as well, for + * setting CPUToScreenColorExpandBase. + */ +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + pSiSEnt->MapCountIOBaseDense++; + if(!(pSiSEnt->IOBaseDense)) { + /* TW: Only map if not mapped previously */ + pSiSEnt->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, + pSiS->PciTag, pSiS->IOAddress, 0x10000); + } + pSiS->IOBaseDense = pSiSEnt->IOBaseDense; + } else +#endif + pSiS->IOBaseDense = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, + pSiS->PciTag, pSiS->IOAddress, 0x10000); + + if(pSiS->IOBaseDense == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not map MMIO dense area\n"); + return FALSE; + } + +#endif /* __alpha__ */ + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + pSiSEnt->MapCountFbBase++; + if(!(pSiSEnt->FbBase)) { + /* TW: Only map if not mapped previously */ + pSiSEnt->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, + pSiS->PciTag, (unsigned long)pSiS->realFbAddress, + pSiS->FbMapSize); + pSiS->sishw_ext.pjVideoMemoryAddress = (UCHAR *)pSiSEnt->FbBase; + } + pSiS->FbBase = pSiSEnt->FbBase; + /* TW: Adapt FbBase (for DHM; dhmOffset is 0 otherwise) */ + pSiS->FbBase += pSiS->dhmOffset; + } else { +#endif + pSiS->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, + pSiS->PciTag, (unsigned long)pSiS->FbAddress, + pSiS->FbMapSize); + pSiS->sishw_ext.pjVideoMemoryAddress = (UCHAR *)pSiS->FbBase; +#ifdef SISDUALHEAD + } +#endif + + if(pSiS->FbBase == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not map framebuffer area\n"); + return FALSE; + } + + return TRUE; +} + + +/* + * Unmap the framebuffer and MMIO memory. + */ + +static Bool +SISUnmapMem(ScrnInfoPtr pScrn) +{ + SISPtr pSiS; +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = NULL; +#endif + + pSiS = SISPTR(pScrn); + +#ifdef SISDUALHEAD + pSiSEnt = pSiS->entityPrivate; +#endif + +/* TW: In dual head mode, we must not unmap if the other head still + * assumes memory as mapped +*/ +#ifdef SISDUALHEAD + if (pSiS->DualHeadMode) { + if (pSiSEnt->MapCountIOBase) { + pSiSEnt->MapCountIOBase--; + if ((pSiSEnt->MapCountIOBase == 0) || (pSiSEnt->forceUnmapIOBase)) { + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBase, 0x10000); + pSiSEnt->IOBase = NULL; + pSiSEnt->MapCountIOBase = 0; + pSiSEnt->forceUnmapIOBase = FALSE; + } + pSiS->IOBase = NULL; + } +#ifdef __alpha__ + if (pSiSEnt->MapCountIOBaseDense) { + pSiSEnt->MapCountIOBaseDense--; + if ((pSiSEnt->MapCountIOBaseDense == 0) || (pSiSEnt->forceUnmapIOBaseDense)) { + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBaseDense, 0x10000); + pSiSEnt->IOBaseDense = NULL; + pSiSEnt->MapCountIOBaseDense = 0; + pSiSEnt->forceUnmapIOBaseDense = FALSE; + } + pSiS->IOBaseDense = NULL; + } +#endif /* __alpha__ */ + if (pSiSEnt->MapCountFbBase) { + pSiSEnt->MapCountFbBase--; + if ((pSiSEnt->MapCountFbBase == 0) || (pSiSEnt->forceUnmapFbBase)) { + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->FbBase, pSiS->FbMapSize); + pSiSEnt->FbBase = NULL; + pSiSEnt->MapCountFbBase = 0; + pSiSEnt->forceUnmapFbBase = FALSE; + + } + pSiS->FbBase = NULL; + } + } else { +#endif + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBase, 0x10000); + pSiS->IOBase = NULL; +#ifdef __alpha__ + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBaseDense, 0x10000); + pSiS->IOBaseDense = NULL; +#endif + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->FbBase, pSiS->FbMapSize); + pSiS->FbBase = NULL; +#ifdef SISDUALHEAD + } +#endif + return TRUE; +} + +/* + * This function saves the video state. + */ +static void +SISSave(ScrnInfoPtr pScrn) +{ + SISPtr pSiS; + vgaRegPtr vgaReg; + SISRegPtr sisReg; + + pSiS = SISPTR(pScrn); + +#ifdef SISDUALHEAD + /* TW: We always save master & slave */ + if(pSiS->DualHeadMode && pSiS->SecondHead) return; +#endif + + vgaReg = &VGAHWPTR(pScrn)->SavedReg; + sisReg = &pSiS->SavedReg; + + vgaHWSave(pScrn, vgaReg, VGA_SR_ALL); + + sisSaveUnlockExtRegisterLock(pSiS,&sisReg->sisRegs3C4[0x05],&sisReg->sisRegs3D4[0x80]); + + (*pSiS->SiSSave)(pScrn, sisReg); + + if(pSiS->UseVESA) SISVESASaveRestore(pScrn, MODE_SAVE); + + /* TW: Save these as they may have been changed prior to SISSave() call */ + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + sisReg->sisRegs3D4[0x17] = pSiS->oldCR17; + if(vgaReg->numCRTC >= 0x17) vgaReg->CRTC[0x17] = pSiS->oldCR17; + sisReg->sisRegs3D4[0x32] = pSiS->oldCR32; + } +} + +/* + * TW: Just adapted from the std* functions in vgaHW.c + */ +static void +SiS_WriteAttr(SISPtr pSiS, int index, int value) +{ + CARD8 tmp; + + tmp = inb(pSiS->IODBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); + + index |= 0x20; + outb(pSiS->IODBase + VGA_ATTR_INDEX, index); + outb(pSiS->IODBase + VGA_ATTR_DATA_W, value); +} + +static int +SiS_ReadAttr(SISPtr pSiS, int index) +{ + CARD8 tmp; + + tmp = inb(pSiS->IODBase + VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); + + index |= 0x20; + outb(pSiS->IODBase + VGA_ATTR_INDEX, index); + return (inb(pSiS->IODBase + VGA_ATTR_DATA_R)); +} + + +static void +SiS_SaveFonts(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn; +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) + CARD8 *vgaIOBase = (CARD8 *)VGAHWPTR(pScrn)->IOBase; +#else + pointer vgaIOBase = VGAHWPTR(pScrn)->Base; +#endif + + if (pSiS->fonts != NULL) + return; + + /* If in graphics mode, don't save anything */ + attr10 = SiS_ReadAttr(pSiS, 0x10); + if (attr10 & 0x01) + return; + + pSiS->fonts = xalloc(16384); + + /* save the registers that are needed here */ + miscOut = inSISREG(SISMISCR); + inSISIDXREG(SISGR, 0x04, gr4); + inSISIDXREG(SISGR, 0x05, gr5); + inSISIDXREG(SISGR, 0x06, gr6); + inSISIDXREG(SISSR, 0x02, seq2); + inSISIDXREG(SISSR, 0x04, seq4); + + /* Force into color mode */ + outSISREG(SISMISCW, miscOut | 0x01); + + inSISIDXREG(SISSR, 0x01, scrn); + outSISIDXREG(SISSR, 0x00, 0x01); + outSISIDXREG(SISSR, 0x01, scrn | 0x20); + outSISIDXREG(SISSR, 0x00, 0x03); + + SiS_WriteAttr(pSiS, 0x10, 0x01); /* graphics mode */ + + /*font1 */ + outSISIDXREG(SISSR, 0x02, 0x04); /* write to plane 2 */ + outSISIDXREG(SISSR, 0x04, 0x06); /* enable plane graphics */ + outSISIDXREG(SISGR, 0x04, 0x02); /* read plane 2 */ + outSISIDXREG(SISGR, 0x05, 0x00); /* write mode 0, read mode 0 */ + outSISIDXREG(SISGR, 0x06, 0x05); /* set graphics */ + slowbcopy_frombus(vgaIOBase, pSiS->fonts, 8192); + + /* font2 */ + outSISIDXREG(SISSR, 0x02, 0x08); /* write to plane 3 */ + outSISIDXREG(SISSR, 0x04, 0x06); /* enable plane graphics */ + outSISIDXREG(SISGR, 0x04, 0x03); /* read plane 3 */ + outSISIDXREG(SISGR, 0x05, 0x00); /* write mode 0, read mode 0 */ + outSISIDXREG(SISGR, 0x06, 0x05); /* set graphics */ + slowbcopy_frombus(vgaIOBase, pSiS->fonts + 8192, 8192); + + inSISIDXREG(SISSR, 0x01, scrn); + outSISIDXREG(SISSR, 0x00, 0x01); + outSISIDXREG(SISSR, 0x01, scrn & ~0x20); + outSISIDXREG(SISSR, 0x00, 0x03); + + /* Restore clobbered registers */ + SiS_WriteAttr(pSiS, 0x10, attr10); + outSISIDXREG(SISSR, 0x02, seq2); + outSISIDXREG(SISSR, 0x04, seq4); + outSISIDXREG(SISGR, 0x04, gr4); + outSISIDXREG(SISGR, 0x05, gr5); + outSISIDXREG(SISGR, 0x06, gr6); + outSISREG(SISMISCW, miscOut); +} + +static void +SiS_RestoreFonts(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn; +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) + CARD8 *vgaIOBase = (CARD8 *)VGAHWPTR(pScrn)->IOBase; +#else + pointer vgaIOBase = VGAHWPTR(pScrn)->Base; +#endif + + if (pSiS->fonts == NULL) + return; + +#if 0 + if (pVesa->mapPhys == 0xa0000 && pVesa->curBank != 0) + VESABankSwitch(pScrn->pScreen, 0); +#endif + + /* save the registers that are needed here */ + miscOut = inSISREG(SISMISCR); + attr10 = SiS_ReadAttr(pSiS, 0x10); + inSISIDXREG(SISGR, 0x01, gr1); + inSISIDXREG(SISGR, 0x03, gr3); + inSISIDXREG(SISGR, 0x04, gr4); + inSISIDXREG(SISGR, 0x05, gr5); + inSISIDXREG(SISGR, 0x06, gr6); + inSISIDXREG(SISGR, 0x08, gr8); + inSISIDXREG(SISSR, 0x02, seq2); + inSISIDXREG(SISSR, 0x04, seq4); + + /* Force into color mode */ + outSISREG(SISMISCW, miscOut | 0x01); + inSISIDXREG(SISSR, 0x01, scrn); + outSISIDXREG(SISSR, 0x00, 0x01); + outSISIDXREG(SISSR, 0x01, scrn | 0x20); + outSISIDXREG(SISSR, 0x00, 0x03); + + SiS_WriteAttr(pSiS, 0x10, 0x01); /* graphics mode */ + if (pScrn->depth == 4) { + outSISIDXREG(SISGR, 0x03, 0x00); /* don't rotate, write unmodified */ + outSISIDXREG(SISGR, 0x08, 0xFF); /* write all bits in a byte */ + outSISIDXREG(SISGR, 0x01, 0x00); /* all planes come from CPU */ + } + + outSISIDXREG(SISSR, 0x02, 0x04); /* write to plane 2 */ + outSISIDXREG(SISSR, 0x04, 0x06); /* enable plane graphics */ + outSISIDXREG(SISGR, 0x04, 0x02); /* read plane 2 */ + outSISIDXREG(SISGR, 0x05, 0x00); /* write mode 0, read mode 0 */ + outSISIDXREG(SISGR, 0x06, 0x05); /* set graphics */ + slowbcopy_tobus(pSiS->fonts, vgaIOBase, 8192); + + outSISIDXREG(SISSR, 0x02, 0x08); /* write to plane 3 */ + outSISIDXREG(SISSR, 0x04, 0x06); /* enable plane graphics */ + outSISIDXREG(SISGR, 0x04, 0x03); /* read plane 3 */ + outSISIDXREG(SISGR, 0x05, 0x00); /* write mode 0, read mode 0 */ + outSISIDXREG(SISGR, 0x06, 0x05); /* set graphics */ + slowbcopy_tobus(pSiS->fonts + 8192, vgaIOBase, 8192); + + inSISIDXREG(SISSR, 0x01, scrn); + outSISIDXREG(SISSR, 0x00, 0x01); + outSISIDXREG(SISSR, 0x01, scrn & ~0x20); + outSISIDXREG(SISSR, 0x00, 0x03); + + /* restore the registers that were changed */ + outSISREG(SISMISCW, miscOut); + SiS_WriteAttr(pSiS, 0x10, attr10); + outSISIDXREG(SISGR, 0x01, gr1); + outSISIDXREG(SISGR, 0x03, gr3); + outSISIDXREG(SISGR, 0x04, gr4); + outSISIDXREG(SISGR, 0x05, gr5); + outSISIDXREG(SISGR, 0x06, gr6); + outSISIDXREG(SISGR, 0x08, gr8); + outSISIDXREG(SISSR, 0x02, seq2); + outSISIDXREG(SISSR, 0x04, seq4); +} + +/* TW: VESASaveRestore taken from vesa driver */ +static void +SISVESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function) +{ + SISPtr pSiS; + + pSiS = SISPTR(pScrn); + + /* Query amount of memory to save state */ + if (function == MODE_QUERY || + (function == MODE_SAVE && pSiS->state == NULL)) { + + /* Make sure we save at least this information in case of failure */ + (void)VBEGetVBEMode(pSiS->pVbe, &pSiS->stateMode); + SiS_SaveFonts(pScrn); + + if (pSiS->vesamajor > 1) { + if (!VBESaveRestore(pSiS->pVbe,function,(pointer)&pSiS->state, + &pSiS->stateSize,&pSiS->statePage)) + return; + + } + } + + /* Save/Restore Super VGA state */ + if (function != MODE_QUERY) { + Bool retval = TRUE; + + if (pSiS->vesamajor > 1) { + if (function == MODE_RESTORE) + memcpy(pSiS->state, pSiS->pstate, pSiS->stateSize); + + if ((retval = VBESaveRestore(pSiS->pVbe,function, + (pointer)&pSiS->state, + &pSiS->stateSize,&pSiS->statePage)) + && function == MODE_SAVE) { + /* don't rely on the memory not being touched */ + if (pSiS->pstate == NULL) + pSiS->pstate = xalloc(pSiS->stateSize); + memcpy(pSiS->pstate, pSiS->state, pSiS->stateSize); + } + } + + if (function == MODE_RESTORE) { + VBESetVBEMode(pSiS->pVbe, pSiS->stateMode, NULL); + SiS_RestoreFonts(pScrn); + } +#if 0 + if (!retval) + return (FALSE); +#endif + + } +#if 0 + if ( (pSiS->vesamajor > 1) && + (function == MODE_SAVE || pSiS->pstate) ) { + if (function == MODE_RESTORE) + memcpy(pSiS->state, pSiS->pstate, pSiS->stateSize); + if ((VBESaveRestore(pSiS->pVbe,function, + (pointer)&pSiS->state, + &pSiS->stateSize,&pSiS->statePage))) { + if (function == MODE_SAVE) { + /* don't rely on the memory not being touched */ + if (pSiS->pstate == NULL) + pSiS->pstate = xalloc(pSiS->stateSize); + memcpy(pSiS->pstate, pSiS->state, pSiS->stateSize); + } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "VBESaveRestore done with success\n"); + return; + } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "VBESaveRestore done\n"); + } else { + if (function == MODE_SAVE) + (void)VBEGetVBEMode(pSiS->pVbe, &pSiS->stateMode); + else + VBESetVBEMode(pSiS->pVbe, pSiS->stateMode, NULL); + } +#endif +} + +/* + * Initialise a new mode. This is currently done using the + * "initialise struct, restore/write struct to HW" model for + * the old chipsets (5597/530/6326). For newer chipsets, + * we use either VESA or our own mode switching code. + */ + +static Bool +SISModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg; + SISPtr pSiS = SISPTR(pScrn); + SISRegPtr sisReg; + + vgaHWUnlock(hwp); + + SISModifyModeInfo(mode); + + /* TW: Initialize SiS Port Register definitions for externally used + * BIOS emulation (native code switching) functions. + */ + if( pSiS->VGAEngine == SIS_300_VGA || + pSiS->VGAEngine == SIS_315_VGA ) { + SiSRegInit(pSiS->SiS_Pr, pSiS->RelIO+0x30); + } + + if (pSiS->UseVESA) { /* With VESA: */ + +#ifdef SISDUALHEAD + /* TW: No dual head mode when using VESA */ + if (pSiS->SecondHead) return TRUE; +#endif + /* + * TW: This order is required: + * The video bridge needs to be adjusted before the + * BIOS is run as the BIOS sets up CRT2 according to + * these register settings. + * After the BIOS is run, the bridges and turboqueue + * registers need to be readjusted as the BIOS may + * very probably have messed them up. + */ + if( pSiS->VGAEngine == SIS_300_VGA || + pSiS->VGAEngine == SIS_315_VGA ) { + SiSPreSetMode(pScrn, mode); + } + if(!SiSSetVESAMode(pScrn, mode)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "SiSSetVESAMode() failed\n"); + return FALSE; + } + sisSaveUnlockExtRegisterLock(pSiS,NULL,NULL); + if( pSiS->VGAEngine == SIS_300_VGA || + pSiS->VGAEngine == SIS_315_VGA ) { + SiSPreSetMode(pScrn, mode); + SiSPostSetMode(pScrn, &pSiS->ModeReg); + } + /* TW: Prepare some register contents and set + * up some mode dependent variables. + */ +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "REAL REGISTER CONTENTS AFTER SETMODE:\n"); +#endif + if (!(*pSiS->ModeInit)(pScrn, mode)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ModeInit() failed\n"); + return FALSE; + } + + pScrn->vtSema = TRUE; + + /* Program the registers */ + vgaHWProtect(pScrn, TRUE); + (*pSiS->SiSRestore)(pScrn, &pSiS->ModeReg); + vgaHWProtect(pScrn, FALSE); + PDEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "HDisplay: %d, VDisplay: %d \n", + mode->HDisplay, mode->VDisplay)); + + } else { /* Without VESA: */ +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(!(*pSiS->ModeInit)(pScrn, mode)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ModeInit() failed\n"); + return FALSE; + } + + pScrn->vtSema = TRUE; + + if(!(pSiS->SecondHead)) { + /* TW: Head 1 (master) is always CRT2 */ + SiSPreSetMode(pScrn, mode); + if (!SiSBIOSSetModeCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pScrn, mode)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "SiSBIOSSetModeCRT2() failed\n"); + return FALSE; + } + SiSPostSetMode(pScrn, &pSiS->ModeReg); + } else { + /* TW: Head 2 (slave) is always CRT1 */ + SiSPreSetMode(pScrn, mode); + if (!SiSBIOSSetModeCRT1(pSiS->SiS_Pr, &pSiS->sishw_ext, pScrn, mode, pSiS->IsCustom)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "SiSBIOSSetModeCRT1() failed\n"); + return FALSE; + } + SiSPostSetMode(pScrn, &pSiS->ModeReg); + } + } else { +#endif + if(pSiS->VGAEngine == SIS_300_VGA || + pSiS->VGAEngine == SIS_315_VGA) { + + /* TW: Prepare the register contents; On 300/310/325, + * we actually "abuse" this only for setting + * up some variables; the registers are NOT + * being written to the hardware as the BIOS + * emulation (native mode switching code) + * takes care of this. + */ + if(!(*pSiS->ModeInit)(pScrn, mode)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ModeInit() failed\n"); + return FALSE; + } + + pScrn->vtSema = TRUE; + + /* 300/310/325 series: Use our own code for mode switching */ + SiSPreSetMode(pScrn, mode); + + if(!SiSBIOSSetMode(pSiS->SiS_Pr, &pSiS->sishw_ext, pScrn, mode, pSiS->IsCustom)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "SiSBIOSSetMode() failed\n"); + return FALSE; + } + + SiSPostSetMode(pScrn, &pSiS->ModeReg); +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "REAL REGISTER CONTENTS AFTER SETMODE:\n"); + (*pSiS->ModeInit)(pScrn, mode); +#endif + } else { + + /* For other chipsets, use the old method */ + + /* Initialise the ModeReg values */ + if(!vgaHWInit(pScrn, mode)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "vgaHWInit() failed\n"); + return FALSE; + } + + /* Reset our PIOOffset as vgaHWInit might have reset it */ + VGAHWPTR(pScrn)->PIOOffset = pSiS->IODBase + (pSiS->PciInfo->ioBase[2] & 0xFFFC) - 0x380; + + /* Prepare the register contents */ + if(!(*pSiS->ModeInit)(pScrn, mode)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ModeInit() failed\n"); + return FALSE; + } + + pScrn->vtSema = TRUE; + + /* Program the registers */ + vgaHWProtect(pScrn, TRUE); + vgaReg = &hwp->ModeReg; + sisReg = &pSiS->ModeReg; + + vgaReg->Attribute[0x10] = 0x01; + if(pScrn->bitsPerPixel > 8) { + vgaReg->Graphics[0x05] = 0x00; + } + + vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE); + + (*pSiS->SiSRestore)(pScrn, sisReg); + + if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { + SiS6326PostSetMode(pScrn, &pSiS->ModeReg); + } + +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "REAL REGISTER CONTENTS AFTER SETMODE:\n"); + (*pSiS->ModeInit)(pScrn, mode); +#endif + + vgaHWProtect(pScrn, FALSE); + } +#ifdef SISDUALHEAD + } +#endif + } + + /* TW: Update Currentlayout */ + pSiS->CurrentLayout.mode = mode; + + /* Debug */ +/* SiSDumpModeInfo(pScrn, mode); */ + + return TRUE; +} + +static Bool +SiSSetVESAMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) +{ + SISPtr pSiS; + int mode; + + pSiS = SISPTR(pScrn); + + if (!(mode = SiSCalcVESAModeIndex(pScrn, pMode))) return FALSE; + + mode |= 1 << 15; /* TW: Don't clear framebuffer */ + mode |= 1 << 14; /* TW: Use linear adressing */ + + if(VBESetVBEMode(pSiS->pVbe, mode, NULL) == FALSE) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Setting VESA mode 0x%x failed\n", + mode & 0x0fff); + return (FALSE); + } + + if(pMode->HDisplay != pScrn->virtualX) + VBESetLogicalScanline(pSiS->pVbe, pScrn->virtualX); + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Setting VESA mode 0x%x succeeded\n", + mode & 0x0fff); + + return (TRUE); +} + +/* + * Restore the initial mode. To be used internally only! + */ +static void +SISRestore(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + SISRegPtr sisReg = &pSiS->SavedReg; + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg = &hwp->SavedReg; + Bool doit = FALSE, doitlater = FALSE; + + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + +#ifdef SISDUALHEAD + /* TW: We always restore master AND slave */ + if(pSiS->DualHeadMode && pSiS->SecondHead) return; +#endif + + /* TW: We must not disable the sequencer if the bridge is in SlaveMode! */ + if(!(SiSBridgeIsInSlaveMode(pScrn))) { + vgaHWProtect(pScrn, TRUE); + } + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL,NULL); +#endif + + /* TW: First, restore CRT1 on/off and VB connection registers */ + outSISIDXREG(SISCR, 0x32, pSiS->oldCR32); + if(!(pSiS->oldCR17 & 0x80)) { /* TW: CRT1 was off */ + if(!(SiSBridgeIsInSlaveMode(pScrn))) { /* TW: Bridge is NOT in SlaveMode now -> do it */ + doit = TRUE; + } else { + doitlater = TRUE; + } + } else { /* TW: CRT1 was on -> do it now */ + doit = TRUE; + } + + if(doit) { + outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); + } + + /* TW: For 30xB/LV, restoring the registers does not + * work. We "manually" set the old mode, instead. + * The same applies for SiS730 machines with LVDS. + * Finally, this behavior can be forced by setting + * the option RestoreBySetMode. + */ + if( ( (pSiS->restorebyset) || + (pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) || + ((pSiS->sishw_ext.jChipType == SIS_730) && (pSiS->VBFlags & VB_LVDS)) ) && + (pSiS->OldMode) ) { + + if(pSiS->AccelInfoPtr) { + (*pSiS->AccelInfoPtr->Sync)(pScrn); + } + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Restoring by setting old mode 0x%02x\n", pSiS->OldMode); + + if( (pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) && + (!pSiS->restorebyset) ) { + if(pSiS->OldMode == 0x03) pSiS->OldMode = 0x13; + } + + pSiS->SiS_Pr->UseCustomMode = FALSE; + pSiS->SiS_Pr->CRT1UsesCustomMode = FALSE; + SiSSetMode(pSiS->SiS_Pr, &pSiS->sishw_ext, pScrn, pSiS->OldMode, FALSE); +#ifdef TWDEBUG + { + SISRegPtr pReg = &pSiS->ModeReg; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "REAL REGISTER CONTENTS AFTER RESTORE BY SETMODE:\n"); + (*pSiS->SiSSave)(pScrn, pReg); + } +#endif + + } else { + + if(pSiS->VBFlags & VB_VIDEOBRIDGE) { + /* TW: If a video bridge is present, we need to restore + * non-extended (=standard VGA) SR and CR registers + * before restoring the extended ones and the bridge + * registers itself. Unfortunately, the vgaHWRestore + * routine clears CR17[7] - which must not be done if + * the bridge is in slave mode. + */ + if(!(SiSBridgeIsInSlaveMode(pScrn))) { + vgaHWProtect(pScrn, TRUE); + + if(pSiS->Primary) { + vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE); + } + } + } + + (*pSiS->SiSRestore)(pScrn, sisReg); + + } + + if(doitlater) { + outSISIDXREG(SISCR, 0x17, pSiS->oldCR17); + } + + sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[0x05],sisReg->sisRegs3D4[0x80]); + + if( ( (pSiS->sishw_ext.jChipType == SIS_730) && (pSiS->VBFlags & VB_LVDS)) || + (pSiS->restorebyset) ) { + + /* TW: SiS730/LVDS has extreme problems restoring the text display due + * to over-sensible LCD panels + */ + + vgaHWProtect(pScrn, TRUE); + + if(pSiS->Primary) { + vgaHWRestore(pScrn, vgaReg, (VGA_SR_FONTS | VGA_SR_CMAP)); + } + + vgaHWProtect(pScrn, FALSE); + + } else { + + vgaHWProtect(pScrn, TRUE); + + if(pSiS->Primary) { + vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); + } + + vgaHWProtect(pScrn, FALSE); + + } + + } else { /* All other chipsets */ + + vgaHWProtect(pScrn, TRUE); +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL,NULL); +#endif + (*pSiS->SiSRestore)(pScrn, sisReg); + + vgaHWProtect(pScrn, TRUE); + if(pSiS->Primary) { + vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); + } + + /* TW: Restore TV. This is rather complicated, but if we don't do it, + * TV output will flicker terribly + */ + if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { + if(sisReg->sis6326tv[0] & 0x04) { + unsigned char tmp; + int val; + + orSISIDXREG(SISSR, 0x01, 0x20); + tmp = SiS6326GetTVReg(pScrn,0x00); + tmp &= ~0x04; + while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ + SiS6326SetTVReg(pScrn,0x00,tmp); + for(val=0; val < 2; val++) { + while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ + while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ + } + SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); + tmp = inSISREG(SISINPSTAT); + outSISREG(SISAR, 0x20); + tmp = inSISREG(SISINPSTAT); + while(inSISREG(SISINPSTAT) & 0x01); + while(!(inSISREG(SISINPSTAT) & 0x01)); + andSISIDXREG(SISSR, 0x01, ~0x20); + for(val=0; val < 10; val++) { + while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ + while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ + } + andSISIDXREG(SISSR, 0x01, ~0x20); + } + } + + sisRestoreExtRegisterLock(pSiS,sisReg->sisRegs3C4[5],sisReg->sisRegs3D4[0x80]); + + vgaHWProtect(pScrn, FALSE); + } +} + +static void +SISVESARestore(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + + if(pSiS->UseVESA) SISVESASaveRestore(pScrn, MODE_RESTORE); +} + +/* TW: Restore bridge registers - to be called BEFORE VESARestore */ +static void +SISBridgeRestore(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + +#ifdef SISDUALHEAD + /* We only restore for master head */ + if(pSiS->DualHeadMode && pSiS->SecondHead) return; +#endif + + if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { + SiSRestoreBridge(pScrn, &pSiS->SavedReg); + } +} + +/* TW: Our generic BlockHandler for Xv */ +static void +SISBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + ScrnInfoPtr pScrn = xf86Screens[i]; + SISPtr pSiS = SISPTR(pScrn); + + pScreen->BlockHandler = pSiS->BlockHandler; + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + pScreen->BlockHandler = SISBlockHandler; + + if(pSiS->VideoTimerCallback) { + (*pSiS->VideoTimerCallback)(pScrn, currentTime.milliseconds); + } +} + +/* Mandatory + * This gets called at the start of each server generation + * + * TW: We use pScrn and not CurrentLayout here, because the + * properties we use have not changed (displayWidth, + * depth, bitsPerPixel) + */ +static Bool +SISScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +{ + ScrnInfoPtr pScrn; + vgaHWPtr hwp; + SISPtr pSiS; + int ret; + int init_picture = 0; + VisualPtr visual; + unsigned long OnScreenSize; + int height, width, displayWidth; + unsigned char *FBStart; +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = NULL; +#endif + + pScrn = xf86Screens[pScreen->myNum]; + + hwp = VGAHWPTR(pScrn); + + pSiS = SISPTR(pScrn); + + if(pSiS->UseVESA) { +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) + pSiS->pVbe = VBEInit(NULL, pSiS->pEnt->index); +#else + pSiS->pVbe = VBEExtendedInit(NULL, pSiS->pEnt->index, + SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); +#endif + } + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + pSiSEnt = pSiS->entityPrivate; + pSiSEnt->refCount++; + } +#endif + + /* Map the VGA memory and get the VGA IO base */ + if(pSiS->Primary) { + hwp->MapSize = 0x10000; /* Standard 64k VGA window */ + if(!vgaHWMapMem(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not map VGA window\n"); + return FALSE; + } + } + vgaHWGetIOBase(hwp); + + /* TW: Patch the PIOOffset inside vgaHW to use + * our relocated IO ports. + */ + VGAHWPTR(pScrn)->PIOOffset = pSiS->IODBase + (pSiS->PciInfo->ioBase[2] & 0xFFFC) - 0x380; + + /* Map the SIS memory and MMIO areas */ + if(!SISMapMem(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "SiSMapMem() failed\n"); + return FALSE; + } + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + /* TW: Enable TurboQueue so that SISSave() saves it in enabled + * state. If we don't do this, X will hang after a restart! + * (Happens for some unknown reason only when using VESA + * for mode switching; assumingly a BIOS issue.) + * This is done on 300 and 310/325 series only. + */ + if(pSiS->UseVESA) { + SiSEnableTurboQueue(pScrn); + } + + /* Save the current state */ + SISSave(pScrn); + + /* TW: Save the current mode number */ + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + inSISIDXREG(SISCR, 0x34, pSiS->OldMode); + } + + /* Initialise the first mode */ + if(!SISModeInit(pScrn, pScrn->currentMode)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "SiSModeInit() failed\n"); + return FALSE; + } + + /* Darken the screen for aesthetic reasons */ + /* TW: Not using Dual Head variant on purpose; we darken + * the screen for both displays, and un-darken + * it when the second head is finished + */ + SISSaveScreen(pScreen, SCREEN_SAVER_ON); + + /* Set the viewport */ + SISAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + /* Clear frame buffer */ + OnScreenSize = pScrn->displayWidth * pScrn->currentMode->VDisplay + * (pScrn->bitsPerPixel / 8); + bzero(pSiS->FbBase, OnScreenSize); + + /* + * The next step is to setup the screen's visuals, and initialise the + * framebuffer code. In cases where the framebuffer's default + * choices for things like visual layouts and bits per RGB are OK, + * this may be as simple as calling the framebuffer's ScreenInit() + * function. If not, the visuals will need to be setup before calling + * a fb ScreenInit() function and fixed up after. + * + * For most PC hardware at depths >= 8, the defaults that cfb uses + * are not appropriate. In this driver, we fixup the visuals after. + */ + + /* + * Reset visual list. + */ + miClearVisualTypes(); + + /* Setup the visuals we support. */ + + /* + * For bpp > 8, the default visuals are not acceptable because we only + * support TrueColor and not DirectColor. + */ + if(pScrn->bitsPerPixel > 8) { + if(!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits, + pScrn->defaultVisual)) { + SISSaveScreen(pScreen, SCREEN_SAVER_OFF); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "miSetVisualTypes() failed (bpp %d)\n", pScrn->bitsPerPixel); + return FALSE; + } + } else { + if(!miSetVisualTypes(pScrn->depth, + miGetDefaultVisualMask(pScrn->depth), + pScrn->rgbBits, pScrn->defaultVisual)) { + SISSaveScreen(pScreen, SCREEN_SAVER_OFF); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "miSetVisualTypes() failed (bpp %d)\n", pScrn->bitsPerPixel); + return FALSE; + } + } + + width = pScrn->virtualX; + height = pScrn->virtualY; + displayWidth = pScrn->displayWidth; + + if(pSiS->Rotate) { + height = pScrn->virtualX; + width = pScrn->virtualY; + } + + if(pSiS->ShadowFB) { + pSiS->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); + pSiS->ShadowPtr = xalloc(pSiS->ShadowPitch * height); + displayWidth = pSiS->ShadowPitch / (pScrn->bitsPerPixel >> 3); + FBStart = pSiS->ShadowPtr; + } else { + pSiS->ShadowPtr = NULL; + FBStart = pSiS->FbBase; + } + + if(!miSetPixmapDepths()) { + SISSaveScreen(pScreen, SCREEN_SAVER_OFF); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "miSetPixmapDepths() failed\n"); + return FALSE; + } + +#ifdef SISDUALHEAD + if(pSiS->SecondHead) + pSiS->cmdQueueLenPtr = &(SISPTR(pSiSEnt->pScrn_1)->cmdQueueLen); + else +#endif + pSiS->cmdQueueLenPtr = &(pSiS->cmdQueueLen); + + pSiS->cmdQueueLen = 0; /* TW: Force an EngineIdle() at start */ + +#ifdef XF86DRI +#ifdef SISDUALHEAD + /* TW: No DRI in dual head mode */ + if(pSiS->DualHeadMode) { + pSiS->directRenderingEnabled = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "DRI not supported in Dual Head mode\n"); + } else +#endif + /* Force the initialization of the context */ + if(pSiS->VGAEngine != SIS_315_VGA) { + pSiS->directRenderingEnabled = SISDRIScreenInit(pScreen); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_NOT_IMPLEMENTED, + "DRI not supported on this chipset\n"); + pSiS->directRenderingEnabled = FALSE; + } +#endif + + /* + * Call the framebuffer layer's ScreenInit function, and fill in other + * pScreen fields. + */ + + switch(pScrn->bitsPerPixel) { + case 1: + ret = xf1bppScreenInit(pScreen, FBStart, width, + height, pScrn->xDpi, pScrn->yDpi, + displayWidth); + break; + case 4: + ret = xf4bppScreenInit(pScreen, FBStart, width, + height, pScrn->xDpi, pScrn->yDpi, + displayWidth); + break; + case 8: + case 16: + case 24: + case 32: + ret = fbScreenInit(pScreen, FBStart, width, + height, pScrn->xDpi, pScrn->yDpi, + displayWidth, pScrn->bitsPerPixel); + + init_picture = 1; + break; + default: + xf86DrvMsg(scrnIndex, X_ERROR, + "Internal error: invalid bpp (%d) in SISScrnInit\n", + pScrn->bitsPerPixel); + ret = FALSE; + break; + } + if (!ret) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "xf1bpp/xf4bpp/fbScreenInit() failed\n"); + SISSaveScreen(pScreen, SCREEN_SAVER_OFF); + return FALSE; + } + + if(pScrn->bitsPerPixel > 8) { + /* Fixup RGB ordering */ + visual = pScreen->visuals + pScreen->numVisuals; + while (--visual >= pScreen->visuals) { + if ((visual->class | DynamicClass) == DirectColor) { + visual->offsetRed = pScrn->offset.red; + visual->offsetGreen = pScrn->offset.green; + visual->offsetBlue = pScrn->offset.blue; + visual->redMask = pScrn->mask.red; + visual->greenMask = pScrn->mask.green; + visual->blueMask = pScrn->mask.blue; + } + } + } else if(pScrn->depth == 1) { + SIS1bppColorMap(pScrn); + } + + /* Initialize RENDER ext; must be after RGB ordering fixed */ + if(init_picture) fbPictureInit(pScreen, 0, 0); + + /* hardware cursor needs to wrap this layer <-- TW: what does that mean? */ + if(!pSiS->ShadowFB) SISDGAInit(pScreen); + + xf86SetBlackWhitePixels(pScreen); + + if(!pSiS->NoAccel) { + switch(pSiS->VGAEngine) { + case SIS_530_VGA: + case SIS_300_VGA: + SiS300AccelInit(pScreen); + break; + case SIS_315_VGA: + SiS310AccelInit(pScreen); + break; + default: + SiSAccelInit(pScreen); + } + } + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + xf86SetSilkenMouse(pScreen); + + /* Initialise cursor functions */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + if(pSiS->HWCursor) + SiSHWCursorInit(pScreen); + + /* Initialise default colourmap */ + if(!miCreateDefColormap(pScreen)) { + SISSaveScreen(pScreen, SCREEN_SAVER_OFF); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "miCreateDefColormap() failed\n"); + return FALSE; + } + + if(!xf86HandleColormaps(pScreen, 256, (pScrn->depth == 8) ? 8 : pScrn->rgbBits, + SISLoadPalette, NULL, + CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) { + SISSaveScreen(pScreen, SCREEN_SAVER_OFF); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "xf86HandleColormaps() failed\n"); + return FALSE; + } + + if(pSiS->ShadowFB) { + RefreshAreaFuncPtr refreshArea = SISRefreshArea; + + if(pSiS->Rotate) { + if(!pSiS->PointerMoved) { + pSiS->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = SISPointerMoved; + } + + switch(pScrn->bitsPerPixel) { + case 8: refreshArea = SISRefreshArea8; break; + case 16: refreshArea = SISRefreshArea16; break; + case 24: refreshArea = SISRefreshArea24; break; + case 32: refreshArea = SISRefreshArea32; break; + } + } + + ShadowFBInit(pScreen, refreshArea); + } + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) + /* TW: DPMS for dual head mode */ + xf86DPMSInit(pScreen, (DPMSSetProcPtr)SISDisplayPowerManagementSetDH, 0); + else +#endif + xf86DPMSInit(pScreen, (DPMSSetProcPtr)SISDisplayPowerManagementSet, 0); + + /* Init memPhysBase and fbOffset in pScrn */ + pScrn->memPhysBase = pSiS->FbAddress; + pScrn->fbOffset = 0; + +#ifdef XvExtension + if(!pSiS->NoXvideo) { +#ifdef SISDUALHEAD + /* TW: On chipsets with only one overlay, we support + * Xv only in "real" dual head mode, not Xinerama + */ + if ( ((pSiS->VGAEngine == SIS_300_VGA) || + (pSiS->VGAEngine == SIS_315_VGA) ) + && + ((pSiS->hasTwoOverlays) || + (!pSiS->DualHeadMode) || + (noPanoramiXExtension) ) ) { +#else + if ( (pSiS->VGAEngine == SIS_300_VGA) || + (pSiS->VGAEngine == SIS_315_VGA) ) { +#endif +#ifdef SISDUALHEAD + if (pSiS->DualHeadMode) { + if ( pSiS->hasTwoOverlays || + (pSiS->XvOnCRT2 && (!pSiS->SecondHead)) || + ((!pSiS->XvOnCRT2 && pSiS->SecondHead)) ) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using SiS300/310/325 series HW Xv on CRT%d\n", + (pSiS->SecondHead ? 1 : 2)); + SISInitVideo(pScreen); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using SiS300/310/325 series HW Xv on CRT%d\n", + (pSiS->SecondHead ? 1 : 2)); + } + } else { +#endif + if (pSiS->hasTwoOverlays) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using SiS300/310/325 series HW Xv\n" ); + else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using SiS300/310/325 series HW Xv on CRT%d\n", + (pSiS->XvOnCRT2 ? 2 : 1)); + SISInitVideo(pScreen); +#ifdef SISDUALHEAD + } +#endif +#ifdef USE6326VIDEO + } else if( pSiS->Chipset == PCI_CHIP_SIS6326 || + pSiS->Chipset == PCI_CHIP_SIS530 || + pSiS->Chipset == PCI_CHIP_SIS5597 ) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using SiS5597/5598/6326/530/620 HW Xv\n" ); + SIS6326InitVideo(pScreen); +#endif + } else { /* generic Xv */ + + XF86VideoAdaptorPtr *ptr; + int n; + + n = xf86XVListGenericAdaptors(pScrn, &ptr); + if (n) { + xf86XVScreenInit(pScreen, ptr, n); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using generic Xv\n" ); + } + if (!noPanoramiXExtension) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "HW Xv not supported in Xinerama mode\n"); + } + } +#endif + +#ifdef XF86DRI + if(pSiS->directRenderingEnabled) { + /* Now that mi, drm and others have done their thing, + * complete the DRI setup. + */ + pSiS->directRenderingEnabled = SISDRIFinishScreenInit(pScreen); + } + if(pSiS->directRenderingEnabled) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); + /* TODO */ + /* SISSetLFBConfig(pSiS); */ + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering disabled\n"); + } +#endif + + pSiS->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = SISCloseScreen; +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) + pScreen->SaveScreen = SISSaveScreenDH; + else +#endif + pScreen->SaveScreen = SISSaveScreen; + + /* Install BlockHandler */ + pSiS->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = SISBlockHandler; + + /* Report any unused options (only for the first generation) */ + if(serverGeneration == 1) { + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + } + + /* Turn on the screen now */ + /* TW: We do this in dual head mode after second head is finished */ +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(pSiS->SecondHead) + SISSaveScreen(pScreen, SCREEN_SAVER_OFF); + } else +#endif + SISSaveScreen(pScreen, SCREEN_SAVER_OFF); + + return TRUE; +} + +/* Usually mandatory */ +Bool +SISSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + SISPtr pSiS = SISPTR(pScrn); + + if(!pSiS->NoAccel) { + if(pSiS->AccelInfoPtr) { + (*pSiS->AccelInfoPtr->Sync)(pScrn); + } + } + + return SISModeInit(xf86Screens[scrnIndex], mode); +} + +#ifdef CYCLECRT2 +/* TW: Cycle CRT2 output devices */ +Bool +SISCycleCRT2Type(int scrnIndex, DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + SISPtr pSiS = SISPTR(pScrn); + int i = 0; + + /* TW: Only on 300 and 310/325 series */ + if(pSiS->VGAEngine != SIS_300_VGA && + pSiS->VGAEngine != SIS_315_VGA) return FALSE; + + /* TW: Only if there is a video bridge */ + if(pSiS->VBFlags & VB_VIDEOBRIDGE) return FALSE; + + /* TW: Only if there were more than 1 CRT2 devices detected */ + if(pSiS->detectedCRT2Devices & CRT2_VGA) i++; + if(pSiS->detectedCRT2Devices & CRT2_LCD) i++; + if(pSiS->detectedCRT2Devices & CRT2_TV) i++; + if(i <= 1) return FALSE; + + /* TW: Cycle CRT2 type */ + i = (pSiS->VBFlags & DISPTYPE_DISP2) << 1; + while(!(i & pSiS->detectedCRT2Devices)) { + i <<= 1; + if(i > CRT2_VGA) i = CRT2_LCD; + } + + /* TW: Check if mode is suitable for desired output device */ + if(!SiS_CheckCalcModeIndex(pScrn, pScrn->currentMode, + ((pSiS->VBFlags & ~(DISPTYPE_DISP2)) | i))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Current mode not suitable for desired CRT2 output device\n"); + return FALSE; + } + + /* TW: Sync the accelerators */ + if(!pSiS->NoAccel) { + if(pSiS->AccelInfoPtr) { + (*pSiS->AccelInfoPtr->Sync)(pScrn); + } + } + + pSiS->VBFlags &= ~(DISPTYPE_DISP2); + pSiS->VBFlags |= i; + + return SISModeInit(xf86Screens[scrnIndex], mode); +} +#endif + +/* + * This function is used to initialize the Start Address - the first + * displayed location in the video memory. + */ +/* Usually mandatory */ +void +SISAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + SISPtr pSiS; + vgaHWPtr hwp; + int base; + unsigned char temp; + + hwp = VGAHWPTR(pScrn); + pSiS = SISPTR(pScrn); + + base = y * pSiS->CurrentLayout.displayWidth + x; + + if(pSiS->UseVESA) { + + /* TW: Let BIOS adjust frame if using VESA */ + VBESetDisplayStart(pSiS->pVbe, x, y, TRUE); + + } else { + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + if(pScrn->bitsPerPixel < 8) { + base = (y * pSiS->CurrentLayout.displayWidth + x + 3) >> 3; + } else { + base = y * pSiS->CurrentLayout.displayWidth + x; + + /* calculate base bpp dep. */ + switch(pSiS->CurrentLayout.bitsPerPixel) { + case 16: + base >>= 1; + break; + case 24: + base = ((base * 3)) >> 2; + base -= base % 6; + break; + case 32: + break; + default: /* 8bpp */ + base >>= 2; + break; + } + } + +#ifdef SISDUALHEAD + if (pSiS->DualHeadMode) { + /* TW: We assume that DualHeadMode only can be true for + * dual head capable chipsets (and thus save the check + * for chipset here) + */ + if (!pSiS->SecondHead) { + /* TW: Head 1 (master) is always CRT2 */ + SiS_UnLockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + outSISIDXREG(SISPART1, 0x06, GETVAR8(base)); + outSISIDXREG(SISPART1, 0x05, GETBITS(base, 15:8)); + outSISIDXREG(SISPART1, 0x04, GETBITS(base, 23:16)); + if (pSiS->VGAEngine == SIS_315_VGA) { + setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); + } + SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + } else { + /* TW: Head 2 (slave) is always CRT1 */ + base += (pSiS->dhmOffset/4); + outSISIDXREG(SISCR, 0x0D, base & 0xFF); + outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); + outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); + if (pSiS->VGAEngine == SIS_315_VGA) { + setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); + } + } + } else { +#endif + switch (pSiS->VGAEngine) { + case SIS_300_VGA: + outSISIDXREG(SISCR, 0x0D, base & 0xFF); + outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); + outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); + if (pSiS->VBFlags & CRT2_ENABLE) { + SiS_UnLockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + outSISIDXREG(SISPART1, 0x06, GETVAR8(base)); + outSISIDXREG(SISPART1, 0x05, GETBITS(base, 15:8)); + outSISIDXREG(SISPART1, 0x04, GETBITS(base, 23:16)); + SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + } + break; + case SIS_315_VGA: + outSISIDXREG(SISCR, 0x0D, base & 0xFF); + outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); + outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); + setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); + if (pSiS->VBFlags & CRT2_ENABLE) { + SiS_UnLockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + outSISIDXREG(SISPART1, 0x06, GETVAR8(base)); + outSISIDXREG(SISPART1, 0x05, GETBITS(base, 15:8)); + outSISIDXREG(SISPART1, 0x04, GETBITS(base, 23:16)); + setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); + SiS_LockCRT2(pSiS->SiS_Pr, &pSiS->sishw_ext, pSiS->RelIO+0x30); + } + break; + default: + outSISIDXREG(SISCR, 0x0D, base & 0xFF); + outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); + inSISIDXREG(SISSR, 0x27, temp); + temp &= 0xF0; + temp |= (base & 0x0F0000) >> 16; + outSISIDXREG(SISSR, 0x27, temp); + } +#ifdef SISDUALHEAD + } +#endif + } /* if not VESA */ + +} + + +/* + * This is called when VT switching back to the X server. Its job is + * to reinitialise the video mode. + * Mandatory! + */ +static Bool +SISEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + SISPtr pSiS = SISPTR(pScrn); + + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); + + if(!SISModeInit(pScrn, pScrn->currentMode)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "SiSEnterVT: SISModeInit() failed\n"); + return FALSE; + } + + SISAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + +#ifdef XF86DRI + /* TW: this is to be done AFTER switching the mode */ + if(pSiS->directRenderingEnabled) + DRIUnlock(screenInfo.screens[scrnIndex]); +#endif + + return TRUE; +} + +/* + * This is called when VT switching away from the X server. Its job is + * to restore the previous (text) mode. + * Mandatory! + */ +static void +SISLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + vgaHWPtr hwp = VGAHWPTR(pScrn); + SISPtr pSiS = SISPTR(pScrn); +#ifdef XF86DRI + ScreenPtr pScreen; + + /* TW: to be done before mode change */ + if(pSiS->directRenderingEnabled) { + pScreen = screenInfo.screens[scrnIndex]; + DRILock(pScreen, 0); + } +#endif + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode && pSiS->SecondHead) return; +#endif + + if(pSiS->CursorInfoPtr) { +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(!pSiS->SecondHead) { + pSiS->ForceCursorOff = TRUE; + pSiS->CursorInfoPtr->HideCursor(pScrn); + SISWaitVBRetrace(pScrn); + pSiS->ForceCursorOff = FALSE; + } + } else { +#endif + pSiS->CursorInfoPtr->HideCursor(pScrn); + SISWaitVBRetrace(pScrn); +#ifdef SISDUALHEAD + } +#endif + } + + SISBridgeRestore(pScrn); + + if(pSiS->UseVESA) { + + /* TW: This is a q&d work-around for a BIOS bug. In case we disabled CRT2, + * VBESaveRestore() does not restore CRT1. So we set any mode now, + * because VBESetVBEMode correctly restores CRT1. Afterwards, we + * can call VBESaveRestore to restore original mode. + */ + if ( (pSiS->VBFlags & VB_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2)) ) + VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); + + SISVESARestore(pScrn); + + } else { + + SISRestore(pScrn); + + } + + vgaHWLock(hwp); +} + + +/* + * This is called at the end of each server generation. It restores the + * original (text) mode. It should really also unmap the video memory too. + * Mandatory! + */ +static Bool +SISCloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + vgaHWPtr hwp = VGAHWPTR(pScrn); + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + +#ifdef XF86DRI + if(pSiS->directRenderingEnabled) { + SISDRICloseScreen(pScreen); + pSiS->directRenderingEnabled = FALSE; + } +#endif + + if(pScrn->vtSema) { + + if(pSiS->CursorInfoPtr) { +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(!pSiS->SecondHead) { + pSiS->ForceCursorOff = TRUE; + pSiS->CursorInfoPtr->HideCursor(pScrn); + SISWaitVBRetrace(pScrn); + pSiS->ForceCursorOff = FALSE; + } + } else { +#endif + pSiS->CursorInfoPtr->HideCursor(pScrn); + SISWaitVBRetrace(pScrn); +#ifdef SISDUALHEAD + } +#endif + } + + SISBridgeRestore(pScrn); + + if(pSiS->UseVESA) { + + /* TW: This is a q&d work-around for a BIOS bug. In case we disabled CRT2, + * VBESaveRestore() does not restore CRT1. So we set any mode now, + * because VBESetVBEMode correctly restores CRT1. Afterwards, we + * can call VBESaveRestore to restore original mode. + */ + if( (pSiS->VBFlags & VB_VIDEOBRIDGE) && (!(pSiS->VBFlags & DISPTYPE_DISP2))) + VBESetVBEMode(pSiS->pVbe, (pSiS->SISVESAModeList->n) | 0xc000, NULL); + + SISVESARestore(pScrn); + + } else { + + SISRestore(pScrn); + + } + + vgaHWLock(hwp); + } + + SISUnmapMem(pScrn); + vgaHWUnmapMem(pScrn); + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + pSiSEnt = pSiS->entityPrivate; + pSiSEnt->refCount--; + } +#endif + + if(pSiS->pInt) { + xf86FreeInt10(pSiS->pInt); + pSiS->pInt = NULL; + } + + if(pSiS->AccelInfoPtr) { + XAADestroyInfoRec(pSiS->AccelInfoPtr); + pSiS->AccelInfoPtr = NULL; + } + + if(pSiS->CursorInfoPtr) { + xf86DestroyCursorInfoRec(pSiS->CursorInfoPtr); + pSiS->CursorInfoPtr = NULL; + } + + if(pSiS->ShadowPtr) { + xfree(pSiS->ShadowPtr); + pSiS->ShadowPtr = NULL; + } + + if(pSiS->DGAModes) { + xfree(pSiS->DGAModes); + pSiS->DGAModes = NULL; + } + + if(pSiS->adaptor) { + xfree(pSiS->adaptor); + pSiS->adaptor = NULL; + } + + pScrn->vtSema = FALSE; + + /* Restore Blockhandler */ + pScreen->BlockHandler = pSiS->BlockHandler; + + pScreen->CloseScreen = pSiS->CloseScreen; + return (*pScreen->CloseScreen)(scrnIndex, pScreen); +} + + +/* Free up any per-generation data structures */ + +/* Optional */ +static void +SISFreeScreen(int scrnIndex, int flags) +{ + if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) + vgaHWFreeHWRec(xf86Screens[scrnIndex]); + SISFreeRec(xf86Screens[scrnIndex]); +} + + +/* Checks if a mode is suitable for the selected chipset. */ + +/* Optional */ +static int +SISValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + SISPtr pSiS = SISPTR(pScrn); + + if(pSiS->UseVESA) { + if(SiSCalcVESAModeIndex(pScrn, mode)) + return(MODE_OK); + else + return(MODE_BAD); + } + if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { +#ifdef SISDUALHEAD + if((pSiS->DualHeadMode) && (pSiS->SecondHead)) { + /* DHM: Only check modes for CRT1 */ + if(SiS_CalcModeIndex(pScrn, mode) < 0x14) + return(MODE_BAD); + } else +#endif + if(SiS_CheckCalcModeIndex(pScrn, mode, pSiS->VBFlags) < 0x14) + return(MODE_BAD); + + } + + return(MODE_OK); +} + +/* Do screen blanking */ + +/* Mandatory */ +static Bool +SISSaveScreen(ScreenPtr pScreen, int mode) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if ((pScrn != NULL) && pScrn->vtSema) { + + SISPtr pSiS = SISPTR(pScrn); + + /* enable access to extended sequencer registers */ +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + if(pSiS->VGAEngine == SIS_300_VGA) { + + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + if(!xf86IsUnblank(mode)) { + pSiS->Blank = TRUE; + SiS_SiS30xBLOff(pSiS->SiS_Pr,&pSiS->sishw_ext); + } else { + pSiS->Blank = FALSE; + SiS_SiS30xBLOn(pSiS->SiS_Pr,&pSiS->sishw_ext); + } + } else { + /* if not blanked obtain state of LCD blank flags set by BIOS */ + if(!pSiS->Blank) { + inSISIDXREG(SISSR, 0x11, pSiS->LCDon); + } + + if(!xf86IsUnblank(mode)) { + pSiS->Blank = TRUE; + outSISIDXREG(SISSR, 0x11, pSiS->LCDon | 0x08); + } else { + pSiS->Blank = FALSE; + /* don't just unblanking; use LCD state set by BIOS */ + outSISIDXREG(SISSR, 0x11, pSiS->LCDon); + } + } + + } else if(pSiS->VGAEngine == SIS_315_VGA) { + + if(!pSiS->Blank) { + inSISIDXREG(SISSR, 0x11, pSiS->LCDon); + } + + if(pSiS->VBFlags & VB_CHRONTEL) { + if(!xf86IsUnblank(mode)) { + pSiS->Blank = TRUE; + SiS_Chrontel701xBLOff(pSiS->SiS_Pr); + } else { + pSiS->Blank = FALSE; + SiS_Chrontel701xBLOn(pSiS->SiS_Pr); + } + } else if(pSiS->VBFlags & VB_LVDS) { + if(!xf86IsUnblank(mode)) { + pSiS->Blank = TRUE; + outSISIDXREG(SISSR, 0x11, pSiS->LCDon | 0x08); + } else { + pSiS->Blank = FALSE; + outSISIDXREG(SISSR, 0x11, pSiS->LCDon); + } + } else if(pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) { + if(!xf86IsUnblank(mode)) { + pSiS->Blank = TRUE; + SiS_SiS30xBLOff(pSiS->SiS_Pr,&pSiS->sishw_ext); + } else { + pSiS->Blank = FALSE; + SiS_SiS30xBLOn(pSiS->SiS_Pr,&pSiS->sishw_ext); + } + } + + } + + } + + return vgaHWSaveScreen(pScreen, mode); +} + +#ifdef SISDUALHEAD +/* TW: SaveScreen for dual head mode */ +static Bool +SISSaveScreenDH(ScreenPtr pScreen, int mode) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if ((pScrn != NULL) && pScrn->vtSema) { + + SISPtr pSiS = SISPTR(pScrn); + if (pSiS->SecondHead) { + + /* Slave head is always CRT1 */ + return vgaHWSaveScreen(pScreen, mode); + + } else { + + /* Master head is always CRT2 */ + + /* We can only blank LCD, not other CRT2 devices */ + if(!(pSiS->VBFlags & CRT2_LCD)) return TRUE; + + /* enable access to extended sequencer registers */ +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + if(pSiS->VGAEngine == SIS_300_VGA) { + + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + if(!xf86IsUnblank(mode)) { + pSiS->BlankCRT2 = TRUE; + SiS_SiS30xBLOff(pSiS->SiS_Pr,&pSiS->sishw_ext); + } else { + pSiS->BlankCRT2 = FALSE; + SiS_SiS30xBLOn(pSiS->SiS_Pr,&pSiS->sishw_ext); + } + } else { + /* if not blanked obtain state of LCD blank flags set by BIOS */ + if(!pSiS->BlankCRT2) { + inSISIDXREG(SISSR, 0x11, pSiS->LCDon); + } + + if (!xf86IsUnblank(mode)) { + pSiS->BlankCRT2 = TRUE; + outSISIDXREG(SISSR, 0x11, pSiS->LCDon | 0x08); + } else { + pSiS->BlankCRT2 = FALSE; + /* don't just unblank; use LCD state set by BIOS */ + outSISIDXREG(SISSR, 0x11, pSiS->LCDon); + } + } + + } else if(pSiS->VGAEngine == SIS_315_VGA) { + + if(!pSiS->BlankCRT2) { + inSISIDXREG(SISSR, 0x11, pSiS->LCDon); + } + + if(pSiS->VBFlags & VB_CHRONTEL) { + if(!xf86IsUnblank(mode)) { + pSiS->BlankCRT2 = TRUE; + SiS_Chrontel701xBLOff(pSiS->SiS_Pr); + } else { + pSiS->BlankCRT2 = FALSE; + SiS_Chrontel701xBLOn(pSiS->SiS_Pr); + } + } else if(pSiS->VBFlags & VB_LVDS) { + if(!xf86IsUnblank(mode)) { + pSiS->BlankCRT2 = TRUE; + outSISIDXREG(SISSR, 0x11, pSiS->LCDon | 0x08); + } else { + pSiS->BlankCRT2 = FALSE; + outSISIDXREG(SISSR, 0x11, pSiS->LCDon); + } + } else if(pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) { + if(!xf86IsUnblank(mode)) { + pSiS->BlankCRT2 = TRUE; + SiS_SiS30xBLOff(pSiS->SiS_Pr,&pSiS->sishw_ext); + } else { + pSiS->BlankCRT2 = FALSE; + SiS_SiS30xBLOn(pSiS->SiS_Pr,&pSiS->sishw_ext); + } + } + + } + } + } + return TRUE; +} +#endif + +#ifdef DEBUG +/* locally used for debug */ +static void +SiSDumpModeInfo(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Clock : %x\n", mode->Clock); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Display : %x\n", mode->CrtcHDisplay); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank Start : %x\n", mode->CrtcHBlankStart); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync Start : %x\n", mode->CrtcHSyncStart); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Sync End : %x\n", mode->CrtcHSyncEnd); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Blank End : %x\n", mode->CrtcHBlankEnd); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Total : %x\n", mode->CrtcHTotal); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz Skew : %x\n", mode->CrtcHSkew); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Hz HAdjusted : %x\n", mode->CrtcHAdjusted); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Display : %x\n", mode->CrtcVDisplay); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank Start : %x\n", mode->CrtcVBlankStart); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync Start : %x\n", mode->CrtcVSyncStart); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Sync End : %x\n", mode->CrtcVSyncEnd); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Blank End : %x\n", mode->CrtcVBlankEnd); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt Total : %x\n", mode->CrtcVTotal); + xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Vt VAdjusted : %x\n", mode->CrtcVAdjusted); +} +#endif + +/* local used for debug */ +static void +SISModifyModeInfo(DisplayModePtr mode) +{ +#if 1 + if(mode->CrtcHBlankStart == mode->CrtcHDisplay) + mode->CrtcHBlankStart++; + if(mode->CrtcHBlankEnd == mode->CrtcHTotal) + mode->CrtcHBlankEnd--; + if(mode->CrtcVBlankStart == mode->CrtcVDisplay) + mode->CrtcVBlankStart++; + if(mode->CrtcVBlankEnd == mode->CrtcVTotal) + mode->CrtcVBlankEnd--; +#endif +} + +/* TW: Enable the TurboQueue (For 300 and 310/325 series only) */ +void +SiSEnableTurboQueue(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned short SR26, SR27; + unsigned long temp; + + switch (pSiS->VGAEngine) { + case SIS_300_VGA: + if ((!pSiS->NoAccel) && (pSiS->TurboQueue)) { + /* TQ size is always 512k */ + temp = (pScrn->videoRam/64) - 8; + SR26 = temp & 0xFF; + inSISIDXREG(SISSR, 0x27, SR27); + SR27 &= 0xFC; + SR27 |= (0xF0 | ((temp >> 8) & 3)); + outSISIDXREG(SISSR, 0x26, SR26); + outSISIDXREG(SISSR, 0x27, SR27); + } + break; + case SIS_315_VGA: + if (!pSiS->NoAccel) { + /* TW: On 310/325 series, there are three queue modes available + * which are chosen by setting bits 7:5 in SR26: + * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep + * track of the queue, the FIFO, command parsing and so + * on. This is the one comparable to the 300 series. + * 2. VRAM queue mode (bit 6, 0x40). In this case, one will + * have to do queue management himself. Register 0x85c4 will + * hold the location of the next free queue slot, 0x85c8 + * is the "queue read pointer" whose way of working is + * unknown to me. Anyway, this mode would require a + * translation of the MMIO commands to some kind of + * accelerator assembly and writing these commands + * to the memory location pointed to by 0x85c4. + * We will not use this, as nobody knows how this + * "assembly" works, and as it would require a complete + * re-write of the accelerator code. + * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the + * queue in AGP memory space. + * We go MMIO here. + * SR26 bit 4 is called "Bypass H/W queue". + * SR26 bit 1 is called "Enable Command Queue Auto Correction" + * SR26 bit 0 resets the queue + * Size of queue memory is encoded in bits 3:2 like this: + * 00 (0x00) 512K + * 01 (0x04) 1M + * 10 (0x08) 2M + * 11 (0x0C) 4M + * The queue location is to be written to 0x85C0. + */ +#if 0 + if (pSiS->TurboQueue) { +#endif + /* TW: We only use MMIO Cmd Queue, not VRAM or AGP */ + /* TW: Set Command Queue Threshold to max value 11111b */ + outSISIDXREG(SISSR, 0x27, 0x1F); + /* TW: Syncronous reset for Command Queue */ + outSISIDXREG(SISSR, 0x26, 0x01); + /* TW: Do some magic (cp readport to writeport) */ + temp = MMIO_IN32(pSiS->IOBase, 0x85C8); + MMIO_OUT32(pSiS->IOBase, 0x85C4, temp); + /* TW: Enable MMIO Command Queue mode (0x20), + * Enable_command_queue_auto_correction (0x02) + * (no idea, but sounds good, so use it) + * 512k (0x00) (does this apply to MMIO mode?) */ + outSISIDXREG(SISSR, 0x26, 0x22); + /* TW: Calc Command Queue position (Q is always 512k)*/ + temp = (pScrn->videoRam - 512) * 1024; + /* TW: Set Q position */ + MMIO_OUT32(pSiS->IOBase, 0x85C0, temp); +#if 0 + } else { + /* TW: Is there a non-TurboQueue mode within MMIO mode? */ + } +#endif + } + break; + default: + break; + } +} + +/* TW: Things to do before a ModeSwitch. We set up the + * video bridge configuration and the TurboQueue. + */ +void SiSPreSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char usScratchCR30, usScratchCR31; + unsigned char usScratchCR32, usScratchCR33; + unsigned char usScratchCR17, usScratchCR38 = 0; + int vbflag, temp = 0; + int crt1rateindex = 0; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); /* Unlock Registers */ +#endif + + vbflag = pSiS->VBFlags; + pSiS->IsCustom = FALSE; + + if(pSiS->HaveCustomModes) { + if(!(mode->type & M_T_DEFAULT)) { + pSiS->IsCustom = TRUE; + } + } + + /* TW: The CR3x registers are for communicating with our BIOS emulation + * code (native code in init.c/init301.c) or the BIOS (via VESA) + */ + inSISIDXREG(SISCR, 0x30, usScratchCR30); /* Bridge config */ + inSISIDXREG(SISCR, 0x31, usScratchCR31); /* Bridge config */ + usScratchCR32 = pSiS->newCR32; /* Bridge connection info (use our new value) */ + inSISIDXREG(SISCR, 0x33, usScratchCR33); /* CRT1 refresh rate index */ + if(pSiS->Chipset != PCI_CHIP_SIS300) { + switch(pSiS->VGAEngine) { + case SIS_300_VGA: temp = 0x35; break; + case SIS_315_VGA: temp = 0x38; break; + } + } + if(temp) inSISIDXREG(SISCR, temp, usScratchCR38); /* PAL-M, PAL-N selection */ + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "VBFlags=0x%x\n", pSiS->VBFlags); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 3, + "Before: CR30=0x%02x, CR31=0x%02x, CR32=0x%02x, CR33=0x%02x, CR%02x=0x%02x\n", + usScratchCR30, usScratchCR31, usScratchCR32, usScratchCR33, temp, usScratchCR38); + + usScratchCR30 = 0; + usScratchCR31 &= ~0x60; /* TW: Clear VB_Drivermode & VB_OutputDisable */ +#if 0 /* TW: For future use */ + if( (pSiS->VBFlags & VB_LVDS) || + (pSiS->VBFlags & VB_301) || + ( (pSiS->VBFlags & (VB_301B | VB_302B |VB_30xLV | VB_30xLVX)) && + (!(pSiS->VBLCDFlags & VB_LCD_1400x1050)) ) ) { +#endif + usScratchCR31 |= 0x04; /* TW: Set VB_NotSimuMode (not for 30xB/1400x1050?) */ +#if 0 + } +#endif + + switch(vbflag & (CRT2_TV|CRT2_LCD|CRT2_VGA)) { + case CRT2_TV: + if(vbflag & TV_CHSCART) { + usScratchCR38 |= 0x04; + usScratchCR31 |= 0x01; + } else if(vbflag & TV_CHHDTV) { + usScratchCR38 |= 0x08; + usScratchCR31 &= ~0x01; + } else if(vbflag & TV_HIVISION) + usScratchCR30 |= 0x80; + else if(vbflag & TV_SVIDEO) + usScratchCR30 |= 0x08; + else if(vbflag & TV_AVIDEO) + usScratchCR30 |= 0x04; + else if(vbflag & TV_SCART) + usScratchCR30 |= 0x10; + else + usScratchCR30 |= 0x08; /* default: SVIDEO */ + + if(!(vbflag & (TV_CHSCART | TV_CHHDTV))) { + if(vbflag & TV_PAL) { + usScratchCR31 |= 0x01; + usScratchCR38 &= ~0xC0; + if( (vbflag & VB_SISBRIDGE) || + ((vbflag & VB_CHRONTEL) && (pSiS->ChrontelType == CHRONTEL_701x)) ) { + if(vbflag & TV_PALM) usScratchCR38 |= 0x40; + else if(vbflag & TV_PALN) usScratchCR38 |= 0x80; + } + } else + usScratchCR31 &= ~0x01; + } + + usScratchCR30 |= 0x01; /* Set SimuScanMode */ + + usScratchCR31 &= ~0x04; /* Clear NotSimuMode */ + pSiS->SiS_Pr->SiS_CHOverScan = pSiS->UseCHOverScan; + if(pSiS->OptTVSOver == 1) { + pSiS->SiS_Pr->SiS_CHSOverScan = TRUE; + } else { + pSiS->SiS_Pr->SiS_CHSOverScan = FALSE; + } + break; + case CRT2_LCD: + usScratchCR30 |= 0x21; /* LCD + SimuScanMode */ + break; + case CRT2_VGA: + usScratchCR30 |= 0x41; /* VGA2 + SimuScanMode */ + break; + default: + usScratchCR30 |= 0x00; + usScratchCR31 |= 0x20; /* VB_OUTPUT_DISABLE */ + if(pSiS->UseVESA) { + crt1rateindex = SISSearchCRT1Rate(pScrn, mode); + } + } + /* TW: for VESA: no DRIVERMODE, otherwise + * -) CRT2 will not be initialized correctly when using mode + * where LCD has to scale, and + * -) CRT1 will have too low rate + */ + if (pSiS->UseVESA) { + usScratchCR31 &= 0x40; /* TW: Clear Drivermode */ +#ifdef TWDEBUG + usScratchCR31 |= 0x40; /* DEBUG (for non-slave mode VESA) */ + crt1rateindex = SISSearchCRT1Rate(pScrn, mode); +#endif + } else { + usScratchCR31 |= 0x40; /* TW: Set Drivermode */ + if(!pSiS->IsCustom) { + crt1rateindex = SISSearchCRT1Rate(pScrn, mode); + } else { + crt1rateindex = usScratchCR33; + } + } + outSISIDXREG(SISCR, 0x30, usScratchCR30); + outSISIDXREG(SISCR, 0x31, usScratchCR31); + if(temp) { + usScratchCR38 &= ~0x03; /* Clear LCDA/DualEdge bits */ + outSISIDXREG(SISCR, temp, usScratchCR38); + } + + pSiS->SiS_Pr->SiS_UseOEM = pSiS->OptUseOEM; + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(pSiS->SecondHead) { + /* CRT1 */ + usScratchCR33 &= 0xf0; + usScratchCR33 |= (crt1rateindex & 0x0f); + } else { + /* CRT2 */ + usScratchCR33 &= 0x0f; + if(vbflag & CRT2_VGA) usScratchCR33 |= ((crt1rateindex << 4) & 0xf0); + } + } else { +#endif + if(vbflag & CRT2_VGA) { + usScratchCR33 = (crt1rateindex & 0x0f) | ((crt1rateindex & 0x0f) << 4); + } else { + usScratchCR33 = crt1rateindex & 0x0f; + } + if((!(pSiS->UseVESA)) && (vbflag & CRT2_ENABLE)) { +#ifndef TWDEBUG + if(pSiS->CRT1off) usScratchCR33 &= 0xf0; +#endif + } +#ifdef SISDUALHEAD + } +#endif + outSISIDXREG(SISCR, 0x33, usScratchCR33); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "After: CR30=0x%02x, CR31=0x%02x, CR33=0x%02x\n", + usScratchCR30, usScratchCR31, usScratchCR33); + + /* Enable TurboQueue */ + SiSEnableTurboQueue(pScrn); + + if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { + /* Switch on CRT1 for modes that require the bridge in SlaveMode */ + inSISIDXREG(SISCR, 0x17, usScratchCR17); + if(!(usScratchCR17 & 0x80)) { + orSISIDXREG(SISCR, 0x17, 0x80); + outSISIDXREG(SISSR, 0x00, 0x01); + usleep(10000); + outSISIDXREG(SISSR, 0x00, 0x03); + } + } + +} + +/* Functions for adjusting various TV settings */ + +/* These are used by the PostSetMode() functions as well as + * the (hopefully) upcoming display properties extension/tool. + * + * There is each a Set and a Get routine. The Set functions + * take a value of the same range as the corresponding option. + * The Get routines return a value of the same range (although + * not necessarily the same value as previously set because + * of the lower resolution of the respective setting compared + * to the valid range). + * The Get routines return -2 on error (eg. hardware does not + * support this setting). + * Note: The x and y positioning routines accept a position + * RELATIVE to the default position. All other routines + * take ABSOLUTE values. + * + * The Set functions will store the property regardless if TV is + * currently used or not and if the hardware supports the property + * or not. The Get routines will return this stored + * value if TV is not currently used (because the register does + * not contain the correct value then) or if the hardware supports + * the respective property. This should make it easier for the + * display property tool because it does not have to know the + * hardware features. + * + * All the routines are dual head aware. It does not matter + * if the function is called from the CRT1 or CRT2 session. + * The values will be stored in pSiSEnt if we're running dual. + */ + +void SiS_SetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + pSiS->chtvlumabandwidthcvbs = val; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->chtvlumabandwidthcvbs = val; +#endif + + if(!(pSiS->VBFlags & CRT2_TV)) return; + if(!(pSiS->VBFlags & VB_CHRONTEL)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + val /= 8; + if((val == 0) || (val == 1)) { + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 8) | 0x03),0xFE); + } + break; + case CHRONTEL_701x: + val /= 4; + if((val >= 0) && (val <= 3)) { + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 8) | 0x02),0xFC); + } + break; + } +} + +int SiS_GetCHTVlumabandwidthcvbs(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + if(!(pSiS->VBFlags & VB_CHRONTEL && pSiS->VBFlags & CRT2_TV)) { +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) + return (int)pSiSEnt->chtvlumabandwidthcvbs; + else +#endif + return (int)pSiS->chtvlumabandwidthcvbs; + } else { +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + return(int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x01) * 8); + case CHRONTEL_701x: + return(int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x03) * 4); + default: + return -2; + } + } +} + +void SiS_SetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + pSiS->chtvlumabandwidthsvideo = val; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->chtvlumabandwidthsvideo = val; +#endif + + if(!(pSiS->VBFlags & CRT2_TV)) return; + if(!(pSiS->VBFlags & VB_CHRONTEL)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + val /= 6; + if((val >= 0) && (val <= 2)) { + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 9) | 0x03),0xF9); + } + break; + case CHRONTEL_701x: + val /= 4; + if((val >= 0) && (val <= 3)) { + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 10) | 0x02),0xF3); + } + break; + } +} + +int SiS_GetCHTVlumabandwidthsvideo(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + if(!(pSiS->VBFlags & VB_CHRONTEL && pSiS->VBFlags & CRT2_TV)) { +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) + return (int)pSiSEnt->chtvlumabandwidthsvideo; + else +#endif + return (int)pSiS->chtvlumabandwidthsvideo; + } else { +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + return(int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x06) >> 1) * 6); + case CHRONTEL_701x: + return(int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x0c) >> 2) * 4); + default: + return -2; + } + } +} + +void SiS_SetCHTVlumaflickerfilter(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + pSiS->chtvlumaflickerfilter = val; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->chtvlumaflickerfilter = val; +#endif + + if(!(pSiS->VBFlags & CRT2_TV)) return; + if(!(pSiS->VBFlags & VB_CHRONTEL)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + val /= 6; + if((val >= 0) && (val <= 2)) { + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 10) | 0x01),0xF3); + } + break; + case CHRONTEL_701x: + val /= 4; + if((val >= 0) && (val <= 3)) { + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 10) | 0x01),0xF3); + } + break; + } +} + +int SiS_GetCHTVlumaflickerfilter(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + if(!(pSiS->VBFlags & VB_CHRONTEL && pSiS->VBFlags & CRT2_TV)) { +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) + return (int)pSiSEnt->chtvlumaflickerfilter; + else +#endif + return (int)pSiS->chtvlumaflickerfilter; + } else { +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + return(int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 6); + case CHRONTEL_701x: + return(int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x0c) >> 2) * 4); + default: + return -2; + } + } +} + +void SiS_SetCHTVchromabandwidth(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + pSiS->chtvchromabandwidth = val; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->chtvchromabandwidth = val; +#endif + + if(!(pSiS->VBFlags & CRT2_TV)) return; + if(!(pSiS->VBFlags & VB_CHRONTEL)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + val /= 4; + if((val >= 0) && (val <= 3)) { + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 12) | 0x03),0xCF); + } + break; + case CHRONTEL_701x: + val /= 8; + if((val >= 0) && (val <= 1)) { + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 12) | 0x02),0xEF); + } + break; + } +} + +int SiS_GetCHTVchromabandwidth(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + if(!(pSiS->VBFlags & VB_CHRONTEL && pSiS->VBFlags & CRT2_TV)) { +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) + return (int)pSiSEnt->chtvchromabandwidth; + else +#endif + return (int)pSiS->chtvchromabandwidth; + } else { +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + return(int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x30) >> 4) * 4); + case CHRONTEL_701x: + return(int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x10) >> 4) * 8); + default: + return -2; + } + } +} + +void SiS_SetCHTVchromaflickerfilter(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + pSiS->chtvchromaflickerfilter = val; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->chtvchromaflickerfilter = val; +#endif + + if(!(pSiS->VBFlags & CRT2_TV)) return; + if(!(pSiS->VBFlags & VB_CHRONTEL)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + val /= 6; + if((val >= 0) && (val <= 2)) { + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 12) | 0x01),0xCF); + } + break; + case CHRONTEL_701x: + val /= 4; + if((val >= 0) && (val <= 3)) { + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 12) | 0x01),0xCF); + } + break; + } +} + +int SiS_GetCHTVchromaflickerfilter(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + if(!(pSiS->VBFlags & VB_CHRONTEL && pSiS->VBFlags & CRT2_TV)) { +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) + return (int)pSiSEnt->chtvchromaflickerfilter; + else +#endif + return (int)pSiS->chtvchromaflickerfilter; + } else { +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + return(int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 6); + case CHRONTEL_701x: + return(int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x30) >> 4) * 4); + default: + return -2; + } + } +} + +void SiS_SetCHTVcvbscolor(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + pSiS->chtvcvbscolor = val ? 1 : 0; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->chtvcvbscolor = pSiS->chtvcvbscolor; +#endif + + if(!(pSiS->VBFlags & CRT2_TV)) return; + if(!(pSiS->VBFlags & VB_CHRONTEL)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x4003,0x00); + else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x0003,~0x40); + break; + case CHRONTEL_701x: + if(!val) SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x0002,~0x20); + else SiS_SetCH70xxANDOR(pSiS->SiS_Pr, 0x2002,0x00); + break; + } +} + +int SiS_GetCHTVcvbscolor(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + if(!(pSiS->VBFlags & VB_CHRONTEL && pSiS->VBFlags & CRT2_TV)) { +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) + return (int)pSiSEnt->chtvcvbscolor; + else +#endif + return (int)pSiS->chtvcvbscolor; + } else { +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + return(int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x40) >> 6) ^ 0x01); + case CHRONTEL_701x: + return(int)(((SiS_GetCH70xx(pSiS->SiS_Pr, 0x02) & 0x20) >> 5) ^ 0x01); + default: + return -2; + } + } +} + +void SiS_SetCHTVtextenhance(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + pSiS->chtvtextenhance = val; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->chtvtextenhance = val; +#endif + + if(!(pSiS->VBFlags & CRT2_TV)) return; + if(!(pSiS->VBFlags & VB_CHRONTEL)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + val /= 6; + if((val >= 0) && (val <= 2)) { + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 8) | 0x01),0xFC); + } + break; + case CHRONTEL_701x: + val /= 2; + if((val >= 0) && (val <= 7)) { + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 8) | 0x03),0xF8); + } + break; + } +} + +int SiS_GetCHTVtextenhance(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + if(!(pSiS->VBFlags & VB_CHRONTEL && pSiS->VBFlags & CRT2_TV)) { +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) + return (int)pSiSEnt->chtvtextenhance; + else +#endif + return (int)pSiS->chtvtextenhance; + } else { +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + return(int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x01) & 0x03) * 6); + case CHRONTEL_701x: + return(int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x03) & 0x07) * 2); + default: + return -2; + } + } +} + +void SiS_SetCHTVcontrast(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + pSiS->chtvcontrast = val; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->chtvcontrast = val; +#endif + + if(!(pSiS->VBFlags & CRT2_TV)) return; + if(!(pSiS->VBFlags & VB_CHRONTEL)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + val /= 2; + if((val >= 0) && (val <= 7)) { + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 8) | 0x11),0xF8); + break; + case CHRONTEL_701x: + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((val << 8) | 0x08),0xF8); + break; + } + } +} + +int SiS_GetCHTVcontrast(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + if(!(pSiS->VBFlags & VB_CHRONTEL && pSiS->VBFlags & CRT2_TV)) { +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) + return (int)pSiSEnt->chtvcontrast; + else +#endif + return (int)pSiS->chtvcontrast; + } else { +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + return(int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x11) & 0x07) * 2); + case CHRONTEL_701x: + return(int)((SiS_GetCH70xx(pSiS->SiS_Pr, 0x08) & 0x07) * 2); + default: + return -2; + } + } +} + +void SiS_SetSISTVedgeenhance(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + pSiS->sistvedgeenhance = val; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->sistvedgeenhance = val; +#endif + + if(!(pSiS->VBFlags & CRT2_TV)) return; + if(!(pSiS->VBFlags & VB_301)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + val /= 2; + if((val >= 0) && (val <= 7)) { + setSISIDXREG(SISPART2,0x3A, 0x1F, (val << 5)); + } +} + +int SiS_GetSISTVedgeenhance(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + if(!(pSiS->VBFlags & VB_301 && pSiS->VBFlags & CRT2_TV)) { +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) + return (int)pSiSEnt->sistvedgeenhance; + else +#endif + return (int)pSiS->sistvedgeenhance; + } else { + unsigned char temp; +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + inSISIDXREG(SISPART2, 0x3a, temp); + return(int)(((temp & 0xe0) >> 5) * 2); + } +} + +void SiS_SetSISTVantiflicker(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + pSiS->sistvantiflicker = val; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->sistvantiflicker = val; +#endif + + if(!(pSiS->VBFlags & CRT2_TV)) return; + if(!(pSiS->VBFlags & VB_SISBRIDGE)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + val /= 2; + if((val >= 0) && (val <= 7)) { + setSISIDXREG(SISPART2,0x0A,0x8F, (val << 4)); + } +} + +int SiS_GetSISTVantiflicker(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + if(!(pSiS->VBFlags & VB_SISBRIDGE && pSiS->VBFlags & CRT2_TV)) { +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) + return (int)pSiSEnt->sistvantiflicker; + else +#endif + return (int)pSiS->sistvantiflicker; + } else { + unsigned char temp; +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + inSISIDXREG(SISPART2, 0x0a, temp); + return(int)(((temp & 0x70) >> 4) * 2); + } +} + +void SiS_SetSISTVsaturation(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + pSiS->sistvsaturation = val; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->sistvsaturation = val; +#endif + + if(!(pSiS->VBFlags & CRT2_TV)) return; + if(!(pSiS->VBFlags & VB_SISBRIDGE)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + val /= 2; + if((val >= 0) && (val <= 7)) { + setSISIDXREG(SISPART4,0x21,0xF8, val); + } +} + +int SiS_GetSISTVsaturation(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + + if(!(pSiS->VBFlags & VB_SISBRIDGE && pSiS->VBFlags & CRT2_TV)) { +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) + return (int)pSiSEnt->sistvsaturation; + else +#endif + return (int)pSiS->sistvsaturation; + } else { + unsigned char temp; +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + inSISIDXREG(SISPART4, 0x21, temp); + return(int)((temp & 0x07) * 2); + } +} + +void SiS_SetSIS6326TVantiflicker(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char tmp; + + pSiS->sis6326antiflicker = val; + + if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + tmp = SiS6326GetTVReg(pScrn,0x00); + if(!(tmp & 0x04)) return; + + /* Valid values: 0=off, 1=low, 2=med, 3=high, 4=adaptive */ + if(val >= 0 && val <= 4) { + tmp &= 0x1f; + tmp |= (val << 5); + SiS6326SetTVReg(pScrn,0x00,tmp); + } +} + +int SiS_GetSIS6326TVantiflicker(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char tmp; + + if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { + return (int)pSiS->sis6326antiflicker; + } + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + tmp = SiS6326GetTVReg(pScrn,0x00); + if(!(tmp & 0x04)) { + return (int)pSiS->sis6326antiflicker; + } else { + return (int)((tmp >> 5) & 0x07); + } +} + +void SiS_SetSIS6326TVenableyfilter(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char tmp; + + if(val) val = 1; + pSiS->sis6326enableyfilter = val; + + if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + tmp = SiS6326GetTVReg(pScrn,0x00); + if(!(tmp & 0x04)) return; + + tmp = SiS6326GetTVReg(pScrn,0x43); + tmp &= ~0x10; + tmp |= ((val & 0x01) << 4); + SiS6326SetTVReg(pScrn,0x43,tmp); +} + +int SiS_GetSIS6326TVenableyfilter(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char tmp; + + if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { + return (int)pSiS->sis6326enableyfilter; + } + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + tmp = SiS6326GetTVReg(pScrn,0x00); + if(!(tmp & 0x04)) { + return (int)pSiS->sis6326enableyfilter; + } else { + tmp = SiS6326GetTVReg(pScrn,0x43); + return (int)((tmp >> 4) & 0x01); + } +} + +void SiS_SetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char tmp; + + if(val) val = 1; + pSiS->sis6326yfilterstrong = val; + + if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + tmp = SiS6326GetTVReg(pScrn,0x00); + if(!(tmp & 0x04)) return; + + tmp = SiS6326GetTVReg(pScrn,0x43); + if(tmp & 0x10) { + tmp &= ~0x40; + tmp |= ((val & 0x01) << 6); + SiS6326SetTVReg(pScrn,0x43,tmp); + } +} + +int SiS_GetSIS6326TVyfilterstrong(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char tmp; + + if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) { + return (int)pSiS->sis6326yfilterstrong; + } + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + tmp = SiS6326GetTVReg(pScrn,0x00); + if(!(tmp & 0x04)) { + return (int)pSiS->sis6326yfilterstrong; + } else { + tmp = SiS6326GetTVReg(pScrn,0x43); + if(!(tmp & 0x10)) { + return (int)pSiS->sis6326yfilterstrong; + } else { + return (int)((tmp >> 6) & 0x01); + } + } +} + +void SiS_SetTVxposoffset(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + pSiS->tvxpos = val; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->tvxpos = val; +#endif + + if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { + + if(pSiS->VBFlags & CRT2_TV) { + + if(pSiS->VBFlags & VB_CHRONTEL) { + + int x = pSiS->tvx; +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) x = pSiSEnt->tvx; +#endif + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + if((val >= -32) && (val <= 32)) { + x += val; + if(x < 0) x = 0; + SiS_SetCH700x(pSiS->SiS_Pr, (((x & 0xff) << 8) | 0x0a)); + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, (((x & 0x0100) << 1) | 0x08),0xFD); + } + break; + case CHRONTEL_701x: + /* TO DO */ + break; + } + + } else if(pSiS->VBFlags & VB_SISBRIDGE) { + + if((val >= -32) && (val <= 32)) { + unsigned char p2_1f,p2_2b,p2_2c,p2_2d,p2_43; + const unsigned char p2_left_ntsc[8][4] = { + { 0x48, 0x63, 0x49, 0xf4 }, + { 0x45, 0x60, 0x46, 0xf1 }, + { 0x43, 0x6e, 0x44, 0xff }, + { 0x40, 0x6b, 0x41, 0xfc }, + { 0x3e, 0x69, 0x3f, 0xfa }, + { 0x3c, 0x67, 0x3d, 0xf8 }, + { 0x39, 0x64, 0x3a, 0xf5 }, + { 0x37, 0x62, 0x38, 0xf3 } + }; + const unsigned char p2_right_ntsc[8][4] = { + { 0x4b, 0x66, 0x4c, 0xf7 }, + { 0x4c, 0x67, 0x4d, 0xf8 }, + { 0x4e, 0x69, 0x4f, 0xfa }, + { 0x4f, 0x6a, 0x50, 0xfb }, + { 0x51, 0x6c, 0x52, 0xfd }, + { 0x53, 0x6e, 0x54, 0xff }, + { 0x55, 0x60, 0x56, 0xf1 }, + { 0x56, 0x61, 0x57, 0xf2 } + }; + const unsigned char p2_left_pal[8][4] = { + { 0x5b, 0x66, 0x5c, 0x87 }, + { 0x59, 0x64, 0x5a, 0x85 }, + { 0x56, 0x61, 0x57, 0x82 }, + { 0x53, 0x6e, 0x54, 0x8f }, + { 0x50, 0x6b, 0x51, 0x8c }, + { 0x4d, 0x68, 0x4e, 0x89 }, + { 0x4a, 0x65, 0x4b, 0x86 }, + { 0x49, 0x64, 0x4a, 0x85 } + }; + const unsigned char p2_right_pal[8][4] = { + { 0x5f, 0x6a, 0x60, 0x8b }, + { 0x61, 0x6c, 0x62, 0x8d }, + { 0x63, 0x6e, 0x64, 0x8f }, + { 0x65, 0x60, 0x66, 0x81 }, + { 0x66, 0x61, 0x67, 0x82 }, + { 0x68, 0x63, 0x69, 0x84 }, + { 0x69, 0x64, 0x6a, 0x85 }, + { 0x6b, 0x66, 0x6c, 0x87 } + }; + val /= 4; + p2_2d = pSiS->p2_2d; +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) p2_2d = pSiSEnt->p2_2d; +#endif + p2_2d &= 0xf0; + if(val < 0) { + val = -val; + if(val == 8) val = 7; + if(pSiS->VBFlags & TV_PAL) { + p2_1f = p2_left_pal[val][0]; + p2_2b = p2_left_pal[val][1]; + p2_2c = p2_left_pal[val][2]; + p2_2d |= (p2_left_pal[val][3] & 0x0f); + } else { + p2_1f = p2_left_ntsc[val][0]; + p2_2b = p2_left_ntsc[val][1]; + p2_2c = p2_left_ntsc[val][2]; + p2_2d |= (p2_left_ntsc[val][3] & 0x0f); + } + } else { + if(val == 8) val = 7; + if(pSiS->VBFlags & TV_PAL) { + p2_1f = p2_right_pal[val][0]; + p2_2b = p2_right_pal[val][1]; + p2_2c = p2_right_pal[val][2]; + p2_2d |= (p2_right_pal[val][3] & 0x0f); + } else { + p2_1f = p2_right_ntsc[val][0]; + p2_2b = p2_right_ntsc[val][1]; + p2_2c = p2_right_ntsc[val][2]; + p2_2d |= (p2_right_ntsc[val][3] & 0x0f); + } + } + p2_43 = p2_1f + 3; + SISWaitRetraceCRT2(pScrn); + outSISIDXREG(SISPART2,0x1f,p2_1f); + outSISIDXREG(SISPART2,0x2b,p2_2b); + outSISIDXREG(SISPART2,0x2c,p2_2c); + outSISIDXREG(SISPART2,0x2d,p2_2d); + outSISIDXREG(SISPART2,0x43,p2_43); + } + } + } + + } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { + + if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { + + unsigned char tmp; + unsigned short temp1, temp2, temp3; + + tmp = SiS6326GetTVReg(pScrn,0x00); + if(tmp & 0x04) { + + temp1 = pSiS->tvx1; + temp2 = pSiS->tvx2; + temp3 = pSiS->tvx3; + if((val >= -16) && (val <= 16)) { + if(val > 0) { + temp1 += (val * 4); + temp2 += (val * 4); + while((temp1 > 0x0fff) || (temp2 > 0x0fff)) { + temp1 -= 4; + temp2 -= 4; + } + } else { + val = -val; + temp3 += (val * 4); + while(temp3 > 0x03ff) { + temp3 -= 4; + } + } + } + SiS6326SetTVReg(pScrn,0x3a,(temp1 & 0xff)); + tmp = SiS6326GetTVReg(pScrn,0x3c); + tmp &= 0xf0; + tmp |= ((temp1 & 0x0f00) >> 8); + SiS6326SetTVReg(pScrn,0x3c,tmp); + SiS6326SetTVReg(pScrn,0x26,(temp2 & 0xff)); + tmp = SiS6326GetTVReg(pScrn,0x27); + tmp &= 0x0f; + tmp |= ((temp2 & 0x0f00) >> 4); + SiS6326SetTVReg(pScrn,0x27,tmp); + SiS6326SetTVReg(pScrn,0x12,(temp3 & 0xff)); + tmp = SiS6326GetTVReg(pScrn,0x13); + tmp &= ~0xC0; + tmp |= ((temp3 & 0x0300) >> 2); + SiS6326SetTVReg(pScrn,0x13,tmp); + } + } + } +} + +int SiS_GetTVxposoffset(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; + + if(pSiSEnt && pSiS->DualHeadMode) + return (int)pSiSEnt->tvxpos; + else +#endif + return (int)pSiS->tvxpos; +} + +void SiS_SetTVyposoffset(ScrnInfoPtr pScrn, int val) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + pSiS->tvypos = val; +#ifdef SISDUALHEAD + if(pSiSEnt) pSiSEnt->tvypos = val; +#endif + + if(pSiS->VGAEngine == SIS_300_VGA || pSiS->VGAEngine == SIS_315_VGA) { + + if(pSiS->VBFlags & CRT2_TV) { + + if(pSiS->VBFlags & VB_CHRONTEL) { + + int y = pSiS->tvy; +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) y = pSiSEnt->tvy; +#endif + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + if((val >= -32) && (val <= 32)) { + y -= val; + if(y < 0) y = 0; + SiS_SetCH700x(pSiS->SiS_Pr, (((y & 0xff) << 8) | 0x0b)); + SiS_SetCH70xxANDOR(pSiS->SiS_Pr, ((y & 0x0100) | 0x08),0xFE); + } + break; + case CHRONTEL_701x: + /* TO DO */ + break; + } + + } else if(pSiS->VBFlags & VB_SISBRIDGE) { + + if((val >= -32) && (val <= 32)) { + char p2_01, p2_02; + val /= 4; + p2_01 = pSiS->p2_01; + p2_02 = pSiS->p2_02; +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) { + p2_01 = pSiSEnt->p2_01; + p2_02 = pSiSEnt->p2_02; + } +#endif + p2_01 += (val * 2); + p2_02 += (val * 2); + while((p2_01 <= 0) || (p2_02 <= 0)) { + p2_01 += 2; + p2_02 += 2; + } + SISWaitRetraceCRT2(pScrn); + outSISIDXREG(SISPART2,0x01,p2_01); + outSISIDXREG(SISPART2,0x02,p2_02); + } + } + + } + + } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { + + if(pSiS->SiS6326Flags & SIS6326_TVDETECTED) { + + unsigned char tmp; + int temp1, limit; + + tmp = SiS6326GetTVReg(pScrn,0x00); + if(tmp & 0x04) { + + if((val >= -16) && (val <= 16)) { + temp1 = (unsigned short)pSiS->tvy1; + limit = (pSiS->SiS6326Flags & SIS6326_TVPAL) ? 625 : 525; + if(val > 0) { + temp1 += (val * 4); + if(temp1 > limit) temp1 -= limit; + } else { + val = -val; + temp1 -= (val * 2); + if(temp1 <= 0) temp1 += (limit -1); + } + SiS6326SetTVReg(pScrn,0x11,(temp1 & 0xff)); + tmp = SiS6326GetTVReg(pScrn,0x13); + tmp &= ~0x30; + tmp |= ((temp1 & 0x300) >> 4); + SiS6326SetTVReg(pScrn,0x13,tmp); + if(temp1 == 1) tmp = 0x10; + else { + if(pSiS->SiS6326Flags & SIS6326_TVPAL) { + if((temp1 <= 3) || (temp1 >= (limit - 2))) tmp = 0x08; + else if(temp1 < 22) tmp = 0x02; + else tmp = 0x04; + } else { + if((temp1 <= 5) || (temp1 >= (limit - 4))) tmp = 0x08; + else if(temp1 < 19) tmp = 0x02; + else tmp = 0x04; + } + } + SiS6326SetTVReg(pScrn,0x21,tmp); + } + } + } + } +} + +int SiS_GetTVyposoffset(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; + + if(pSiSEnt && pSiS->DualHeadMode) + return (int)pSiSEnt->tvypos; + else +#endif + return (int)pSiS->tvypos; +} + +/* TW: Disable CRT1 for saving bandwidth. This doesn't work with VESA; + * VESA uses the bridge in SlaveMode and switching CRT1 off while the + * bridge is in SlaveMode not that clever... + */ +void SiSPostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); +#ifdef SISDUALHEAD + SISEntPtr pSiSEnt = pSiS->entityPrivate; +#endif + unsigned char usScratchCR17; + Bool flag = FALSE; + Bool doit = TRUE; + int temp; + +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "CRT1off is %d\n", pSiS->CRT1off); +#endif + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE)) { + + if(pSiS->VBFlags != pSiS->VBFlags_backup) { + pSiS->VBFlags = pSiS->VBFlags_backup; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "VBFlags restored to %0lx\n", pSiS->VBFlags); + } + + /* TW: -) We can't switch off CRT1 if bridge is in SlaveMode. + * -) If we change to a SlaveMode-Mode (like 512x384), we + * need to adapt VBFlags for eg. Xv. + */ +#ifdef SISDUALHEAD + if(!pSiS->DualHeadMode) { +#endif + if(SiSBridgeIsInSlaveMode(pScrn)) { + doit = FALSE; + temp = pSiS->VBFlags; + pSiS->VBFlags &= (~VB_DISPMODE_SINGLE); + pSiS->VBFlags |= (VB_DISPMODE_MIRROR | DISPTYPE_DISP1); + if(temp != pSiS->VBFlags) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "VBFlags changed to 0x%0lx\n", pSiS->VBFlags); + } + } +#ifdef SISDUALHEAD + } +#endif + if(doit) { + inSISIDXREG(SISCR, 0x17, usScratchCR17); + if(pSiS->CRT1off) { + if(usScratchCR17 & 0x80) flag = TRUE; + usScratchCR17 &= ~0x80; + } else { + if(!(usScratchCR17 & 0x80)) flag = TRUE; + usScratchCR17 |= 0x80; + } + outSISIDXREG(SISCR, 0x17, usScratchCR17); + /* TW: Reset only if status changed */ + if(flag) { + outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ + usleep(10000); + outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ + } + } + } + + /* TW: Apply TV settings given by options + Do this even in DualHeadMode: + - if this is called by SetModeCRT1, CRT2 mode has been reset by SetModeCRT1 + - if this is called by SetModeCRT2, CRT2 mode has changed (duh!) + -> In both cases, the settings must be re-applied. + */ + if(pSiS->VBFlags & CRT2_TV) { + int val; + if(pSiS->VBFlags & VB_CHRONTEL) { + int mychtvlumabandwidthcvbs = pSiS->chtvlumabandwidthcvbs; + int mychtvlumabandwidthsvideo = pSiS->chtvlumabandwidthsvideo; + int mychtvlumaflickerfilter = pSiS->chtvlumaflickerfilter; + int mychtvchromabandwidth = pSiS->chtvchromabandwidth; + int mychtvchromaflickerfilter = pSiS->chtvchromaflickerfilter; + int mychtvcvbscolor = pSiS->chtvcvbscolor; + int mychtvtextenhance = pSiS->chtvtextenhance; + int mychtvcontrast = pSiS->chtvcontrast; + int mytvxpos = pSiS->tvxpos; + int mytvypos = pSiS->tvypos; +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) { + mychtvlumabandwidthcvbs = pSiSEnt->chtvlumabandwidthcvbs; + mychtvlumabandwidthsvideo = pSiSEnt->chtvlumabandwidthsvideo; + mychtvlumaflickerfilter = pSiSEnt->chtvlumaflickerfilter; + mychtvchromabandwidth = pSiSEnt->chtvchromabandwidth; + mychtvchromaflickerfilter = pSiSEnt->chtvchromaflickerfilter; + mychtvcvbscolor = pSiSEnt->chtvcvbscolor; + mychtvtextenhance = pSiSEnt->chtvtextenhance; + mychtvcontrast = pSiSEnt->chtvcontrast; + mytvxpos = pSiSEnt->tvxpos; + mytvypos = pSiSEnt->tvypos; + } +#endif + if((val = mychtvlumabandwidthcvbs) != -1) { + SiS_SetCHTVlumabandwidthcvbs(pScrn, val); + } + if((val = mychtvlumabandwidthsvideo) != -1) { + SiS_SetCHTVlumabandwidthsvideo(pScrn, val); + } + if((val = mychtvlumaflickerfilter) != -1) { + SiS_SetCHTVlumaflickerfilter(pScrn, val); + } + if((val = mychtvchromabandwidth) != -1) { + SiS_SetCHTVchromabandwidth(pScrn, val); + } + if((val = mychtvchromaflickerfilter) != -1) { + SiS_SetCHTVchromaflickerfilter(pScrn, val); + } + if((val = mychtvcvbscolor) != -1) { + SiS_SetCHTVcvbscolor(pScrn, val); + } + if((val = mychtvtextenhance) != -1) { + SiS_SetCHTVtextenhance(pScrn, val); + } + if((val = mychtvcontrast) != -1) { + SiS_SetCHTVcontrast(pScrn, val); + } + /* Backup default TV position registers */ + switch(pSiS->ChrontelType) { + case CHRONTEL_700x: + pSiS->tvx = SiS_GetCH700x(pSiS->SiS_Pr, 0x0a); + pSiS->tvx |= (((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x02) >> 1) << 8); + pSiS->tvy = SiS_GetCH700x(pSiS->SiS_Pr, 0x0b); + pSiS->tvy |= ((SiS_GetCH700x(pSiS->SiS_Pr, 0x08) & 0x01) << 8); +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) { + pSiSEnt->tvx = pSiS->tvx; + pSiSEnt->tvy = pSiS->tvy; + } +#endif + break; + case CHRONTEL_701x: + /* TO DO */ + break; + } + if((val = mytvxpos) != 0) { + SiS_SetTVxposoffset(pScrn, val); + } + if((val = mytvypos) != 0) { + SiS_SetTVyposoffset(pScrn, val); + } + } + if(pSiS->VBFlags & VB_301) { + int mysistvedgeenhance = pSiS->sistvedgeenhance; +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) { + mysistvedgeenhance = pSiSEnt->sistvedgeenhance; + } +#endif + if((val = mysistvedgeenhance) != -1) { + SiS_SetSISTVedgeenhance(pScrn, val); + } + } + if(pSiS->VBFlags & VB_SISBRIDGE) { + int mysistvantiflicker = pSiS->sistvantiflicker; + int mysistvsaturation = pSiS->sistvsaturation; + int mytvxpos = pSiS->tvxpos; + int mytvypos = pSiS->tvypos; +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) { + mysistvantiflicker = pSiSEnt->sistvantiflicker; + mysistvsaturation = pSiSEnt->sistvsaturation; + mytvxpos = pSiSEnt->tvxpos; + mytvypos = pSiSEnt->tvypos; + } +#endif + /* Backup default TV position registers */ + inSISIDXREG(SISPART2,0x2d,pSiS->p2_2d); + inSISIDXREG(SISPART2,0x01,pSiS->p2_01); + inSISIDXREG(SISPART2,0x02,pSiS->p2_02); +#ifdef SISDUALHEAD + if(pSiSEnt && pSiS->DualHeadMode) { + pSiSEnt->p2_2d = pSiS->p2_2d; + pSiSEnt->p2_01 = pSiS->p2_01; + pSiSEnt->p2_02 = pSiS->p2_02; + } +#endif + if((val = mysistvantiflicker) != -1) { + SiS_SetSISTVantiflicker(pScrn, val); + } + if((val = mysistvsaturation) != -1) { + SiS_SetSISTVsaturation(pScrn, val); + } + if((val = mytvxpos) != 0) { + SiS_SetTVxposoffset(pScrn, val); + } + if((val = mytvypos) != 0) { + SiS_SetTVyposoffset(pScrn, val); + } + } + } + +} + +/* Post-set SiS6326 TV registers */ +void SiS6326PostSetMode(ScrnInfoPtr pScrn, SISRegPtr sisReg) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char tmp; + int val; + + if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return; + +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + + /* Backup default TV position registers */ + pSiS->tvx1 = SiS6326GetTVReg(pScrn,0x3a); + pSiS->tvx1 |= ((SiS6326GetTVReg(pScrn,0x3c) & 0x0f) << 8); + pSiS->tvx2 = SiS6326GetTVReg(pScrn,0x26); + pSiS->tvx2 |= ((SiS6326GetTVReg(pScrn,0x27) & 0xf0) << 4); + pSiS->tvx3 = SiS6326GetTVReg(pScrn,0x12); + pSiS->tvx3 |= ((SiS6326GetTVReg(pScrn,0x13) & 0xC0) << 2); + pSiS->tvy1 = SiS6326GetTVReg(pScrn,0x11); + pSiS->tvy1 |= ((SiS6326GetTVReg(pScrn,0x13) & 0x30) << 4); + + /* TW: Handle TVPosOffset options (BEFORE switching on TV) */ + if((val = pSiS->tvxpos) != 0) { + SiS_SetTVxposoffset(pScrn, val); + } + if((val = pSiS->tvypos) != 0) { + SiS_SetTVyposoffset(pScrn, val); + } + + /* TW: Switch on TV output. This is rather complicated, but + * if we don't do it, TV output will flicker terribly. + */ + if(pSiS->SiS6326Flags & SIS6326_TVON) { + orSISIDXREG(SISSR, 0x01, 0x20); + tmp = SiS6326GetTVReg(pScrn,0x00); + tmp &= ~0x04; + while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ + SiS6326SetTVReg(pScrn,0x00,tmp); + for(val=0; val < 2; val++) { + while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ + while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ + } + SiS6326SetTVReg(pScrn, 0x00, sisReg->sis6326tv[0]); + tmp = inSISREG(SISINPSTAT); + outSISREG(SISAR, 0x20); + tmp = inSISREG(SISINPSTAT); + while(inSISREG(SISINPSTAT) & 0x01); + while(!(inSISREG(SISINPSTAT) & 0x01)); + andSISIDXREG(SISSR, 0x01, ~0x20); + for(val=0; val < 10; val++) { + while(!(inSISREG(SISINPSTAT) & 0x08)); /* Wait while NOT vb */ + while(inSISREG(SISINPSTAT) & 0x08); /* wait while vb */ + } + andSISIDXREG(SISSR, 0x01, ~0x20); + } + + tmp = SiS6326GetTVReg(pScrn,0x00); + if(!(tmp & 0x04)) return; + + /* TW: Apply TV settings given by options */ + if((val = pSiS->sis6326antiflicker) != -1) { + SiS_SetSIS6326TVantiflicker(pScrn, val); + } + if((val = pSiS->sis6326enableyfilter) != -1) { + SiS_SetSIS6326TVenableyfilter(pScrn, val); + } + if((val = pSiS->sis6326yfilterstrong) != -1) { + SiS_SetSIS6326TVyfilterstrong(pScrn, val); + } + +} + +/* Check if video bridge is in slave mode */ +BOOLEAN +SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char usScratchP1_00; + + if(!(pSiS->VBFlags & VB_VIDEOBRIDGE)) return FALSE; + + inSISIDXREG(SISPART1,0x00,usScratchP1_00); + if( ((pSiS->VGAEngine == SIS_300_VGA) && (usScratchP1_00 & 0xa0) == 0x20) || + ((pSiS->VGAEngine == SIS_315_VGA) && (usScratchP1_00 & 0x50) == 0x10) ) { + return TRUE; + } else { + return FALSE; + } +} + +/* TW: Build a list of the VESA modes the BIOS reports as valid */ +static void +SiSBuildVesaModeList(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe) +{ + SISPtr pSiS = SISPTR(pScrn); + int i = 0; + + while(vbe->VideoModePtr[i] != 0xffff) { + sisModeInfoPtr m; + VbeModeInfoBlock *mode; + int id = vbe->VideoModePtr[i++]; + int bpp; + + if ((mode = VBEGetModeInfo(pVbe, id)) == NULL) + continue; + + bpp = mode->BitsPerPixel; + + m = xnfcalloc(sizeof(sisModeInfoRec),1); + m->width = mode->XResolution; + m->height = mode->YResolution; + m->bpp = bpp; + m->n = id; + m->next = pSiS->SISVESAModeList; + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "BIOS reported VESA mode 0x%x: x:%i y:%i bpp:%i\n", + m->n, m->width, m->height, m->bpp); + + pSiS->SISVESAModeList = m; + + VBEFreeModeInfo(mode); + } +} + +/* TW: Calc VESA mode from given resolution/depth */ +static UShort +SiSCalcVESAModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + SISPtr pSiS = SISPTR(pScrn); + sisModeInfoPtr m = pSiS->SISVESAModeList; + UShort i = (pScrn->bitsPerPixel+7)/8 - 1; + UShort ModeIndex = 0; + + while(m) { + if(pScrn->bitsPerPixel == m->bpp && + mode->HDisplay == m->width && + mode->VDisplay == m->height) + return m->n; + m = m->next; + } + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "No valid BIOS VESA mode found for %dx%dx%d; searching built-in table.\n", + mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); + + switch(mode->HDisplay) { + case 512: + if(mode->VDisplay == 384) + ModeIndex = VESAModeIndex_512x384[i]; + break; + case 640: + if(mode->VDisplay == 480) + ModeIndex = VESAModeIndex_640x480[i]; + break; + case 800: + if(mode->VDisplay == 600) + ModeIndex = VESAModeIndex_800x600[i]; + break; + case 1024: + if(mode->VDisplay == 768) + ModeIndex = VESAModeIndex_1024x768[i]; + break; + case 1280: + if(mode->VDisplay == 1024) + ModeIndex = VESAModeIndex_1280x1024[i]; + break; + case 1600: + if(mode->VDisplay == 1200) + ModeIndex = VESAModeIndex_1600x1200[i]; + break; + case 1920: + if(mode->VDisplay == 1440) + ModeIndex = VESAModeIndex_1920x1440[i]; + break; + } + + if(!ModeIndex) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "No valid mode found for %dx%dx%d in built-in table either.\n", + mode->HDisplay, mode->VDisplay, pScrn->bitsPerPixel); + + return(ModeIndex); +} + +/* TW: Calculate the vertical refresh rate from a mode */ +int +SiSCalcVRate(DisplayModePtr mode) +{ + float hsync, refresh = 0; + + if(mode->HSync > 0.0) + hsync = mode->HSync; + else if(mode->HTotal > 0) + hsync = (float)mode->Clock / (float)mode->HTotal; + else + hsync = 0.0; + + if(mode->VTotal > 0) + refresh = hsync * 1000.0 / mode->VTotal; + + if(mode->Flags & V_INTERLACE) + refresh *= 2.0; + + if(mode->Flags & V_DBLSCAN) + refresh /= 2.0; + + if(mode->VScan > 1) + refresh /= mode->VScan; + + if(mode->VRefresh > 0.0) + refresh = mode->VRefresh; + + if(hsync == 0 || refresh == 0) return(0); + + return((int)(refresh)); +} + +/* TW: Calculate CR33 (rate index) for CRT1. + * Calculation is done using currentmode, therefore it is + * recommended to set VertRefresh and HorizSync to correct + * values in config file. + */ +unsigned char +SISSearchCRT1Rate(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + SISPtr pSiS = SISPTR(pScrn); + int i = 0; + int irefresh; + unsigned short xres = mode->HDisplay; + unsigned short yres = mode->VDisplay; + unsigned char index; + BOOLEAN checksis730 = FALSE; + + irefresh = SiSCalcVRate(mode); + if(!irefresh) { + if(xres == 800 || xres == 1024 || xres == 1280) return 0x02; + else return 0x01; + } + + /* SiS730 has troubles on CRT2 if CRT1 is at 32bpp */ + if( (pSiS->sishw_ext.jChipType == SIS_730) && + (pSiS->VBFlags & VB_VIDEOBRIDGE) && + (pSiS->CurrentLayout.bitsPerPixel == 32) ) { +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(pSiS->SecondHead) { + checksis730 = TRUE; + } + } else +#endif + if((!pSiS->UseVESA) && (pSiS->VBFlags & CRT2_ENABLE) && (!pSiS->CRT1off)) { + checksis730 = TRUE; + } + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "Debug: CalcVRate returned %d\n", irefresh); +#endif + + /* We need the REAL refresh rate here */ + if(mode->Flags & V_INTERLACE) + irefresh /= 2; + + /* Do not multiply by 2 when DBLSCAN! */ + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "Debug: Rate after correction = %d\n", irefresh); +#endif + + index = 0; + while((sisx_vrate[i].idx != 0) && (sisx_vrate[i].xres <= xres)) { + if((sisx_vrate[i].xres == xres) && (sisx_vrate[i].yres == yres)) { + if((checksis730 == FALSE) || (sisx_vrate[i].SiS730valid32bpp == TRUE)) { + if(sisx_vrate[i].refresh == irefresh) { + index = sisx_vrate[i].idx; + break; + } else if(sisx_vrate[i].refresh > irefresh) { + if((sisx_vrate[i].refresh - irefresh) <= 3) { + index = sisx_vrate[i].idx; + } else if( ((checksis730 == FALSE) || (sisx_vrate[i - 1].SiS730valid32bpp == TRUE)) && + ((irefresh - sisx_vrate[i - 1].refresh) <= 2) && + (sisx_vrate[i].idx != 1) ) { + index = sisx_vrate[i - 1].idx; + } + break; + } + } + } + i++; + } + if(index > 0) + return index; + else { + /* TW: Default Rate index */ + if(xres == 800 || xres == 1024 || xres == 1280) return 0x02; + else return 0x01; + } +} + +void +SISWaitRetraceCRT1(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + int watchdog; + unsigned char temp; + + inSISIDXREG(SISCR,0x17,temp); + if(!(temp & 0x80)) return; + + watchdog = 65536; + while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); + watchdog = 65536; + while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); +} + +void +SISWaitRetraceCRT2(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + int watchdog; + unsigned char temp, reg; + + switch(pSiS->VGAEngine) { + case SIS_300_VGA: + reg = 0x28; + break; + case SIS_315_VGA: + reg = 0x33; + break; + default: + return; + } + + watchdog = 65536; + do { + inSISIDXREG(SISPART1, reg, temp); + if(temp & 0x80) break; + } while(--watchdog); + watchdog = 65536; + do { + inSISIDXREG(SISPART1, reg, temp); + if(!(temp & 0x80)) break; + } while(--watchdog); +} + +static void +SISWaitVBRetrace(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + if(pSiS->SecondHead) + SISWaitRetraceCRT1(pScrn); + else + SISWaitRetraceCRT2(pScrn); + } else { +#endif + if(pSiS->VBFlags & DISPTYPE_DISP1) { + SISWaitRetraceCRT1(pScrn); + } + if(pSiS->VBFlags & DISPTYPE_DISP2) { + if(!(SiSBridgeIsInSlaveMode(pScrn))) { + SISWaitRetraceCRT2(pScrn); + } + } +#ifdef SISDUALHEAD + } +#endif +} + +void +sisSaveUnlockExtRegisterLock(SISPtr pSiS, unsigned char *reg1, unsigned char *reg2) +{ + register unsigned char val; + unsigned long mylockcalls; + + pSiS->lockcalls++; + mylockcalls = pSiS->lockcalls; + + /* check if already unlocked */ + inSISIDXREG(SISSR, 0x05, val); + if(val != 0xa1) { + /* save State */ + if(reg1) *reg1 = val; + /* unlock */ + outSISIDXREG(SISSR, 0x05, 0x86); + inSISIDXREG(SISSR, 0x05, val); + if(val != 0xA1) { +#ifdef TWDEBUG + unsigned char val1, val2; + int i; +#endif + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR, + "Failed to unlock sr registers (%p, %x, 0x%02x; %d)\n", + pSiS, pSiS->RelIO, val, mylockcalls); +#ifdef TWDEBUG + for(i = 0; i <= 0x3f; i++) { + inSISIDXREG(SISSR, i, val1); + inSISIDXREG(0x3c4, i, val2); + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO, + "SR%02d: RelIO=0x%02x 0x3c4=0x%02x (%d)\n", i, val1, val2, mylockcalls); + } +#endif + if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { + /* Emergency measure: unlock at 0x3c4, and try to enable Relocated IO ports */ + outSISIDXREG(0x3c4,0x05,0x86); + andSISIDXREG(0x3c4,0x33,~0x20); + outSISIDXREG(SISSR, 0x05, 0x86); + } + } + } + if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { + inSISIDXREG(SISCR, 0x80, val); + if(val != 0xa1) { + /* save State */ + if(reg2) *reg2 = val; + outSISIDXREG(SISCR, 0x80, 0x86); + inSISIDXREG(SISCR, 0x80, val); + if(val != 0xA1) { + xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR, + "Failed to unlock cr registers (%p, %x, 0x%02x)\n", + pSiS, pSiS->RelIO, val); + } + } + } +} + +void +sisRestoreExtRegisterLock(SISPtr pSiS, unsigned char reg1, unsigned char reg2) +{ + /* restore lock */ +#ifndef UNLOCK_ALWAYS + outSISIDXREG(SISSR, 0x05, reg1 == 0xA1 ? 0x86 : 0x00); + if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { + outSISIDXREG(SISCR, 0x80, reg2 == 0xA1 ? 0x86 : 0x00); + } +#endif +} + diff --git a/src/sis_driver.h b/src/sis_driver.h new file mode 100644 index 0000000..8a53cae --- /dev/null +++ b/src/sis_driver.h @@ -0,0 +1,512 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_driver.h,v 1.7 2003/02/04 02:44:29 dawes Exp $ */ +/* + * sis_driver.h + * + * Copyright 2002 by Thomas Winischhofer, Vienna, Austria. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holder not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The copyright holder makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net>: + * - 310/325 series (315/550/650/651/740/M650) support + * - new mode switching code for 300 and 310/325 series + * - many fixes for 300/540/630/730 chipsets, + * - many fixes for 5597/5598, 6326 and 530/620 chipsets, + * - VESA mode switching (deprecated), + * - extended CRT2/video bridge handling support, + * - dual head support on 300 and 310/325 series + * - 650/LVDS (up to 1400x1050), 650/Chrontel 701x support + * - 30xB/30xLV/30xLVX video bridge support (300, 310/325 series) + * - Xv support for 5597/5598, 6326, 530/620 and 310/325 series + * - video overlay enhancements for 300 series + * - etc. + */ + +/* VESA */ +/* TW: The following is included because there are BIOSes out there that + * report incomplete mode lists. These are 630 BIOS versions <2.01.2x + * + * -) VBE 3.0 on SiS300 and 310/325 series do not support 24 fpp modes + * -) Only SiS310/325 series support 1920x1440x32 + */ + /* 8 16 (24) 32 */ +static const UShort VESAModeIndex_512x384[] = {0x134, 0x137, 0x000, 0x000}; +static const UShort VESAModeIndex_640x480[] = {0x101, 0x111, 0x000, 0x13a}; +static const UShort VESAModeIndex_800x600[] = {0x103, 0x114, 0x000, 0x13b}; +static const UShort VESAModeIndex_1024x768[] = {0x105, 0x117, 0x000, 0x13c}; +static const UShort VESAModeIndex_1280x1024[] = {0x107, 0x11a, 0x000, 0x13d}; +static const UShort VESAModeIndex_1600x1200[] = {0x130, 0x131, 0x000, 0x13e}; +static const UShort VESAModeIndex_1920x1440[] = {0x13f, 0x140, 0x000, 0x141}; + +/* TW: For calculating refresh rate index (CR33) */ +static const struct _sis_vrate { + CARD16 idx; + CARD16 xres; + CARD16 yres; + CARD16 refresh; + BOOLEAN SiS730valid32bpp; +} sisx_vrate[] = { + {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, 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, 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, 1024, 576, 60, TRUE}, {2, 1024, 576, 75, TRUE}, {3, 1024, 576, 85, TRUE}, + {1, 1024, 600, 60, TRUE}, + {1, 1152, 768, 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, 1024, 43, TRUE}, {2, 1280, 1024, 60, TRUE}, {3, 1280, 1024, 75, TRUE}, + {4, 1280, 1024, 85, TRUE}, + {1, 1280, 960, 60, TRUE}, {2, 1280, 960, 85, TRUE}, + {1, 1360, 768, 60, 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, 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} +}; + +/* TW: Some 300-series laptops have a badly designed BIOS and make it + * impossible to detect the correct panel delay compensation. This + * table used to detect such machines by their PCI subsystem IDs; + * however, I don't know how reliable this method is. (With Asus + * machines, it is to general, ASUS uses the same ID for different + * boxes) + */ +static const pdctable mypdctable[] = { + { 0x1071, 0x7522, 32, "Mitac", "7521T" }, + { 0, 0, 0, "" , "" } +}; + +static const chswtable mychswtable[] = { + { 0x1631, 0x1002, "Mitachi", "0x1002" }, + { 0, 0, "" , "" } +}; + +/* TW: Our TV modes for the 6326. The data in these structures + * is mainly correct, but since we use our private CR and + * clock values anyway, small errors do no matter. + */ +static DisplayModeRec SiS6326PAL800x600Mode = { + NULL, NULL, /* prev, next */ + "PAL800x600", /* identifier of this mode */ + MODE_OK, /* mode status */ + M_T_BUILTIN, /* mode type */ + 36000, /* Clock frequency */ + 800, /* HDisplay */ + 848, /* HSyncStart */ + 912, /* HSyncEnd */ + 1008, /* HTotal */ + 0, /* HSkew */ + 600, /* VDisplay */ + 600, /* VSyncStart */ + 602, /* VSyncEnd */ + 625, /* VTotal */ + 0, /* VScan */ + V_PHSYNC | V_PVSYNC, /* Flags */ + -1, /* ClockIndex */ + 36000, /* SynthClock */ + 800, /* CRTC HDisplay */ + 808, /* CRTC HBlankStart */ + 848, /* CRTC HSyncStart */ + 912, /* CRTC HSyncEnd */ + 1008, /* CRTC HBlankEnd */ + 1008, /* CRTC HTotal */ + 0, /* CRTC HSkew */ + 600, /* CRTC VDisplay */ + 600, /* CRTC VBlankStart */ + 600, /* CRTC VSyncStart */ + 602, /* CRTC VSyncEnd */ + 625, /* CRTC VBlankEnd */ + 625, /* CRTC VTotal */ + FALSE, /* CrtcHAdjusted */ + FALSE, /* CrtcVAdjusted */ + 0, /* PrivSize */ + NULL, /* Private */ + 0.0, /* HSync */ + 0.0 /* VRefresh */ +}; + +/* TW: Due to the scaling method this mode uses, the vertical data here + * does not match the CR data. But this does not matter, we use our + * private CR data anyway. + */ +static DisplayModeRec SiS6326PAL800x600UMode = { + NULL, /* prev */ + &SiS6326PAL800x600Mode, /* next */ + "PAL800x600U", /* identifier of this mode */ + MODE_OK, /* mode status */ + M_T_BUILTIN, /* mode type */ + 37120, /* Clock frequency */ + 800, /* HDisplay */ + 872, /* HSyncStart */ + 984, /* HSyncEnd */ + 1088, /* HTotal */ + 0, /* HSkew */ + 600, /* VDisplay (548 due to scaling) */ + 600, /* VSyncStart (584) */ + 602, /* VSyncEnd (586) */ + 625, /* VTotal */ + 0, /* VScan */ + V_PHSYNC | V_PVSYNC, /* Flags */ + -1, /* ClockIndex */ + 37120, /* SynthClock */ + 800, /* CRTC HDisplay */ + 808, /* CRTC HBlankStart */ + 872, /* CRTC HSyncStart */ + 984, /* CRTC HSyncEnd */ + 1024, /* CRTC HBlankEnd */ + 1088, /* CRTC HTotal */ + 0, /* CRTC HSkew */ + 600, /* CRTC VDisplay (548 due to scaling) */ + 600, /* CRTC VBlankStart (600) */ + 600, /* CRTC VSyncStart (584) */ + 602, /* CRTC VSyncEnd (586) */ + 625, /* CRTC VBlankEnd */ + 625, /* CRTC VTotal */ + FALSE, /* CrtcHAdjusted */ + FALSE, /* CrtcVAdjusted */ + 0, /* PrivSize */ + NULL, /* Private */ + 0.0, /* HSync */ + 0.0 /* VRefresh */ +}; + +static DisplayModeRec SiS6326PAL720x540Mode = { + NULL, /* prev */ + &SiS6326PAL800x600UMode, /* next */ + "PAL720x540", /* identifier of this mode */ + MODE_OK, /* mode status */ + M_T_BUILTIN, /* mode type */ + 36000, /* Clock frequency */ + 720, /* HDisplay */ + 816, /* HSyncStart */ + 920, /* HSyncEnd */ + 1008, /* HTotal */ + 0, /* HSkew */ + 540, /* VDisplay */ + 578, /* VSyncStart */ + 580, /* VSyncEnd */ + 625, /* VTotal */ + 0, /* VScan */ + V_PHSYNC | V_PVSYNC, /* Flags */ + -1, /* ClockIndex */ + 36000, /* SynthClock */ + 720, /* CRTC HDisplay */ + 736, /* CRTC HBlankStart */ + 816, /* CRTC HSyncStart */ + 920, /* CRTC HSyncEnd */ + 1008, /* CRTC HBlankEnd */ + 1008, /* CRTC HTotal */ + 0, /* CRTC HSkew */ + 540, /* CRTC VDisplay */ + 577, /* CRTC VBlankStart */ + 578, /* CRTC VSyncStart */ + 580, /* CRTC VSyncEnd */ + 625, /* CRTC VBlankEnd */ + 625, /* CRTC VTotal */ + FALSE, /* CrtcHAdjusted */ + FALSE, /* CrtcVAdjusted */ + 0, /* PrivSize */ + NULL, /* Private */ + 0.0, /* HSync */ + 0.0 /* VRefresh */ +}; + +static DisplayModeRec SiS6326PAL640x480Mode = { + NULL, /* prev */ + &SiS6326PAL720x540Mode, /* next */ + "PAL640x480", /* identifier of this mode */ + MODE_OK, /* mode status */ + M_T_BUILTIN, /* mode type */ + 36000, /* Clock frequency */ + 640, /* HDisplay */ + 768, /* HSyncStart */ + 920, /* HSyncEnd */ + 1008, /* HTotal */ + 0, /* HSkew */ + 480, /* VDisplay */ + 532, /* VSyncStart */ + 534, /* VSyncEnd */ + 625, /* VTotal */ + 0, /* VScan */ + V_NHSYNC | V_NVSYNC, /* Flags */ + -1, /* ClockIndex */ + 36000, /* SynthClock */ + 640, /* CRTC HDisplay */ + 648, /* CRTC HBlankStart */ + 768, /* CRTC HSyncStart */ + 920, /* CRTC HSyncEnd */ + 944, /* CRTC HBlankEnd */ + 1008, /* CRTC HTotal */ + 0, /* CRTC HSkew */ + 480, /* CRTC VDisplay */ + 481, /* CRTC VBlankStart */ + 532, /* CRTC VSyncStart */ + 534, /* CRTC VSyncEnd */ + 561, /* CRTC VBlankEnd */ + 625, /* CRTC VTotal */ + FALSE, /* CrtcHAdjusted */ + FALSE, /* CrtcVAdjusted */ + 0, /* PrivSize */ + NULL, /* Private */ + 0.0, /* HSync */ + 0.0 /* VRefresh */ +}; + +static DisplayModeRec SiS6326NTSC640x480Mode = { + NULL, NULL, /* prev, next */ + "NTSC640x480", /* identifier of this mode */ + MODE_OK, /* mode status */ + M_T_BUILTIN, /* mode type */ + 27000, /* Clock frequency */ + 640, /* HDisplay */ + 664, /* HSyncStart */ + 760, /* HSyncEnd */ + 800, /* HTotal */ + 0, /* HSkew */ + 480, /* VDisplay */ + 489, /* VSyncStart */ + 491, /* VSyncEnd */ + 525, /* VTotal */ + 0, /* VScan */ + V_NHSYNC | V_NVSYNC, /* Flags */ + -1, /* ClockIndex */ + 27000, /* SynthClock */ + 640, /* CRTC HDisplay */ + 648, /* CRTC HBlankStart */ + 664, /* CRTC HSyncStart */ + 760, /* CRTC HSyncEnd */ + 792, /* CRTC HBlankEnd */ + 800, /* CRTC HTotal */ + 0, /* CRTC HSkew */ + 480, /* CRTC VDisplay */ + 488, /* CRTC VBlankStart */ + 489, /* CRTC VSyncStart */ + 491, /* CRTC VSyncEnd */ + 517, /* CRTC VBlankEnd */ + 525, /* CRTC VTotal */ + FALSE, /* CrtcHAdjusted */ + FALSE, /* CrtcVAdjusted */ + 0, /* PrivSize */ + NULL, /* Private */ + 0.0, /* HSync */ + 0.0 /* VRefresh */ +}; + +/* TW: Due to the scaling method this mode uses, the vertical data here + * does not match the CR data. But this does not matter, we use our + * private CR data anyway. + */ +static DisplayModeRec SiS6326NTSC640x480UMode = { + NULL, /* prev */ + &SiS6326NTSC640x480Mode, /* next */ + "NTSC640x480U", /* identifier of this mode */ + MODE_OK, /* mode status */ + M_T_BUILTIN, /* mode type */ + 32215, /* Clock frequency */ + 640, /* HDisplay */ + 696, /* HSyncStart */ + 840, /* HSyncEnd */ + 856, /* HTotal */ + 0, /* HSkew */ + 480, /* VDisplay (439 due to scaling) */ + 489, /* VSyncStart (473) */ + 491, /* VSyncEnd (475) */ + 525, /* VTotal */ + 0, /* VScan */ + V_NHSYNC | V_NVSYNC, /* Flags */ + -1, /* ClockIndex */ + 32215, /* SynthClock */ + 640, /* CRTC HDisplay */ + 656, /* CRTC HBlankStart */ + 696, /* CRTC HSyncStart */ + 840, /* CRTC HSyncEnd */ + 856, /* CRTC HBlankEnd */ + 856, /* CRTC HTotal */ + 0, /* CRTC HSkew */ + 480, /* CRTC VDisplay */ + 488, /* CRTC VBlankStart */ + 489, /* CRTC VSyncStart */ + 491, /* CRTC VSyncEnd */ + 517, /* CRTC VBlankEnd */ + 525, /* CRTC VTotal */ + FALSE, /* CrtcHAdjusted */ + FALSE, /* CrtcVAdjusted */ + 0, /* PrivSize */ + NULL, /* Private */ + 0.0, /* HSync */ + 0.0 /* VRefresh */ +}; + + +static DisplayModeRec SiS6326NTSC640x400Mode = { + NULL, /* prev */ + &SiS6326NTSC640x480UMode, /* next */ + "NTSC640x400", /* identifier of this mode */ + MODE_OK, /* mode status */ + M_T_BUILTIN, /* mode type */ + 27000, /* Clock frequency */ + 640, /* HDisplay */ + 664, /* HSyncStart */ + 760, /* HSyncEnd */ + 800, /* HTotal */ + 0, /* HSkew */ + 400, /* VDisplay */ + 459, /* VSyncStart */ + 461, /* VSyncEnd */ + 525, /* VTotal */ + 0, /* VScan */ + V_NHSYNC | V_NVSYNC, /* Flags */ + -1, /* ClockIndex */ + 27000, /* SynthClock */ + 640, /* CRTC HDisplay */ + 648, /* CRTC HBlankStart */ + 664, /* CRTC HSyncStart */ + 760, /* CRTC HSyncEnd */ + 792, /* CRTC HBlankEnd */ + 800, /* CRTC HTotal */ + 0, /* CRTC HSkew */ + 400, /* CRTC VDisplay */ + 407, /* CRTC VBlankStart */ + 459, /* CRTC VSyncStart */ + 461, /* CRTC VSyncEnd */ + 490, /* CRTC VBlankEnd */ + 525, /* CRTC VTotal */ + FALSE, /* CrtcHAdjusted */ + FALSE, /* CrtcVAdjusted */ + 0, /* PrivSize */ + NULL, /* Private */ + 0.0, /* HSync */ + 0.0 /* VRefresh */ +}; + +/* TW: Built-in hi-res modes for the 6326. + * For some reason, our default mode lines and the + * clock calculation functions in sis_dac.c do no + * good job on higher clocks. It seems, the hardware + * needs some tricks so make mode with higher clock + * rates than ca. 120MHz work. I didn't bother trying + * to find out what exactly is going wrong, so I + * implemented two special modes instead for 1280x1024 + * and 1600x1200. These two are automatically added + * to the list if they are supported with the current + * depth. + * The data in the strucures below is a proximation, + * in sis_vga.c the register contents are fetched from + * fixed tables anyway. + */ +static DisplayModeRec SiS6326SIS1280x1024_75Mode = { + NULL, /* prev */ + NULL, /* next */ + "SIS1280x1024-75", /* identifier of this mode */ + MODE_OK, /* mode status */ + M_T_BUILTIN, /* mode type */ + 135000, /* Clock frequency */ + 1280, /* HDisplay */ + 1296, /* HSyncStart */ + 1440, /* HSyncEnd */ + 1688, /* HTotal */ + 0, /* HSkew */ + 1024, /* VDisplay */ + 1025, /* VSyncStart */ + 1028, /* VSyncEnd */ + 1066, /* VTotal */ + 0, /* VScan */ + V_PHSYNC | V_PVSYNC, /* Flags */ + -1, /* ClockIndex */ + 135000, /* SynthClock */ + 1280, /* CRTC HDisplay */ + 1280, /* CRTC HBlankStart */ + 1296, /* CRTC HSyncStart */ + 1440, /* CRTC HSyncEnd */ + 1680, /* CRTC HBlankEnd */ + 1688, /* CRTC HTotal */ + 0, /* CRTC HSkew */ + 1024, /* CRTC VDisplay */ + 1024, /* CRTC VBlankStart */ + 1025, /* CRTC VSyncStart */ + 1028, /* CRTC VSyncEnd */ + 1065, /* CRTC VBlankEnd */ + 1066, /* CRTC VTotal */ + FALSE, /* CrtcHAdjusted */ + FALSE, /* CrtcVAdjusted */ + 0, /* PrivSize */ + NULL, /* Private */ + 0.0, /* HSync */ + 0.0 /* VRefresh */ +}; + +static DisplayModeRec SiS6326SIS1600x1200_60Mode = { + NULL, /* prev */ + NULL, /* next */ + "SIS1600x1200-60", /* identifier of this mode */ + MODE_OK, /* mode status */ + M_T_BUILTIN, /* mode type */ + 162000, /* Clock frequency */ + 1600, /* HDisplay */ + 1664, /* HSyncStart */ + 1856, /* HSyncEnd */ + 2160, /* HTotal */ + 0, /* HSkew */ + 1200, /* VDisplay */ + 1201, /* VSyncStart */ + 1204, /* VSyncEnd */ + 1250, /* VTotal */ + 0, /* VScan */ + V_PHSYNC | V_PVSYNC, /* Flags */ + -1, /* ClockIndex */ + 162000, /* SynthClock */ + 1600, /* CRTC HDisplay */ + 1600, /* CRTC HBlankStart */ + 1664, /* CRTC HSyncStart */ + 1856, /* CRTC HSyncEnd */ + 2152, /* CRTC HBlankEnd */ + 2160, /* CRTC HTotal */ + 0, /* CRTC HSkew */ + 1200, /* CRTC VDisplay */ + 1200, /* CRTC VBlankStart */ + 1201, /* CRTC VSyncStart */ + 1204, /* CRTC VSyncEnd */ + 1249, /* CRTC VBlankEnd */ + 1250, /* CRTC VTotal */ + FALSE, /* CrtcHAdjusted */ + FALSE, /* CrtcVAdjusted */ + 0, /* PrivSize */ + NULL, /* Private */ + 0.0, /* HSync */ + 0.0 /* VRefresh */ +}; + diff --git a/src/sis_opt.c b/src/sis_opt.c new file mode 100644 index 0000000..bd8be86 --- /dev/null +++ b/src/sis_opt.c @@ -0,0 +1,774 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_opt.c,v 1.15 2003/02/04 02:44:29 dawes Exp $ */ +/* + * + * SiS driver option evaluation + * + * Parts Copyright 2001, 2002 by Thomas Winischhofer, Vienna, Austria + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the supplier not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The supplier makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE SUPPLIER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: ? + * Thomas Winischhofer <thomas@winischhofer.net> + */ + +#include "xf86.h" +#include "xf86PciInfo.h" +#include "xf86str.h" +#include "xf86Cursor.h" + +#include "sis.h" + +typedef enum { + OPTION_SW_CURSOR, + OPTION_HW_CURSOR, +/* OPTION_PCI_RETRY, */ + OPTION_NOACCEL, + OPTION_TURBOQUEUE, + OPTION_FAST_VRAM, + OPTION_NOHOSTBUS, +/* OPTION_SET_MEMCLOCK, */ + OPTION_FORCE_CRT2TYPE, + OPTION_SHADOW_FB, + OPTION_ROTATE, + OPTION_NOXVIDEO, + OPTION_VESA, + OPTION_MAXXFBMEM, + OPTION_FORCECRT1, + OPTION_DSTN, + OPTION_XVONCRT2, + OPTION_PDC, + OPTION_TVSTANDARD, + OPTION_USEROMDATA, + OPTION_NOINTERNALMODES, + OPTION_USEOEM, + OPTION_SBIOSN, + OPTION_NOYV12, + OPTION_CHTVOVERSCAN, + OPTION_CHTVSOVERSCAN, + OPTION_CHTVLUMABANDWIDTHCVBS, + OPTION_CHTVLUMABANDWIDTHSVIDEO, + OPTION_CHTVLUMAFLICKERFILTER, + OPTION_CHTVCHROMABANDWIDTH, + OPTION_CHTVCHROMAFLICKERFILTER, + OPTION_CHTVCVBSCOLOR, + OPTION_CHTVTEXTENHANCE, + OPTION_CHTVCONTRAST, + OPTION_SISTVEDGEENHANCE, + OPTION_SISTVANTIFLICKER, + OPTION_SISTVSATURATION, + OPTION_TVXPOSOFFSET, + OPTION_TVYPOSOFFSET, + OPTION_SIS6326ANTIFLICKER, + OPTION_SIS6326ENABLEYFILTER, + OPTION_SIS6326YFILTERSTRONG, + OPTION_CHTVTYPE, + OPTION_USERGBCURSOR, + OPTION_USERGBCURSORBLEND, + OPTION_USERGBCURSORBLENDTH, + OPTION_RESTOREBYSET +} SISOpts; + +static const OptionInfoRec SISOptions[] = { + { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, +/* { OPTION_PCI_RETRY, "PciRetry", OPTV_BOOLEAN, {0}, FALSE }, */ + { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_TURBOQUEUE, "TurboQueue", OPTV_BOOLEAN, {0}, FALSE }, +/* { OPTION_SET_MEMCLOCK, "SetMClk", OPTV_FREQ, {0}, -1 }, */ + { OPTION_FAST_VRAM, "FastVram", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NOHOSTBUS, "NoHostBus", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_FORCE_CRT2TYPE, "ForceCRT2Type", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_NOXVIDEO, "NoXvideo", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_VESA, "Vesa", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_MAXXFBMEM, "MaxXFBMem", OPTV_INTEGER, {0}, -1 }, + { OPTION_FORCECRT1, "ForceCRT1", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_DSTN, "DSTN", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_XVONCRT2, "XvOnCRT2", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_PDC, "PanelDelayCompensation", OPTV_INTEGER, {0}, -1 }, + { OPTION_TVSTANDARD, "TVStandard", OPTV_STRING, {0}, -1 }, + { OPTION_USEROMDATA, "UseROMData", OPTV_BOOLEAN, {0}, -1 }, + { OPTION_NOINTERNALMODES, "NoInternalModes", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_USEOEM, "UseOEMData", OPTV_BOOLEAN, {0}, -1 }, + { OPTION_SBIOSN, "BIOSFile", OPTV_STRING, {0}, FALSE }, + { OPTION_NOYV12, "NoYV12", OPTV_BOOLEAN, {0}, -1 }, + { OPTION_CHTVTYPE, "CHTVType", OPTV_BOOLEAN, {0}, -1 }, + { OPTION_CHTVOVERSCAN, "CHTVOverscan", OPTV_BOOLEAN, {0}, -1 }, + { OPTION_CHTVSOVERSCAN, "CHTVSuperOverscan", OPTV_BOOLEAN, {0}, -1 }, + { OPTION_CHTVLUMABANDWIDTHCVBS, "CHTVLumaBandwidthCVBS", OPTV_INTEGER, {0}, -1 }, + { OPTION_CHTVLUMABANDWIDTHSVIDEO, "CHTVLumaBandwidthSVIDEO",OPTV_INTEGER, {0}, -1 }, + { OPTION_CHTVLUMAFLICKERFILTER, "CHTVLumaFlickerFilter", OPTV_INTEGER, {0}, -1 }, + { OPTION_CHTVCHROMABANDWIDTH, "CHTVChromaBandwidth", OPTV_INTEGER, {0}, -1 }, + { OPTION_CHTVCHROMAFLICKERFILTER, "CHTVChromaFlickerFilter",OPTV_INTEGER, {0}, -1 }, + { OPTION_CHTVCVBSCOLOR, "CHTVCVBSColor", OPTV_BOOLEAN, {0}, -1 }, + { OPTION_CHTVTEXTENHANCE, "CHTVTextEnhance", OPTV_INTEGER, {0}, -1 }, + { OPTION_CHTVCONTRAST, "CHTVContrast", OPTV_INTEGER, {0}, -1 }, + { OPTION_SISTVEDGEENHANCE, "SISTVEdgeEnhance", OPTV_INTEGER, {0}, -1 }, + { OPTION_SISTVANTIFLICKER, "SISTVAntiFlicker", OPTV_INTEGER, {0}, -1 }, + { OPTION_SISTVSATURATION, "SISTVSaturation", OPTV_INTEGER, {0}, -1 }, + { OPTION_TVXPOSOFFSET, "TVXPosOffset", OPTV_INTEGER, {0}, -1 }, + { OPTION_TVYPOSOFFSET, "TVYPosOffset", OPTV_INTEGER, {0}, -1 }, + { OPTION_SIS6326ANTIFLICKER, "SIS6326TVAntiFlicker", OPTV_STRING, {0}, FALSE }, + { OPTION_SIS6326ENABLEYFILTER, "SIS6326TVEnableYFilter", OPTV_BOOLEAN, {0}, -1 }, + { OPTION_SIS6326YFILTERSTRONG, "SIS6326TVYFilterStrong", OPTV_BOOLEAN, {0}, -1 }, + { OPTION_USERGBCURSOR, "UseColorHWCursor", OPTV_BOOLEAN, {0}, -1 }, + { OPTION_USERGBCURSORBLEND, "ColorHWCursorBlending", OPTV_BOOLEAN, {0}, -1 }, + { OPTION_USERGBCURSORBLENDTH, "ColorHWCursorBlendThreshold", OPTV_INTEGER, {0}, -1 }, + { OPTION_RESTOREBYSET, "RestoreBySetMode", OPTV_BOOLEAN, {0}, -1 }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +void +SiSOptions(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + MessageType from; +/* double temp; */ + char *strptr; + + /* Collect all of the relevant option flags (fill in pScrn->options) */ + xf86CollectOptions(pScrn, NULL); + + /* Process the options */ + if (!(pSiS->Options = xalloc(sizeof(SISOptions)))) + return; + + memcpy(pSiS->Options, SISOptions, sizeof(SISOptions)); + + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pSiS->Options); + + /* initalize some defaults */ + pSiS->newFastVram = -1; /* TW: Default: write only; if set, read + write */ + pSiS->NoHostBus = FALSE; +/* pSiS->UsePCIRetry = TRUE; */ + pSiS->TurboQueue = TRUE; + pSiS->HWCursor = TRUE; + pSiS->Rotate = FALSE; + pSiS->ShadowFB = FALSE; + pSiS->VESA = -1; + pSiS->NoXvideo = FALSE; + pSiS->maxxfbmem = 0; + pSiS->forceCRT1 = -1; + pSiS->DSTN = FALSE; /* TW: For using 550 FSTN/DSTN registers */ + pSiS->XvOnCRT2 = FALSE; /* TW: For chipsets with only one overlay */ + pSiS->NoYV12 = -1; + pSiS->PDC = -1; /* TW: Panel Delay Compensation for 300 (and 310/325) series */ + pSiS->OptTVStand = -1; + pSiS->OptROMUsage = -1; + pSiS->noInternalModes = FALSE; + pSiS->OptUseOEM = -1; + pSiS->OptTVOver = -1; + pSiS->OptTVSOver = -1; + pSiS->chtvlumabandwidthcvbs = -1; /* TW: Chrontel TV settings */ + pSiS->chtvlumabandwidthsvideo = -1; + pSiS->chtvlumaflickerfilter = -1; + pSiS->chtvchromabandwidth = -1; + pSiS->chtvchromaflickerfilter = -1; + pSiS->chtvcvbscolor = -1; + pSiS->chtvtextenhance = -1; + pSiS->chtvcontrast = -1; + pSiS->sistvedgeenhance = -1; /* TW: SiS30x TV settings */ + pSiS->sistvantiflicker = -1; + pSiS->sistvsaturation = -1; + pSiS->sis6326antiflicker = -1; /* TW: SiS6326 TV settings */ + pSiS->sis6326enableyfilter = -1; + pSiS->sis6326yfilterstrong = -1; + pSiS->tvxpos = 0; /* TW: Some day hopefully general TV settings */ + pSiS->tvypos = 0; + pSiS->NonDefaultPAL = -1; + pSiS->chtvtype = -1; +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0) + pSiS->OptUseColorCursor = 0; +#else + if(pSiS->VGAEngine == SIS_300_VGA) { + pSiS->OptUseColorCursor = 0; + pSiS->OptUseColorCursorBlend = 1; + pSiS->OptColorCursorBlendThreshold = 0x37000000; + } else if(pSiS->VGAEngine == SIS_315_VGA) { + pSiS->OptUseColorCursor = 1; + } +#endif + pSiS->restorebyset = 0; + + if(pSiS->Chipset == PCI_CHIP_SIS530) { + /* TW: TQ still broken on 530/620? */ + pSiS->TurboQueue = FALSE; + } + + /* sw/hw cursor */ + from = X_DEFAULT; + if(xf86GetOptValBool(pSiS->Options, OPTION_HW_CURSOR, &pSiS->HWCursor)) { + from = X_CONFIG; + } + if(xf86ReturnOptValBool(pSiS->Options, OPTION_SW_CURSOR, FALSE)) { + from = X_CONFIG; + pSiS->HWCursor = FALSE; + pSiS->OptUseColorCursor = 0; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", + pSiS->HWCursor ? "HW" : "SW"); + +#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0) +#ifdef ARGB_CURSOR +#ifdef SIS_ARGB_CURSOR + if((pSiS->HWCursor) && ((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA))) { + from = X_DEFAULT; + if(xf86GetOptValBool(pSiS->Options, OPTION_USERGBCURSOR, &pSiS->OptUseColorCursor)) { + from = X_CONFIG; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Color HW cursor is %s\n", + pSiS->OptUseColorCursor ? "enabled" : "disabled"); + + if(pSiS->VGAEngine == SIS_300_VGA) { + from = X_DEFAULT; + if(xf86GetOptValBool(pSiS->Options, OPTION_USERGBCURSORBLEND, &pSiS->OptUseColorCursorBlend)) { + from = X_CONFIG; + } + if(pSiS->OptUseColorCursor) { + xf86DrvMsg(pScrn->scrnIndex, from, + "HW cursor color blending emulation is %s\n", + (pSiS->OptUseColorCursorBlend) ? "enabled" : "disabled"); + } + { + int temp; + from = X_DEFAULT; + if(xf86GetOptValInteger(pSiS->Options, OPTION_USERGBCURSORBLENDTH, &temp)) { + if((temp >= 0) && (temp <= 255)) { + from = X_CONFIG; + pSiS->OptColorCursorBlendThreshold = (temp << 24); + } else { + temp = pSiS->OptColorCursorBlendThreshold >> 24; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Illegal color HW cursor blending threshold, valid range 0-255\n"); + } + } + if(pSiS->OptUseColorCursor) { + if(pSiS->OptUseColorCursorBlend) { + xf86DrvMsg(pScrn->scrnIndex, from, + "HW cursor color blending emulation threshold is %d\n", temp); + } + } + } + } + } +#endif +#endif +#endif + + /* Accel */ + if(xf86ReturnOptValBool(pSiS->Options, OPTION_NOACCEL, FALSE)) { + pSiS->NoAccel = TRUE; + pSiS->NoXvideo = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration and Xv disabled\n"); + } + +#if 0 + /* PCI retry - TW: What the heck is/was this for? */ + from = X_DEFAULT; + if(xf86GetOptValBool(pSiS->Options, OPTION_PCI_RETRY, &pSiS->UsePCIRetry)) { + from = X_CONFIG; + } + xf86DrvMsg(pScrn->scrnIndex, from, "PCI retry %s\n", + pSiS->UsePCIRetry ? "enabled" : "disabled"); +#endif + + /* Mem clock */ +#if 0 /* TW: This is not used */ + if(xf86GetOptValFreq(pSiS->Options, OPTION_SET_MEMCLOCK, OPTUNITS_MHZ, + &temp)) { + pSiS->MemClock = (int)(temp * 1000.0); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Memory clock set to %.3f MHz\n", pSiS->MemClock/1000.0); + } +#endif + + /* Fast VRAM (not for 300/310/325 series) */ + if((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) { + from = X_DEFAULT; + if(xf86GetOptValBool(pSiS->Options, OPTION_FAST_VRAM, &pSiS->newFastVram)) { + from = X_CONFIG; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Fast VRAM %s\n", + (pSiS->newFastVram == -1) ? "enabled (for write only)" : + (pSiS->newFastVram ? "enabled (for read and write)" : "disabled")); + } + + /* NoHostBus (5597/5598 only) */ + if((pSiS->Chipset == PCI_CHIP_SIS5597)) { + from = X_DEFAULT; + if(xf86GetOptValBool(pSiS->Options, OPTION_NOHOSTBUS, &pSiS->NoHostBus)) { + from = X_CONFIG; + } + xf86DrvMsg(pScrn->scrnIndex, from, "SiS5597/5598 VGA-to-CPU host bus %s\n", + pSiS->NoHostBus ? "disabled" : "enabled"); + } + + if(pSiS->VGAEngine != SIS_315_VGA) { + /* Turbo QUEUE */ + /* (TW: We always use this on 310/325 series) */ + from = X_DEFAULT; + if(xf86GetOptValBool(pSiS->Options, OPTION_TURBOQUEUE, &pSiS->TurboQueue)) { + from = X_CONFIG; + } + xf86DrvMsg(pScrn->scrnIndex, from, "TurboQueue %s\n", + pSiS->TurboQueue ? "enabled" : "disabled"); + } + + /* Force CRT2 type (300/310/325 series only) + TW: SVIDEO, COMPOSITE and SCART for overriding detection + */ + pSiS->ForceCRT2Type = CRT2_DEFAULT; + pSiS->ForceTVType = -1; + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + strptr = (char *)xf86GetOptValString(pSiS->Options, OPTION_FORCE_CRT2TYPE); + if(strptr != NULL) { + if((!strcmp(strptr,"TV")) || (!strcmp(strptr,"tv"))) + pSiS->ForceCRT2Type = CRT2_TV; + else if((!strcmp(strptr,"SVIDEO")) || (!strcmp(strptr,"svideo"))) { + pSiS->ForceCRT2Type = CRT2_TV; + pSiS->ForceTVType = TV_SVIDEO; + } else if((!strcmp(strptr,"COMPOSITE")) || (!strcmp(strptr,"composite"))) { + pSiS->ForceCRT2Type = CRT2_TV; + pSiS->ForceTVType = TV_AVIDEO; + } else if((!strcmp(strptr,"SCART")) || (!strcmp(strptr,"scart"))) { + pSiS->ForceCRT2Type = CRT2_TV; + pSiS->ForceTVType = TV_SCART; + } else if((!strcmp(strptr,"LCD")) || (!strcmp(strptr,"lcd"))) + pSiS->ForceCRT2Type = CRT2_LCD; + else if((!strcmp(strptr,"DVI")) || (!strcmp(strptr,"dvi"))) + pSiS->ForceCRT2Type = CRT2_LCD; + else if((!strcmp(strptr,"VGA")) || (!strcmp(strptr,"vga"))) + pSiS->ForceCRT2Type = CRT2_VGA; + else if((!strcmp(strptr,"NONE")) || (!strcmp(strptr,"none"))) + pSiS->ForceCRT2Type = 0; + else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\"%s\" is not a valid parameter for Option \"ForceCRT2Type\"\n", strptr); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid parameters are \"LCD\" (alias \"DVI\"), \"TV\", \"SVIDEO\", \"COMPOSITE\", \"SCART\", \"VGA\" or \"NONE\"\n"); + } + + if(pSiS->ForceCRT2Type != CRT2_DEFAULT) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "CRT2 type shall be %s\n", strptr); + } + strptr = (char *)xf86GetOptValString(pSiS->Options, OPTION_CHTVTYPE); + if(strptr != NULL) { + if((!strcmp(strptr,"SCART")) || (!strcmp(strptr,"scart"))) + pSiS->chtvtype = 1; + else if((!strcmp(strptr,"HDTV")) || (!strcmp(strptr,"hdtv"))) + pSiS->chtvtype = 0; + else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\"%s\" is not a valid parameter for Option \"CHTVType\"\n", strptr); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid parameters are \"SCART\" or \"HDTV\"\n"); + } + if(pSiS->chtvtype != -1) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Chrontel TV type shall be %s\n", strptr); + } + } + + /* ShadowFB */ + from = X_DEFAULT; + if(xf86GetOptValBool(pSiS->Options, OPTION_SHADOW_FB, &pSiS->ShadowFB)) { + from = X_CONFIG; + } + if(pSiS->ShadowFB) { + pSiS->NoAccel = TRUE; + pSiS->NoXvideo = TRUE; + xf86DrvMsg(pScrn->scrnIndex, from, + "Using \"Shadow Frame Buffer\" - acceleration and Xv disabled\n"); + } + + /* Rotate */ + if((strptr = (char *)xf86GetOptValString(pSiS->Options, OPTION_ROTATE))) { + if(!xf86NameCmp(strptr, "CW")) { + pSiS->ShadowFB = TRUE; + pSiS->NoAccel = TRUE; + pSiS->NoXvideo = TRUE; + pSiS->HWCursor = FALSE; + pSiS->Rotate = 1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen clockwise (acceleration and Xv disabled)\n"); + } else + if(!xf86NameCmp(strptr, "CCW")) { + pSiS->ShadowFB = TRUE; + pSiS->NoAccel = TRUE; + pSiS->NoXvideo = TRUE; + pSiS->HWCursor = FALSE; + pSiS->Rotate = -1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen counter clockwise (acceleration and Xv disabled)\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\"%s\" is not a valid parameter for Option \"Rotate\"\n", strptr); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid parameters are \"CW\" or \"CCW\"\n"); + } + } + + /* RestoreBySetMode */ + /* TW: Set this to force the driver to set the old mode instead of restoring + * the register contents. This can be used to overcome problems with + * LCD panels and video bridges. + */ + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + Bool val; + if(xf86GetOptValBool(pSiS->Options, OPTION_RESTOREBYSET, &val)) { + if(val) pSiS->restorebyset = TRUE; + else pSiS->restorebyset = FALSE; + } + } + + /* NOXvideo: + * Set this to TRUE to disable Xv hardware video acceleration + */ + if(!pSiS->NoAccel) { + if(xf86ReturnOptValBool(pSiS->Options, OPTION_NOXVIDEO, FALSE)) { + pSiS->NoXvideo = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "XVideo extension disabled\n"); + } + + if(!pSiS->NoXvideo) { + Bool val; + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + /* TW: XvOnCRT2: + * On chipsets with only one overlay (315, 650), the user should + * choose to display the overlay on CRT1 or CRT2. By setting this + * option to TRUE, the overlay will be displayed on CRT2. The + * default is: CRT1 if only CRT1 available, CRT2 if only CRT2 + * available, and CRT1 if both is available and detected. + */ + if(xf86GetOptValBool(pSiS->Options, OPTION_XVONCRT2, &val)) { + if(val) pSiS->XvOnCRT2 = TRUE; + else pSiS->XvOnCRT2 = FALSE; + } + } + if((pSiS->VGAEngine == SIS_OLD_VGA) || (pSiS->VGAEngine == SIS_530_VGA)) { + /* TW: NoYV12 (for 5597/5598, 6326 and 530/620 only) + * YV12 has problems with videos larger than 384x288. So + * allow the user to disable YV12 support to force the + * application to use YUV2 instead. + */ + if(xf86GetOptValBool(pSiS->Options, OPTION_NOYV12, &val)) { + if(val) pSiS->NoYV12 = 1; + else pSiS->NoYV12 = 0; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Xv YV12/I420 support is %s\n", + pSiS->NoYV12 ? "disabled" : "enabled"); + } + } + } + } + + /* TW: VESA - DEPRECATED + * This option is for forcing the driver to use + * the VESA BIOS extension for mode switching. + */ + { + Bool val; + + if(xf86GetOptValBool(pSiS->Options, OPTION_VESA, &val)) { + if(val) pSiS->VESA = 1; + else pSiS->VESA = 0; + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VESA: VESA usage shall be %s\n", + val ? "enabled":"disabled"); + } + } + + /* TW: MaxXFBMem + * With the option "MaxXFBMem" you can limit the amount of video memory X + * uses for screen and off-screen buffers. This option should be used if + * you intend to use DRI/DRM. The framebuffer driver required for DRM will + * start its memory heap at 12MB if it detects more than 16MB, at 8MB if + * between 8 and 16MB are available, otherwise at 4MB. So, if you limit + * the amount of memory X uses, you avoid a clash between the framebuffer + * driver and X as regards overwriting memory portions of each other. + * The amount is to be specified in KB. + */ + if(xf86GetOptValULong(pSiS->Options, OPTION_MAXXFBMEM, + &pSiS->maxxfbmem)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "MaxXFBMem: Framebuffer memory shall be limited to %d KB\n", + pSiS->maxxfbmem); + pSiS->maxxfbmem *= 1024; + } + + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + /* TW: ForceCRT1 (300/310/325 series only) + * This option can be used to force CRT1 to be switched on/off. Its + * intention is mainly for old monitors that can't be detected + * automatically. This is only useful on machines with a video bridge. + * In normal cases, this option won't be necessary. + */ + Bool val; + if(xf86GetOptValBool(pSiS->Options, OPTION_FORCECRT1, &val)) { + if(val) pSiS->forceCRT1 = 1; + else pSiS->forceCRT1 = 0; + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "CRT1 shall be forced to %s\n", + val ? "ON" : "OFF"); + } + } + + if(pSiS->Chipset == PCI_CHIP_SIS550) { + /* TW: SiS 550 DSTN/FSTN + * This is for notifying the driver to use the DSTN registers on 550. + * DSTN/FSTN is a special LCD port of the SiS550 (notably not the 551 + * and 552, which I don't know how to detect) that uses an extended + * register range. The only effect of this option is that the driver + * saves and restores these registers. DSTN display modes are chosen + * by using resultion 320x480x8 or 320x480x16. + */ + if(xf86ReturnOptValBool(pSiS->Options, OPTION_DSTN, FALSE)) { + pSiS->DSTN = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "SiS 550 DSTN/FSTN enabled\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "SiS 550 DSTN/FSTN disabled\n"); + } + } + + /* TW: PanelDelayCompensation (300/310/325 series only) + * This might be required if the LCD panel shows "small waves". + * The parameter is an integer, usually either 4, 32 or 24. + * Why this option? Simply because SiS did poor BIOS design. + * The PDC value depends on the very LCD panel used in a + * particular machine. For most panels, the driver is able + * to detect the correct value. However, some panels require + * a different setting. The value given must be within the mask 0x3c. + */ + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + if(xf86GetOptValInteger(pSiS->Options, OPTION_PDC, &pSiS->PDC)) { + if(pSiS->PDC & ~0x3c) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Illegal PanelDelayCompensation value\n"); + pSiS->PDC = -1; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Panel delay compensation shall be %d\n", + pSiS->PDC); + } + } + } + + /* TW: TVStandard (300/310/325 series and 6326 w/ TV only) + * This option is for overriding the autodetection of + * the BIOS option for PAL / NTSC + */ + if((pSiS->VGAEngine == SIS_300_VGA) || + (pSiS->VGAEngine == SIS_315_VGA) || + ((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV))) { + strptr = (char *)xf86GetOptValString(pSiS->Options, OPTION_TVSTANDARD); + if(strptr != NULL) { + if((!strcmp(strptr,"PAL")) || (!strcmp(strptr,"pal"))) + pSiS->OptTVStand = 1; + else if((!strcmp(strptr,"PALM")) || (!strcmp(strptr,"palm"))) { + pSiS->OptTVStand = 1; + pSiS->NonDefaultPAL = 1; + } else if((!strcmp(strptr,"PALN")) || (!strcmp(strptr,"paln"))) { + pSiS->OptTVStand = 1; + pSiS->NonDefaultPAL = 0; + } else if((!strcmp(strptr,"NTSC")) || (!strcmp(strptr,"ntsc"))) + pSiS->OptTVStand = 0; + else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\"%s\" is not a valid parameter for Option \"TVStandard\"\n", strptr); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid options are \"PAL\", \"PALM\", \"PALN\" or \"NTSC\"\n"); + } + + if(pSiS->OptTVStand != -1) { + if(pSiS->Chipset == PCI_CHIP_SIS6326) { + pSiS->NonDefaultPAL = -1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Standard shall be %s\n", + pSiS->OptTVStand ? "PAL" : "NTSC"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Standard shall be %s\n", + (pSiS->OptTVStand ? + ( (pSiS->NonDefaultPAL == -1) ? "PAL" : + ((pSiS->NonDefaultPAL) ? "PALM" : "PALN") ) + : "NTSC")); + } + } + } + } + + /* TW: TVOverscan (300/310/325 series only) + * This option is for overriding the BIOS option for + * TV Overscan. Some BIOS don't even have such an option. + * This is only effective on LVDS+CHRONTEL 70xx systems. + */ + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + Bool val; + if(xf86GetOptValBool(pSiS->Options, OPTION_CHTVOVERSCAN, &val)) { + if(val) pSiS->OptTVOver = 1; + else pSiS->OptTVOver = 0; + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Chrontel: TV overscan shall be %s\n", + val ? "enabled":"disabled"); + } + if(xf86GetOptValBool(pSiS->Options, OPTION_CHTVSOVERSCAN, &pSiS->OptTVSOver)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Chrontel: TV super overscan shall be %s\n", + pSiS->OptTVSOver ? "enabled":"disabled"); + } + } + + /* TW: UseROMData (300/310/325 series only) + * This option is enabling/disabling usage of some machine + * specific data from the BIOS ROM. This option can - and + * should - be used in case the driver makes problems + * because SiS changed the location of this data. + * TW: NoOEM (300/310/325 series only) + * The driver contains quite a lot data for OEM LCD panels + * and TV connector specifics which override the defaults. + * If this data is incorrect, the TV may lose color and + * the LCD panel might show some strange effects. Use this + * option to disable the usage of this data. + */ + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + Bool val; + if(xf86GetOptValBool(pSiS->Options, OPTION_USEROMDATA, &val)) { + if(val) pSiS->OptROMUsage = 1; + else pSiS->OptROMUsage = 0; + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Video ROM data usage shall be %s\n", + val ? "enabled":"disabled"); + } + if(xf86GetOptValBool(pSiS->Options, OPTION_USEOEM, &val)) { + if(val) pSiS->OptUseOEM = 1; + else pSiS->OptUseOEM = 0; + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Internal LCD/TV OEM data usage shall be %s\n", + val ? "enabled":"disabled"); + } + pSiS->sbiosn = NULL; + strptr = (char *)xf86GetOptValString(pSiS->Options, OPTION_SBIOSN); + if(strptr != NULL) { + pSiS->sbiosn = xalloc(strlen(strptr)+1); + if(pSiS->sbiosn) strcpy(pSiS->sbiosn, strptr); + } + } + + /* TW: NoInternalModes (300/310/325 series only) + * Since the mode switching code for these chipsets is a + * Asm-to-C translation of BIOS code, we only have timings + * for a pre-defined number of modes. The default behavior + * is to replace XFree's default modes with a mode list + * generated out of the known and supported modes. Use + * this option to disable this. However, even if using + * out built-in mode list will NOT make it possible to + * use modelines. + */ + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + from = X_DEFAULT; + if(xf86GetOptValBool(pSiS->Options, OPTION_NOINTERNALMODES, &pSiS->noInternalModes)) + from = X_CONFIG; + + xf86DrvMsg(pScrn->scrnIndex, from, "Usage of built-in modes is %s\n", + pSiS->noInternalModes ? "disabled":"enabled"); + } + + /* TW: Various parameters for TV output via SiS bridge, Chrontel or SiS6326 */ + if((pSiS->VGAEngine == SIS_300_VGA) || (pSiS->VGAEngine == SIS_315_VGA)) { + int tmp = 0; + xf86GetOptValInteger(pSiS->Options, OPTION_CHTVLUMABANDWIDTHCVBS, + &pSiS->chtvlumabandwidthcvbs); + xf86GetOptValInteger(pSiS->Options, OPTION_CHTVLUMABANDWIDTHSVIDEO, + &pSiS->chtvlumabandwidthsvideo); + xf86GetOptValInteger(pSiS->Options, OPTION_CHTVLUMAFLICKERFILTER, + &pSiS->chtvlumaflickerfilter); + xf86GetOptValInteger(pSiS->Options, OPTION_CHTVCHROMABANDWIDTH, + &pSiS->chtvchromabandwidth); + xf86GetOptValInteger(pSiS->Options, OPTION_CHTVCHROMAFLICKERFILTER, + &pSiS->chtvchromaflickerfilter); + xf86GetOptValBool(pSiS->Options, OPTION_CHTVCVBSCOLOR, + &pSiS->chtvcvbscolor); + xf86GetOptValInteger(pSiS->Options, OPTION_CHTVTEXTENHANCE, + &pSiS->chtvtextenhance); + xf86GetOptValInteger(pSiS->Options, OPTION_CHTVCONTRAST, + &pSiS->chtvcontrast); + xf86GetOptValInteger(pSiS->Options, OPTION_SISTVEDGEENHANCE, + &pSiS->sistvedgeenhance); + xf86GetOptValInteger(pSiS->Options, OPTION_SISTVANTIFLICKER, + &pSiS->sistvantiflicker); + xf86GetOptValInteger(pSiS->Options, OPTION_SISTVSATURATION, + &pSiS->sistvsaturation); + xf86GetOptValInteger(pSiS->Options, OPTION_TVXPOSOFFSET, + &pSiS->tvxpos); + xf86GetOptValInteger(pSiS->Options, OPTION_TVYPOSOFFSET, + &pSiS->tvypos); + if(pSiS->tvxpos > 32) { pSiS->tvxpos = 32; tmp = 1; } + if(pSiS->tvxpos < -32) { pSiS->tvxpos = -32; tmp = 1; } + if(pSiS->tvypos > 32) { pSiS->tvypos = 32; tmp = 1; } + if(pSiS->tvypos < -32) { pSiS->tvypos = -32; tmp = 1; } + if(tmp) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Illegal TV x or y offset. Range is from -32 to 32\n"); + } + if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { + int tmp = 0; + strptr = (char *)xf86GetOptValString(pSiS->Options, OPTION_SIS6326ANTIFLICKER); + if (strptr != NULL) { + if((!strcmp(strptr,"OFF")) || (!strcmp(strptr,"off"))) + pSiS->sis6326antiflicker = 0; + else if((!strcmp(strptr,"LOW")) || (!strcmp(strptr,"low"))) + pSiS->sis6326antiflicker = 1; + else if((!strcmp(strptr,"MED")) || (!strcmp(strptr,"med"))) + pSiS->sis6326antiflicker = 2; + else if((!strcmp(strptr,"HIGH")) || (!strcmp(strptr,"high"))) + pSiS->sis6326antiflicker = 3; + else if((!strcmp(strptr,"ADAPTIVE")) || (!strcmp(strptr,"adaptive"))) + pSiS->sis6326antiflicker = 4; + else { + pSiS->sis6326antiflicker = -1; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\"%s\" is not a valid parameter for Option \"SIS6326TVAntiFlicker\"\n", strptr); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid parameters are \"OFF\", \"LOW\", \"MED\", \"HIGH\" or \"ADAPTIVE\"\n"); + } + } + xf86GetOptValBool(pSiS->Options, OPTION_SIS6326ENABLEYFILTER, + &pSiS->sis6326enableyfilter); + xf86GetOptValBool(pSiS->Options, OPTION_SIS6326YFILTERSTRONG, + &pSiS->sis6326yfilterstrong); + xf86GetOptValInteger(pSiS->Options, OPTION_TVXPOSOFFSET, + &pSiS->tvxpos); + xf86GetOptValInteger(pSiS->Options, OPTION_TVYPOSOFFSET, + &pSiS->tvypos); + if(pSiS->tvxpos > 16) { pSiS->tvxpos = 16; tmp = 1; } + if(pSiS->tvxpos < -16) { pSiS->tvxpos = -16; tmp = 1; } + if(pSiS->tvypos > 16) { pSiS->tvypos = 16; tmp = 1; } + if(pSiS->tvypos < -16) { pSiS->tvypos = -16; tmp = 1; } + if(tmp) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Illegal TV x or y offset. Range is from -16 to 16\n"); + } +} + +const OptionInfoRec * +SISAvailableOptions(int chipid, int busid) +{ + return SISOptions; +} diff --git a/src/sis_regs.h b/src/sis_regs.h new file mode 100644 index 0000000..928f1dc --- /dev/null +++ b/src/sis_regs.h @@ -0,0 +1,587 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_regs.h,v 1.17 2003/01/29 15:42:17 eich Exp $ */ +/* + * Copyright 1998,1999 by Alan Hourihane, Wigan, England. + * Parts Copyright 2001, 2002 by Thomas Winischhofer, Vienna, Austria. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holder not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The copyright holder makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE PROVIDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE PROVIDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk + * Mike Chapman <mike@paranoia.com>, + * Juanjo Santamarta <santamarta@ctv.es>, + * Mitani Hiroshi <hmitani@drl.mei.co.jp> + * David Thomas <davtom@dream.org.uk> + * + * Thomas Winischhofer <thomas@winischhofer.net> + * - 310/325 series (315/550/650/651/740/M650) support + * - (possibly incomplete) Xabre (SiS330) support + * - new mode switching code for 300, 310/325 and 330 series + * - many fixes for 300/540/630/730 chipsets, + * - many fixes for 5597/5598, 6326 and 530/620 chipsets, + * - VESA mode switching (deprecated), + * - extended CRT2/video bridge handling support, + * - dual head support on 300, 310/325 and 330 series + * - 650/LVDS (up to 1400x1050), 650/Chrontel 701x support + * - 30xB/30xLV/30xLVX video bridge support (300, 310/325, 330 series) + * - Xv support for 5597/5598, 6326, 530/620 and 310/325 series + * - video overlay enhancements for 300 series + * - TV and hi-res support for the 6326 + * - etc. + */ + +/* For general use --------------------------------------------------------------- */ + +#define inSISREG(base) inb(base) +#define outSISREG(base,val) outb(base,val) +#define orSISREG(base,val) do { \ + unsigned char __Temp = inb(base); \ + outSISREG(base, __Temp | (val)); \ + } while (0) +#define andSISREG(base,val) do { \ + unsigned char __Temp = inb(base); \ + outSISREG(base, __Temp & (val)); \ + } while (0) + +#define inSISIDXREG(base,idx,var) do { \ + outb(base,idx); var=inb((base)+1); \ + } while (0) +#define outSISIDXREG(base,idx,val) do { \ + outb(base,idx); outb((base)+1,val); \ + } while (0) +#define orSISIDXREG(base,idx,val) do { \ + unsigned char __Temp; \ + outb(base,idx); \ + __Temp = inb((base)+1)|(val); \ + outSISIDXREG(base,idx,__Temp); \ + } while (0) +#define andSISIDXREG(base,idx,and) do { \ + unsigned char __Temp; \ + outb(base,idx); \ + __Temp = inb((base)+1)&(and); \ + outSISIDXREG(base,idx,__Temp); \ + } while (0) +#define setSISIDXREG(base,idx,and,or) do { \ + unsigned char __Temp; \ + outb(base,idx); \ + __Temp = (inb((base)+1)&(and))|(or); \ + outSISIDXREG(base,idx,__Temp); \ + } while (0) + +#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 SETBITS(val,mask) ((val) << (0?mask)) +#define SETBIT(n) (1<<(n)) + +#define GETBITSTR(val,from,to) ((GETBITS(val,from)) << (0?to)) +#define SETVARBITS(var,val,from,to) (((var)&(~(GENMASK(to)))) | \ + GETBITSTR(val,from,to)) +#define GETVAR8(var) ((var)&0xFF) +#define SETVAR8(var,val) (var) = GETVAR8(val) + +/* #define VGA_RELIO_BASE 0x380 */ + +#define AROFFSET 0x40 /* VGA_ATTR_INDEX - VGA_RELIO_BASE */ +#define ARROFFSET 0x41 /* VGA_ATTR_DATA_R - VGA_RELIO_BASE */ +#define GROFFSET 0x4e /* VGA_GRAPH_INDEX - VGA_RELIO_BASE */ +#define SROFFSET 0x44 /* VGA_SEQ_INDEX - VGA_RELIO_BASE */ +#define CROFFSET 0x54 /* VGA_CRTC_INDEX_OFFSET + VGA_IOBASE_COLOR - VGA_RELIO_BASE */ +#define MISCROFFSET 0x4c /* VGA_MISC_OUT_R - VGA_RELIO_BASE */ +#define MISCWOFFSET 0x42 /* VGA_MISC_OUT_W - VGA_RELIO_BASE */ +#define INPUTSTATOFFSET 0x5A +#define PART1OFFSET 0x04 +#define PART2OFFSET 0x10 +#define PART3OFFSET 0x12 +#define PART4OFFSET 0x14 +#define PART5OFFSET 0x16 +#define VIDEOOFFSET 0x02 +#define COLREGOFFSET 0x48 + +#define SISAR pSiS->RelIO + AROFFSET +#define SISARR pSiS->RelIO + ARROFFSET +#define SISGR pSiS->RelIO + GROFFSET +#define SISSR pSiS->RelIO + SROFFSET +#define SISCR pSiS->RelIO + CROFFSET +#define SISMISCR pSiS->RelIO + MISCROFFSET +#define SISMISCW pSiS->RelIO + MISCWOFFSET +#define SISINPSTAT pSiS->RelIO + INPUTSTATOFFSET +#define SISPART1 pSiS->RelIO + PART1OFFSET +#define SISPART2 pSiS->RelIO + PART2OFFSET +#define SISPART3 pSiS->RelIO + PART3OFFSET +#define SISPART4 pSiS->RelIO + PART4OFFSET +#define SISPART5 pSiS->RelIO + PART5OFFSET +#define SISVID pSiS->RelIO + VIDEOOFFSET +#define SISCOLIDX pSiS->RelIO + COLREGOFFSET +#define SISCOLDATA pSiS->RelIO + COLREGOFFSET + 1 +#define SISCOL2IDX SISPART5 +#define SISCOL2DATA SISPART5 + 1 + + +#define vc_index_offset 0x00 /* Video capture - unused */ +#define vc_data_offset 0x01 +#define vi_index_offset VIDEOOFFSET +#define vi_data_offset (VIDEOOFFSET + 1) +#define crt2_index_offset PART1OFFSET +#define crt2_port_offset (PART1OFFSET + 1) +#define sr_index_offset SROFFSET +#define sr_data_offset (SROFFSET + 1) +#define cr_index_offset CROFFSET +#define cr_data_offset (CROFFSET + 1) +#define input_stat INPUTSTATOFFSET + +/* For old chipsets (5597/5598, 6326, 530/620) ------------ */ +/* SR (3C4) */ +#define BankReg 0x06 +#define ClockReg 0x07 +#define CPUThreshold 0x08 +#define CRTThreshold 0x09 +#define CRTCOff 0x0A +#define DualBanks 0x0B +#define MMIOEnable 0x0B +#define RAMSize 0x0C +#define Mode64 0x0C +#define ExtConfStatus1 0x0E +#define ClockBase 0x13 +#define LinearAdd0 0x20 +#define LinearAdd1 0x21 +#define GraphEng 0x27 +#define MemClock0 0x28 +#define MemClock1 0x29 +#define XR2A 0x2A +#define XR2B 0x2B +#define TurboQueueBase 0x2C +#define FBSize 0x2F +#define ExtMiscCont5 0x34 +#define ExtMiscCont9 0x3C + +/* 3x4 */ +#define Offset 0x13 + +/* SiS Registers for 300, 540, 630, 730, 315, 550, 650, 740 ---------------------- */ + +/* VGA standard register */ +#define Index_SR_Graphic_Mode 0x06 +#define Index_SR_RAMDAC_Ctrl 0x07 +#define Index_SR_Threshold_Ctrl1 0x08 +#define Index_SR_Threshold_Ctrl2 0x09 +#define Index_SR_Misc_Ctrl 0x0F +#define Index_SR_DDC 0x11 +#define Index_SR_Feature_Connector_Ctrl 0x12 +#define Index_SR_DRAM_Sizing 0x14 +#define Index_SR_DRAM_State_Machine_Ctrl 0x15 +#define Index_SR_AGP_PCI_State_Machine 0x21 +#define Index_SR_Internal_MCLK0 0x28 +#define Index_SR_Internal_MCLK1 0x29 +#define Index_SR_Internal_DCLK1 0x2B +#define Index_SR_Internal_DCLK2 0x2C +#define Index_SR_Internal_DCLK3 0x2D +#define Index_SR_Ext_Clock_Sel 0x32 +#define Index_SR_Int_Status 0x34 +#define Index_SR_Int_Enable 0x35 +#define Index_SR_Int_Reset 0x36 +#define Index_SR_Power_On_Trap 0x38 +#define Index_SR_Power_On_Trap2 0x39 +#define Index_SR_Power_On_Trap3 0x3A + +/* video registers (300/630/730/315/550/650/740 only) */ +#define Index_VI_Passwd 0x00 + +/* Video overlay horizontal start/end, unit=screen pixels */ +#define Index_VI_Win_Hor_Disp_Start_Low 0x01 +#define Index_VI_Win_Hor_Disp_End_Low 0x02 +#define Index_VI_Win_Hor_Over 0x03 /* Overflow */ + +/* Video overlay vertical start/end, unit=screen pixels */ +#define Index_VI_Win_Ver_Disp_Start_Low 0x04 +#define Index_VI_Win_Ver_Disp_End_Low 0x05 +#define Index_VI_Win_Ver_Over 0x06 /* Overflow */ + +/* Y Plane (4:2:0) or YUV (4:2:2) buffer start address, unit=word */ +#define Index_VI_Disp_Y_Buf_Start_Low 0x07 +#define Index_VI_Disp_Y_Buf_Start_Middle 0x08 +#define Index_VI_Disp_Y_Buf_Start_High 0x09 + +/* U Plane (4:2:0) buffer start address, unit=word */ +#define Index_VI_U_Buf_Start_Low 0x0A +#define Index_VI_U_Buf_Start_Middle 0x0B +#define Index_VI_U_Buf_Start_High 0x0C + +/* V Plane (4:2:0) buffer start address, unit=word */ +#define Index_VI_V_Buf_Start_Low 0x0D +#define Index_VI_V_Buf_Start_Middle 0x0E +#define Index_VI_V_Buf_Start_High 0x0F + +/* Pitch for Y, UV Planes, unit=word */ +#define Index_VI_Disp_Y_Buf_Pitch_Low 0x10 +#define Index_VI_Disp_UV_Buf_Pitch_Low 0x11 +#define Index_VI_Disp_Y_UV_Buf_Pitch_Middle 0x12 + +/* What is this ? */ +#define Index_VI_Disp_Y_Buf_Preset_Low 0x13 +#define Index_VI_Disp_Y_Buf_Preset_Middle 0x14 + +#define Index_VI_UV_Buf_Preset_Low 0x15 +#define Index_VI_UV_Buf_Preset_Middle 0x16 +#define Index_VI_Disp_Y_UV_Buf_Preset_High 0x17 + +/* Scaling control registers */ +#define Index_VI_Hor_Post_Up_Scale_Low 0x18 +#define Index_VI_Hor_Post_Up_Scale_High 0x19 +#define Index_VI_Ver_Up_Scale_Low 0x1A +#define Index_VI_Ver_Up_Scale_High 0x1B +#define Index_VI_Scale_Control 0x1C + +/* Playback line buffer control */ +#define Index_VI_Play_Threshold_Low 0x1D +#define Index_VI_Play_Threshold_High 0x1E +#define Index_VI_Line_Buffer_Size 0x1F + +/* Destination color key */ +#define Index_VI_Overlay_ColorKey_Red_Min 0x20 +#define Index_VI_Overlay_ColorKey_Green_Min 0x21 +#define Index_VI_Overlay_ColorKey_Blue_Min 0x22 +#define Index_VI_Overlay_ColorKey_Red_Max 0x23 +#define Index_VI_Overlay_ColorKey_Green_Max 0x24 +#define Index_VI_Overlay_ColorKey_Blue_Max 0x25 + +/* Source color key, YUV color space */ +#define Index_VI_Overlay_ChromaKey_Red_Y_Min 0x26 +#define Index_VI_Overlay_ChromaKey_Green_U_Min 0x27 +#define Index_VI_Overlay_ChromaKey_Blue_V_Min 0x28 +#define Index_VI_Overlay_ChromaKey_Red_Y_Max 0x29 +#define Index_VI_Overlay_ChromaKey_Green_U_Max 0x2A +#define Index_VI_Overlay_ChromaKey_Blue_V_Max 0x2B + +/* Contrast enhancement and brightness control */ +#define Index_VI_Contrast_Factor 0x2C /* obviously unused/undefined */ +#define Index_VI_Brightness 0x2D +#define Index_VI_Contrast_Enh_Ctrl 0x2E + +#define Index_VI_Key_Overlay_OP 0x2F + +#define Index_VI_Control_Misc0 0x30 +#define Index_VI_Control_Misc1 0x31 +#define Index_VI_Control_Misc2 0x32 + +/* TW: Subpicture registers */ +#define Index_VI_SubPict_Buf_Start_Low 0x33 +#define Index_VI_SubPict_Buf_Start_Middle 0x34 +#define Index_VI_SubPict_Buf_Start_High 0x35 + +/* TW: What is this ? */ +#define Index_VI_SubPict_Buf_Preset_Low 0x36 +#define Index_VI_SubPict_Buf_Preset_Middle 0x37 + +/* TW: Subpicture pitch, unit=16 bytes */ +#define Index_VI_SubPict_Buf_Pitch 0x38 + +/* TW: Subpicture scaling control */ +#define Index_VI_SubPict_Hor_Scale_Low 0x39 +#define Index_VI_SubPict_Hor_Scale_High 0x3A +#define Index_VI_SubPict_Vert_Scale_Low 0x3B +#define Index_VI_SubPict_Vert_Scale_High 0x3C + +#define Index_VI_SubPict_Scale_Control 0x3D +/* (0x40 = enable/disable subpicture) */ + +/* TW: Subpicture line buffer control */ +#define Index_VI_SubPict_Threshold 0x3E + +/* TW: What is this? */ +#define Index_VI_FIFO_Max 0x3F + +/* TW: Subpicture palette; 16 colors, total 32 bytes address space */ +#define Index_VI_SubPict_Pal_Base_Low 0x40 +#define Index_VI_SubPict_Pal_Base_High 0x41 + +/* I wish I knew how to use these ... */ +#define Index_MPEG_Read_Ctrl0 0x60 /* MPEG auto flip */ +#define Index_MPEG_Read_Ctrl1 0x61 /* MPEG auto flip */ +#define Index_MPEG_Read_Ctrl2 0x62 /* MPEG auto flip */ +#define Index_MPEG_Read_Ctrl3 0x63 /* MPEG auto flip */ + +/* TW: MPEG AutoFlip scale */ +#define Index_MPEG_Ver_Up_Scale_Low 0x64 +#define Index_MPEG_Ver_Up_Scale_High 0x65 + +#define Index_MPEG_Y_Buf_Preset_Low 0x66 +#define Index_MPEG_Y_Buf_Preset_Middle 0x67 +#define Index_MPEG_UV_Buf_Preset_Low 0x68 +#define Index_MPEG_UV_Buf_Preset_Middle 0x69 +#define Index_MPEG_Y_UV_Buf_Preset_High 0x6A + +/* TW: The following registers only exist on the 310/325 series */ + +/* TW: Bit 16:24 of Y_U_V buf start address (?) */ +#define Index_VI_Y_Buf_Start_Over 0x6B +#define Index_VI_U_Buf_Start_Over 0x6C +#define Index_VI_V_Buf_Start_Over 0x6D + +#define Index_VI_Disp_Y_Buf_Pitch_High 0x6E +#define Index_VI_Disp_UV_Buf_Pitch_High 0x6F + +/* Hue and saturation */ +#define Index_VI_Hue 0x70 +#define Index_VI_Saturation 0x71 + +#define Index_VI_SubPict_Start_Over 0x72 +#define Index_VI_SubPict_Buf_Pitch_High 0x73 + +#define Index_VI_Control_Misc3 0x74 + + +/* TW: Bits (and helpers) for Index_VI_Control_Misc0 */ +#define VI_Misc0_Enable_Overlay 0x02 +#define VI_Misc0_420_Plane_Enable 0x04 /* Select Plane or Packed mode */ +#define VI_Misc0_422_Enable 0x20 /* Select 422 or 411 mode */ +#define VI_Misc0_Fmt_YVU420P 0x0C /* YUV420 Planar (I420, YV12) */ +#define VI_Misc0_Fmt_YUYV 0x28 /* YUYV Packed (YUY2) */ +#define VI_Misc0_Fmt_UYVY 0x08 /* (UYVY) */ + +/* TW: Bits for Index_VI_Control_Misc1 */ +/* #define VI_Misc1_? 0x01 */ +#define VI_Misc1_BOB_Enable 0x02 +#define VI_Misc1_Line_Merge 0x04 +#define VI_Misc1_Field_Mode 0x08 +/* #define VI_Misc1_? 0x10 */ +#define VI_Misc1_Non_Interleave 0x20 /* 300 series only? */ +#define VI_Misc1_Buf_Addr_Lock 0x20 /* 310 series only? */ +/* #define VI_Misc1_? 0x40 */ +/* #define VI_Misc1_? 0x80 */ + +/* TW: Bits for Index_VI_Control_Misc2 */ +#define VI_Misc2_Select_Video2 0x01 +#define VI_Misc2_Video2_On_Top 0x02 +/* #define VI_Misc2_? 0x04 */ +#define VI_Misc2_Vertical_Interpol 0x08 +#define VI_Misc2_Dual_Line_Merge 0x10 +#define VI_Misc2_All_Line_Merge 0x20 /* 310 series only? */ +#define VI_Misc2_Auto_Flip_Enable 0x40 /* 300 series only? */ +#define VI_Misc2_Video_Reg_Write_Enable 0x80 /* 310 series only? */ + +/* TW: Bits for Index_VI_Control_Misc3 */ +#define VI_Misc3_Submit_Video_1 0x01 /* AKA "address ready" */ +#define VI_Misc3_Submit_Video_2 0x02 /* AKA "address ready" */ +#define VI_Misc3_Submit_SubPict 0x04 /* AKA "address ready" */ + +/* TW: Values for Index_VI_Key_Overlay_OP (0x2F) */ +#define VI_ROP_Never 0x00 +#define VI_ROP_DestKey 0x03 +#define VI_ROP_Always 0x0F + + +/* video registers (6326 and 530/620) --------------- */ +#define Index_VI6326_Passwd 0x80 + +/* Video overlay horizontal start/end, unit=screen pixels */ +#define Index_VI6326_Win_Hor_Disp_Start_Low 0x81 +#define Index_VI6326_Win_Hor_Disp_End_Low 0x82 +#define Index_VI6326_Win_Hor_Over 0x83 /* Overflow */ + +/* Video overlay vertical start/end, unit=screen pixels */ +#define Index_VI6326_Win_Ver_Disp_Start_Low 0x84 +#define Index_VI6326_Win_Ver_Disp_End_Low 0x85 +#define Index_VI6326_Win_Ver_Over 0x86 /* Overflow */ + +/* Y Plane (4:2:0) or YUV (4:2:2) buffer start address, unit=dword */ +#define Index_VI6326_Disp_Y_Buf_Start_Low 0x8A +#define Index_VI6326_Disp_Y_Buf_Start_Middle 0x8B +#define Index_VI6326_Disp_Capt_Y_Buf_Start_High 0x89 /* 6326: 7:4 display, 3:0 capture */ + /* 530/620: 7:3 display. 2:0 reserved */ +/* End address of Y plane (in 16k unit) - 6326 ONLY */ +#define Index_VI6326_Disp_Y_End 0x8D + +/* U Plane (4:2:0) buffer start address, unit=dword */ +#define Index_VI6326_U_Buf_Start_Low 0xB7 +#define Index_VI6326_U_Buf_Start_Middle 0xB8 + +/* V Plane (4:2:0) buffer start address, unit=dword */ +#define Index_VI6326_V_Buf_Start_Low 0xBA +#define Index_VI6326_V_Buf_Start_Middle 0xBB + +/* U/V plane start address overflow bits 19:16 */ +#define Index_VI6326_UV_Buf_Start_High 0xB9 + +/* Pitch for Y, UV Planes, unit=dword(6326 & 530/620) */ +#define Index_VI6326_Disp_Y_Buf_Pitch_Low 0x8C /* 7:0 */ +#define Index_VI6326_Disp_Y_Buf_Pitch_High 0x8E /* 11:8 (3:0 here) */ + +#define Index_VI6326_Disp_UV_Buf_Pitch_Low 0xBC /* 7:0 */ +#define Index_VI6326_Disp_UV_Buf_Pitch_High 0xBD /* 11:8 (3:0 here) */ + +/* Scaling control registers */ +#define Index_VI6326_Hor_Scale 0x92 +#define Index_VI6326_Hor_Scale_Integer 0x94 +#define Index_VI6326_Ver_Scale 0x93 + +/* Playback line buffer control */ +#define Index_VI6326_Play_Threshold_Low 0x9E +#define Index_VI6326_Play_Threshold_High 0x9F +#define Index_VI6326_Line_Buffer_Size 0xA0 /* 530 & 6326: quad-word */ + +/* Destination color key */ +#define Index_VI6326_Overlay_ColorKey_Red_Min 0x97 +#define Index_VI6326_Overlay_ColorKey_Green_Min 0x96 +#define Index_VI6326_Overlay_ColorKey_Blue_Min 0x95 +#define Index_VI6326_Overlay_ColorKey_Red_Max 0xA3 +#define Index_VI6326_Overlay_ColorKey_Green_Max 0xA2 +#define Index_VI6326_Overlay_ColorKey_Blue_Max 0xA1 + +/* Source color key */ +#define Index_VI6326_Overlay_ChromaKey_Red_Y_Min 0x9C +#define Index_VI6326_Overlay_ChromaKey_Green_U_Min 0x9B +#define Index_VI6326_Overlay_ChromaKey_Blue_V_Min 0x9A +#define Index_VI6326_Overlay_ChromaKey_Red_Y_Max 0xA6 +#define Index_VI6326_Overlay_ChromaKey_Green_U_Max 0xA5 +#define Index_VI6326_Overlay_ChromaKey_Blue_V_Max 0xA4 + +/* Contrast enhancement and brightness control */ +#define Index_VI6326_Contrast_Factor 0xB3 +#define Index_VI6326_Brightness 0xB4 +#define Index_VI6326_Contrast_Enh_Ctrl 0xB5 + +/* Alpha (ALL 6326 only?) */ +#define Index_VI6326_AlphaGraph 0xA7 +#define Index_VI6326_AlphaVideo 0xA8 + +#define Index_VI6326_Key_Overlay_OP 0xA9 + +#define Index_VI6326_Control_Misc0 0x98 +#define Index_VI6326_Control_Misc1 0x99 /* (Datasheet: 6326 ONLY - not correct?) */ +#define Index_VI6326_Control_Misc3 0x9D +#define Index_VI6326_Control_Misc4 0xB6 +#define Index_VI6326_VideoFormatSelect Index_VI6326_Ver_Scale +#define Index_VI6326_Control_Misc5 0xBE /* (Datasheet: 530/620 ONLY - not correct) */ +#define Index_VI6326_Control_Misc6 0xB2 /* 5597 and 6326 only! */ + +/* TW: What is this? not a register, obviously */ +#define Index_VI6326_FIFO_Max 0x3F + +/* TW: Bits (and helpers) for Index_VI6326_Control_Misc0 */ +#define VI6326_Misc0_EnableCapture 0x01 /* 1 = on, 0 = off (6326 only) */ +#define VI6326_Misc0_EnableOverlay 0x02 /* 1 = on, 0 = off */ +#define VI6326_Misc0_VideoOnly 0x10 /* 1 = video only, 0 = gfx + video */ +#define VI6326_Misc0_CaptureInterlace 0x20 /* 1 = capture data is interlace, 0 = not (6326 only) */ +#define VI6326_Misc0_VideoFormat 0x40 /* 1 = YUV, 0 = RGB */ +#define VI6326_Misc0_FieldPolarity 0x80 /* 1 = *Odd / Even, 0 = Odd / *Even (6326 only) */ + +/* TW: Bits for Index_VI6326_Control_Misc1 (ALL 6326 ONLY) */ +#define VI6326_Misc1_EnableYUVCapture 0x01 /* 0 = RGB, 1 = YUV */ +#define VI6326_Misc1_EnableCaptureDithering 0x02 /* 0 = disable, 1 = enable */ +#define VI6326_Misc1_CaptureFormat555 0x04 /* 1 = 555, 0 = 565 */ +#define VI6326_Misc1_FilterModeMask 0x38 +#define VI6326_Misc1_FilterMode0 0x00 /* 1 */ +#define VI6326_Misc1_FilterMode1 0x08 /* 1/8(1+3z^-1+3z^-2+z^-3)*/ +#define VI6326_Misc1_FilterMode2 0x10 /* 1/4(1+2z^-1+z^-2) */ +#define VI6326_Misc1_FilterMode3 0x18 /* 1/2(1+z^-1) */ +#define VI6326_Misc1_FilterMode4 0x20 /* 1/8(1+2z^-1+2z^-2+2z^-3+z^-4) */ +#define VI6326_Misc1_EnableVBSyncIRQ 0x40 /* 1 = Enable IRQ on vertical blank */ +#define VI6326_Misc1_ClearVBSyncIRQ 0x80 /* Clear pending irq */ + +/* TW: Bits for Index_VI6326_Control_Misc3 */ +#define VI6326_Misc3_UVCaptureFormat 0x01 /* 1 = 2's complement, 0 = CCIR 601 (6326 only) */ +#define VI6326_Misc3_UVOverlayFormat 0x02 /* 1 = 2's complement, 0 = CCIR 601 */ +#define VI6326_Misc3_ChromaKeyFormat 0x04 /* 1 = YUV, 0 = RGB */ +#define VI6326_Misc3_VMIAccess 0x08 /* 1 = enable, 0 = disable (6326 only) */ +#define VI6326_Misc3_VMIEnable 0x10 /* 1 = enable, 0 = disable (6326 only) */ +#define VI6326_Misc3_VMIIRQ 0x20 /* 1 = enable, 0 = disable (6326 only) */ +#define VI6326_Misc3_BT819A 0x40 /* 1 = enable, 0 = disable (6326 only) */ +#define VI6326_Misc3_SystemMemFB 0x80 /* 1 = enable, 0 = disable (6326 only) */ + +/* TW: Bits for Index_VI6326_Control_Misc4 */ +#define VI6326_Misc4_CPUVideoFormatMask 0x03 +#define VI6326_Misc4_CPUVideoFormatRGB555 0x00 +#define VI6326_Misc4_CPUVideoFormatYUV422 0x01 +#define VI6326_Misc4_CPUVideoFormatRGB565 0x02 +#define VI6326_Misc4_EnableYUV420 0x04 /* 1 = enable, 0 = disable */ +/** #define WHATISTHIS 0x40 */ + +/* TW: Bits for Index_VI6326_Control_Misc5 (all 530/620 only) */ +#define VI6326_Misc5_LineBufferMerge 0x10 /* 0 = disable, 1=enable */ +#define VI6326_Misc5_VPlaneBit20 0x04 +#define VI6326_Misc5_UPlaneBit20 0x02 + +/* TW: Bits for Index_VI6326_Control_Misc6 (5597 and 6326 only) */ +#define VI6326_Misc6_Decimation 0x80 /* 0=disable 1=enable video decimation */ + +/* Video format selection */ +#define VI_6326_VideoUYVY422 0x00 +#define VI_6326_VideoVYUY422 0x40 +#define VI_6326_VideoYUYV422 0x80 +#define VI_6326_VideoYVYU422 0xC0 +#define VI_6326_VideoRGB555 0x00 +#define VI_6326_VideoRGB565 0x40 + +/* TW: Values for Index_VI6326_Key_Overlay_OP */ +#define VI6326_ROP_Never 0x00 +#define VI6326_ROP_DestKey 0x03 +#define VI6326_ROP_Always 0x0F + +/* --- end of 6326 video registers ---------------------------------- */ + +/* TW register base (6326 only) */ +#define Index_TV6326_TVOutIndex 0xE0 +#define Index_TV6326_TVOutData 0xE1 + +/* + * CRT_2 function control register --------------------------------- + */ +#define Index_CRT2_FC_CONTROL 0x00 +#define Index_CRT2_FC_SCREEN_HIGH 0x04 +#define Index_CRT2_FC_SCREEN_MID 0x05 +#define Index_CRT2_FC_SCREEN_LOW 0x06 +#define Index_CRT2_FC_ENABLE_WRITE 0x24 +#define Index_CRT2_FC_VR 0x25 +#define Index_CRT2_FC_VCount 0x27 +#define Index_CRT2_FC_VCount1 0x28 + +#define Index_310_CRT2_FC_VR 0x30 /* d[1] = vertical retrace */ +#define Index_310_CRT2_FC_RT 0x33 /* d[7] = retrace in progress */ + +/* video attributes - these should probably be configurable on the fly + * so users with different desktop sizes can keep + * captured data off the desktop + */ +#define _VINWID 704 +#define _VINHGT _VINHGT_NTSC +#define _VINHGT_NTSC 240 +#define _VINHGT_PAL 290 +#define _VIN_WINDOW (704 * 291 * 2) +#define _VBI_WINDOW (704 * 64 * 2) + +#define _VIN_FIELD_EVEN 1 +#define _VIN_FIELD_ODD 2 +#define _VIN_FIELD_BOTH 4 + + +/* i2c registers (TW; not on 300/310/325 series) */ +#define X_INDEXREG 0x14 +#define X_PORTREG 0x15 +#define X_DATA 0x0f +#define I2C_SCL 0x00 +#define I2C_SDA 0x01 +#define I2C_DELAY 10 + +/* mmio registers for video */ +#define REG_PRIM_CRT_COUNTER 0x8514 + +/* TW: MPEG MMIO registers (630 and later) ----------------------------------------- */ + +/* Not public (yet?) */ + diff --git a/src/sis_setup.c b/src/sis_setup.c new file mode 100644 index 0000000..a26d191 --- /dev/null +++ b/src/sis_setup.c @@ -0,0 +1,528 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_setup.c,v 1.9 2003/02/04 02:44:29 dawes Exp $ */ +/* + * Basic hardware and memory detection + * + * Copyright 1998,1999 by Alan Hourihane, Wigan, England. + * Parts Copyright 2001, 2002 by Thomas Winischhofer, Vienna, Austria. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holder not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The copyright holder makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk + * Mike Chapman <mike@paranoia.com>, + * Juanjo Santamarta <santamarta@ctv.es>, + * Mitani Hiroshi <hmitani@drl.mei.co.jp> + * David Thomas <davtom@dream.org.uk>. + * Thomas Winischhofer <thomas@winischhofer.net> + */ + +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "xf86.h" +#include "fb.h" +#include "xf1bpp.h" +#include "xf4bpp.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "xf86Version.h" + +#include "xf86pciBus.h" +#include "xf86cmap.h" + +#include "sis.h" +#include "sis_regs.h" +#include "sis_dac.h" + +#define _XF86DGA_SERVER_ +#include "extensions/xf86dgastr.h" + +#include "globals.h" +#define DPMS_SERVER +#include "extensions/dpms.h" + +static const char *dramTypeStr[] = { + "Fast Page DRAM", + "2 cycle EDO RAM", + "1 cycle EDO RAM", + "SDRAM/SGRAM", + "SDRAM", + "SGRAM", + "ESDRAM", + "DDR RAM", /* for 550/650 */ + "DDR RAM", /* for 550/650 */ + "" }; + +/* TW: MCLK tables for SiS6326 */ +static const int SiS6326MCLKIndex[4][8] = { + { 10, 12, 14, 16, 17, 18, 19, 7 }, /* SGRAM */ + { 4, 6, 8, 10, 11, 12, 13, 3 }, /* Fast Page */ + { 9, 11, 12, 13, 15, 16, 5, 7 }, /* 2 cycle EDO */ + { 10, 12, 14, 16, 17, 18, 19, 7 } /* ? (Not 1 cycle EDO) */ +}; + +static const struct _sis6326mclk { + CARD16 mclk; + unsigned char sr13; + unsigned char sr28; + unsigned char sr29; +} SiS6326MCLK[] = { + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 45, 0, 0x2b, 0x26 }, + { 53, 0, 0x49, 0xe4 }, + { 55, 0, 0x7c, 0xe7 }, + { 56, 0, 0x7c, 0xe7 }, + { 60, 0, 0x42, 0xe3 }, + { 61, 0, 0x21, 0xe1 }, + { 65, 0, 0x5a, 0xe4 }, + { 66, 0, 0x5a, 0xe4 }, + { 70, 0, 0x61, 0xe4 }, + { 75, 0, 0x3e, 0xe2 }, + { 80, 0, 0x42, 0xe2 }, + { 83, 0, 0xb3, 0xc5 }, + { 85, 0, 0x5e, 0xe3 }, + { 90, 0, 0xae, 0xc4 }, + {100, 0, 0x37, 0xe1 }, + {115, 0, 0x78, 0x0e }, + {134, 0, 0x4a, 0xa3 } +}; + +/* For 5597, 6326, 530/620 */ +static void +sisOldSetup(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + int ramsize[8] = { 1, 2, 4, 0, 0, 2, 4, 8}; + int buswidth[8] = {32, 64, 64, 0, 0, 32, 32, 64 }; + int clockTable[4] = { 66, 75, 83, 100 }; + int ramtype[4] = { 5, 0, 1, 3 }; + int config; + int temp, i; + unsigned char sr23, sr33, sr34, sr37; +#if 0 + unsigned char newsr13, newsr28, newsr29; +#endif + pciConfigPtr pdptr, *systemPCIdevices = NULL; + + if(pSiS->Chipset == PCI_CHIP_SIS5597) { + inSISIDXREG(SISSR, FBSize, temp); + pScrn->videoRam = ((temp & 0x07) + 1) * 256; + inSISIDXREG(SISSR, Mode64, temp); + if(temp & 0x06) { + pScrn->videoRam *= 2; + pSiS->BusWidth = 64; + } else pSiS->BusWidth = 32; + } else { + inSISIDXREG(SISSR, RAMSize, temp); + config = ((temp & 0x10) >> 2 ) | ((temp & 0x6) >> 1); + pScrn->videoRam = ramsize[config] * 1024; + pSiS->BusWidth = buswidth[config]; + } + + if(pSiS->Chipset == PCI_CHIP_SIS530) { + + inSISIDXREG(SISSR, 0x0D, temp); + pSiS->Flags &= ~(UMA); + if(temp & 0x01) { + pSiS->Flags |= UMA; /* TW: Shared fb mode */ + inSISIDXREG(SISSR, 0x10, temp); + pSiS->MemClock = clockTable[temp & 0x03] * 1000; + } else pSiS->MemClock = SiSMclk(pSiS); /* TW: Local fb mode */ + + } else if(pSiS->Chipset == PCI_CHIP_SIS6326) { + + inSISIDXREG(SISSR,0x0e,temp); + i = temp & 0x03; + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected DRAM type: %s\n", + dramTypeStr[ramtype[i]]); + + temp = (temp >> 5) & 0x07; + i = SiS6326MCLKIndex[i][temp]; + pSiS->MemClock = SiS6326MCLK[i].mclk; +#if 0 + /* TW: Correct invalid MCLK settings by old BIOSes */ + newsr13 = SiS6326MCLK[i].sr13; + newsr28 = SiS6326MCLK[i].sr28; + newsr29 = SiS6326MCLK[i].sr29; + if((pSiS->ChipRev == 0x92) || + (pSiS->ChipRev == 0xd1) || + (pSiS->ChipRev == 0xd2)) { + if(pSiS->MemClock == 60) { + newsr28 = 0xae; + newsr29 = 0xc4; + } + } +#endif + pSiS->MemClock *= 1000; +#if 0 + inSISIDXREG(SISSR, 0x13, temp); + temp &= 0x80; + temp |= (newsr13 & 0x80); + outSISIDXREG(SISSR,0x13,temp); + outSISIDXREG(SISSR,0x28,newsr28); + outSISIDXREG(SISSR,0x29,newsr29); +#endif + + } else { + + pSiS->MemClock = SiSMclk(pSiS); + + } + + pSiS->Flags &= ~(SYNCDRAM | RAMFLAG); + if(pSiS->oldChipset >= OC_SIS82204) { + inSISIDXREG(SISSR, 0x23, sr23); + inSISIDXREG(SISSR, 0x33, sr33); + inSISIDXREG(SISSR, 0x34, sr34); + if(sr33 & 0x09) { /* 5597: Sync DRAM timing | One cycle EDO ram; */ + pSiS->Flags |= (sr33 & SYNCDRAM); /* 6326: Enable SGRam timing | One cycle EDO ram */ + pSiS->Flags |= RAMFLAG; /* 530: Enable SGRAM timing | reserved (0) */ + } else if(sr23 & 0x20) { /* 5597, 6326: EDO DRAM enabled */ + pSiS->Flags |= SYNCDRAM; /* 530/620: reserved (0) */ + } + } + + pSiS->Flags &= ~(ESS137xPRESENT); + if(pSiS->Chipset == PCI_CHIP_SIS530) { + if(pSiS->oldChipset == OC_SIS530A) { + if((systemPCIdevices = xf86GetPciConfigInfo())) { + i = 0; + while((pdptr = systemPCIdevices[i])) { + if((pdptr->pci_vendor == 0x1274) && + ((pdptr->pci_device == 0x5000) || + ((pdptr->pci_device & 0xFFF0) == 0x1370))) { + pSiS->Flags |= ESS137xPRESENT; + break; + } + i++; + } + } + if(pSiS->Flags & ESS137xPRESENT) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "SiS530/620: Found ESS device\n"); + } + } + } + + pSiS->Flags &= ~(SECRETFLAG); + if(pSiS->oldChipset >= OC_SIS5597) { + inSISIDXREG(SISSR, 0x37, sr37); + if(sr37 & 0x80) pSiS->Flags |= SECRETFLAG; + } + + pSiS->Flags &= ~(A6326REVAB); + if(pSiS->Chipset == PCI_CHIP_SIS6326) { + if(((pSiS->ChipRev & 0x0f) == 0x0a) || + ((pSiS->ChipRev & 0x0f) == 0x0b)) { + pSiS->Flags |= A6326REVAB; + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected memory clock: %3.3f MHz\n", + pSiS->MemClock/1000.0); + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected DRAM bus width: %d bit\n", + pSiS->BusWidth); +} + +static void +sis300Setup(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + const int bus[4] = {32, 64, 128, 32}; + const int adaptermclk[8] = { 66, 83, 100, 133, + 100, 100, 100, 100}; + const int adaptermclk300[8] = { 125, 125, 125, 100, + 100, 100, 100, 100}; + unsigned int config; + unsigned char temp; + int cpubuswidth; + int from = X_PROBED; + + pSiS->MemClock = SiSMclk(pSiS); + + inSISIDXREG(SISSR, 0x14, config); + pScrn->videoRam = ((config & 0x3F) + 1) * 1024; + cpubuswidth = bus[config >> 6]; + + switch(pSiS->Chipset) { + case PCI_CHIP_SIS300: + pSiS->BusWidth = cpubuswidth; + break; + case PCI_CHIP_SIS540: + pSiS->BusWidth = 64; + from = X_INFO; + break; + case PCI_CHIP_SIS630: + pSiS->BusWidth = 64; + from = X_INFO; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Internal error: sis300setup() called with invalid chipset!\n"); + pSiS->BusWidth = 64; + from = X_INFO; + } + + inSISIDXREG(SISSR, 0x3A, config); + config &= 0x03; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected DRAM type: %s\n", + dramTypeStr[config+4]); + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected memory clock: %3.3f MHz\n", + pSiS->MemClock/1000.0); + + if(pSiS->Chipset == PCI_CHIP_SIS300) { + if(pSiS->ChipRev > 0x13) { + inSISIDXREG(SISSR, 0x3A, temp); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "(Adapter assumes MCLK being %d Mhz)\n", + adaptermclk300[(temp & 0x07)]); + } + } else { + inSISIDXREG(SISSR, 0x1A, temp); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "(Adapter assumes MCLK being %d Mhz)\n", + adaptermclk[(temp & 0x07)]); + } + + xf86DrvMsg(pScrn->scrnIndex, from, + "%s DRAM bus width: %d bit\n", + (from == X_PROBED) ? "Detected" : "Assuming", + pSiS->BusWidth); +} + +/* TW: for 315, 315H, 315PRO, 330 */ +static void +sis310Setup(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + int busSDR[4] = {64, 64, 128, 128}; + int busDDR[4] = {32, 32, 64, 64}; + int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2}; + unsigned int config, config1, config2; + char *dramTypeStr310[] = { + "Single Channel 1 rank SDR SDRAM", + "Single Channel 1 rank SDR SGRAM", + "Single Channel 1 rank DDR SDRAM", + "Single Channel 1 rank DDR SGRAM", + "Single Channel 2 rank SDR SDRAM", + "Single Channel 2 rank SDR SGRAM", + "Single Channel 2 rank DDR SDRAM", + "Single Channel 2 rank DDR SGRAM", + "Asymmetric SDR SDRAM", + "Asymmetric SDR SGRAM", + "Asymmetric DDR SDRAM", + "Asymmetric DDR SGRAM", + "Dual channel SDR SDRAM", + "Dual channel SDR SGRAM", + "Dual channel DDR SDRAM", + "Dual channel DDR SGRAM"}; + char *dramTypeStr330[] = { + "Single Channel SDR SDRAM", + "", + "Single Channel DDR SDRAM", + "", + "--unknown--", + "", + "--unknown--", + "", + "Asymetric Dual Channel SDR SDRAM", + "", + "Asymetric Dual Channel DDR SDRAM", + "", + "Dual channel SDR SDRAM", + "", + "Dual channel DDR SDRAM", + ""}; + + inSISIDXREG(SISSR, 0x14, config); + config1 = (config & 0x0C) >> 2; + inSISIDXREG(SISSR, 0x3A, config2); + config2 &= 0x03; + + pScrn->videoRam = (1 << ((config & 0xF0) >> 4)) * 1024; + + if(pSiS->Chipset == PCI_CHIP_SIS330) { + + if(config1) pScrn->videoRam <<= 1; + + } else { + + /* If SINGLE_CHANNEL_2_RANK or DUAL_CHANNEL_1_RANK -> mem * 2 */ + if((config1 == 0x01) || (config1 == 0x03)) + pScrn->videoRam <<= 1; + + /* If DDR asymetric -> mem * 1,5 */ + if(config1 == 0x02) + pScrn->videoRam += pScrn->videoRam/2; + + } + + pSiS->MemClock = SiSMclk(pSiS); + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected DRAM type: %s\n", + (pSiS->Chipset == PCI_CHIP_SIS330) ? + dramTypeStr330[(config1 * 4) + (config2 & 0x02)] : + dramTypeStr310[(config1 * 4) + config2]); + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected memory clock: %3.3f MHz\n", + pSiS->MemClock/1000.0); + + /* TW: DDR -> mclk * 2 - needed for bandwidth calculation */ + if(pSiS->Chipset == PCI_CHIP_SIS330) { + if(config2 & 0x02) { + pSiS->MemClock *= 2; + if(config1 == 0x02) { + pSiS->BusWidth = busDDRA[0]; + } else { + pSiS->BusWidth = busDDR[(config & 0x02)]; + } + } else { + if(config1 == 0x02) { + pSiS->BusWidth = busDDRA[2]; + } else { + pSiS->BusWidth = busSDR[(config & 0x02)]; + } + } + } else { + if(config2 & 0x02) pSiS->MemClock *= 2; + if(config1 == 0x02) + pSiS->BusWidth = busDDRA[(config & 0x03)]; + else if(config2 & 0x02) + pSiS->BusWidth = busDDR[(config & 0x03)]; + else + pSiS->BusWidth = busSDR[(config & 0x03)]; + } + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected DRAM bus width: %d bit\n", + pSiS->BusWidth); +} + +/* TW: for 550, 650, 740 */ +static void +sis550Setup(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned int config; + CARD8 pcimemcode; + + /* TW: Some of the following is guessed; however, + since our mode switching code is omniscient + anyway, we only need some reasonable values + to prevent X from deleting modes from the + list + */ + + inSISIDXREG(SISSR, 0x14, config); + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected DRAM type: %s\n", + dramTypeStr[(((config & 0x80) >> 7) << 2) + 4]); + + pSiS->MemClock = SiSMclk(pSiS); + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected memory clock: %3.3f MHz\n", + pSiS->MemClock/1000.0); + + /* TW: DDR -> Mclk * 2 - needed for bandwidth calculation */ + if(config & 0x80) pSiS->MemClock *= 2; + + pSiS->BusWidth = (config & 0x40) ? 128 : 64; + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected DRAM bus width: %d bit\n", + pSiS->BusWidth); + + pScrn->videoRam = (((config & 0x3F) + 1) * 4) * 1024; + + /* TW: Some 550 BIOSes don't seem to set SR14 correctly. We have + * to read PCI configuration in order to get a correct size. + */ + if (pSiS->Chipset == PCI_CHIP_SIS550) { + if((pScrn->videoRam != 4*1024) && + (pScrn->videoRam != 8*1024) && + (pScrn->videoRam != 16*1024) && + (pScrn->videoRam != 24*1024) && + (pScrn->videoRam != 32*1024) && + (pScrn->videoRam != 48*1024) && + (pScrn->videoRam != 64*1024) && + (pScrn->videoRam != 96*1024) && + (pScrn->videoRam != 128*1024) && + (pScrn->videoRam != 256*1024)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Invalid memory size (%d) encountered, reading PCI configuration\n", + pScrn->videoRam); + pcimemcode = pciReadByte(0x00000000, 0x63); + pScrn->videoRam = (1 << (((pcimemcode & 0x70) >> 4) + 21)) / 1024; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "PCI config reported %dKB video RAM\n", pScrn->videoRam); + } + } +} + +void +SiSSetup(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + + pSiS->Flags = 0; + pSiS->VBFlags = 0; + + switch (SISPTR(pScrn)->Chipset) { + case PCI_CHIP_SIS5597: + case PCI_CHIP_SIS6326: + case PCI_CHIP_SIS530: + sisOldSetup(pScrn); + break; + case PCI_CHIP_SIS300: + case PCI_CHIP_SIS630: /* +730 */ + case PCI_CHIP_SIS540: + sis300Setup(pScrn); + break; + case PCI_CHIP_SIS315: + case PCI_CHIP_SIS315H: + case PCI_CHIP_SIS315PRO: + case PCI_CHIP_SIS330: + sis310Setup(pScrn); + break; + case PCI_CHIP_SIS550: + case PCI_CHIP_SIS650: /* + 740 */ + sis550Setup(pScrn); + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Internal error: SiSSetup() called with invalid Chipset (0x%x)\n", + pSiS->Chipset); + break; + } +} + + diff --git a/src/sis_shadow.c b/src/sis_shadow.c new file mode 100644 index 0000000..dfc920e --- /dev/null +++ b/src/sis_shadow.c @@ -0,0 +1,250 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_shadow.c,v 1.4 2003/01/29 15:42:17 eich Exp $ */ +/* + * Copyright (c) 1999, The XFree86 Project Inc. + * based on code written by Mark Vojkovich <markv@valinux.com> + * + * TW: This module doesn't use CurrentLayout, because it is never + * active when DGA is active and vice versa. + */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "sis.h" +#include "servermd.h" + +#include "sis_shadow.h" + +void +SISRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + SISPtr pSiS = SISPTR(pScrn); + int width, height, Bpp, FBPitch; + unsigned char *src, *dst; + + Bpp = pScrn->bitsPerPixel >> 3; + FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel); + + while(num--) { + width = (pbox->x2 - pbox->x1) * Bpp; + height = pbox->y2 - pbox->y1; + src = pSiS->ShadowPtr + (pbox->y1 * pSiS->ShadowPitch) + + (pbox->x1 * Bpp); + dst = pSiS->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp); + + while(height--) { + memcpy(dst, src, width); + dst += FBPitch; + src += pSiS->ShadowPitch; + } + + pbox++; + } +} + +void +SISPointerMoved(int index, int x, int y) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + SISPtr pSiS = SISPTR(pScrn); + int newX, newY; + + if(pSiS->Rotate == 1) { + newX = pScrn->pScreen->height - y - 1; + newY = x; + } else { + newX = y; + newY = pScrn->pScreen->width - x - 1; + } + + (*pSiS->PointerMoved)(index, newX, newY); +} + +void +SISRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + SISPtr pSiS = SISPTR(pScrn); + int count, width, height, y1, y2, dstPitch, srcPitch; + CARD8 *dstPtr, *srcPtr, *src; + CARD32 *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -pSiS->Rotate * pSiS->ShadowPitch; + + while(num--) { + width = pbox->x2 - pbox->x1; + y1 = pbox->y1 & ~3; + y2 = (pbox->y2 + 3) & ~3; + height = (y2 - y1) >> 2; /* in dwords */ + + if(pSiS->Rotate == 1) { + dstPtr = pSiS->FbBase + + (pbox->x1 * dstPitch) + pScrn->virtualX - y2; + srcPtr = pSiS->ShadowPtr + ((1 - y2) * srcPitch) + pbox->x1; + } else { + dstPtr = pSiS->FbBase + + ((pScrn->virtualY - pbox->x2) * dstPitch) + y1; + srcPtr = pSiS->ShadowPtr + (y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = (CARD32*)dstPtr; + count = height; + while(count--) { + *(dst++) = src[0] | (src[srcPitch] << 8) | + (src[srcPitch * 2] << 16) | + (src[srcPitch * 3] << 24); + src += srcPitch * 4; + } + srcPtr += pSiS->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} + + +void +SISRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + SISPtr pSiS = SISPTR(pScrn); + int count, width, height, y1, y2, dstPitch, srcPitch; + CARD16 *dstPtr, *srcPtr, *src; + CARD32 *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -pSiS->Rotate * pSiS->ShadowPitch >> 1; + + while(num--) { + width = pbox->x2 - pbox->x1; + y1 = pbox->y1 & ~1; + y2 = (pbox->y2 + 1) & ~1; + height = (y2 - y1) >> 1; /* in dwords */ + + if(pSiS->Rotate == 1) { + dstPtr = (CARD16*)pSiS->FbBase + + (pbox->x1 * dstPitch) + pScrn->virtualX - y2; + srcPtr = (CARD16*)pSiS->ShadowPtr + + ((1 - y2) * srcPitch) + pbox->x1; + } else { + dstPtr = (CARD16*)pSiS->FbBase + + ((pScrn->virtualY - pbox->x2) * dstPitch) + y1; + srcPtr = (CARD16*)pSiS->ShadowPtr + + (y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = (CARD32*)dstPtr; + count = height; + while(count--) { + *(dst++) = src[0] | (src[srcPitch] << 16); + src += srcPitch * 2; + } + srcPtr += pSiS->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} + + +/* this one could be faster */ +void +SISRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + SISPtr pSiS = SISPTR(pScrn); + int count, width, height, y1, y2, dstPitch, srcPitch; + CARD8 *dstPtr, *srcPtr, *src; + CARD32 *dst; + + dstPitch = BitmapBytePad(pScrn->displayWidth * 24); + srcPitch = -pSiS->Rotate * pSiS->ShadowPitch; + + while(num--) { + width = pbox->x2 - pbox->x1; + y1 = pbox->y1 & ~3; + y2 = (pbox->y2 + 3) & ~3; + height = (y2 - y1) >> 2; /* blocks of 3 dwords */ + + if(pSiS->Rotate == 1) { + dstPtr = pSiS->FbBase + + (pbox->x1 * dstPitch) + ((pScrn->virtualX - y2) * 3); + srcPtr = pSiS->ShadowPtr + ((1 - y2) * srcPitch) + (pbox->x1 * 3); + } else { + dstPtr = pSiS->FbBase + + ((pScrn->virtualY - pbox->x2) * dstPitch) + (y1 * 3); + srcPtr = pSiS->ShadowPtr + (y1 * srcPitch) + (pbox->x2 * 3) - 3; + } + + while(width--) { + src = srcPtr; + dst = (CARD32*)dstPtr; + count = height; + while(count--) { + dst[0] = src[0] | (src[1] << 8) | (src[2] << 16) | + (src[srcPitch] << 24); + dst[1] = src[srcPitch + 1] | (src[srcPitch + 2] << 8) | + (src[srcPitch * 2] << 16) | + (src[(srcPitch * 2) + 1] << 24); + dst[2] = src[(srcPitch * 2) + 2] | (src[srcPitch * 3] << 8) | + (src[(srcPitch * 3) + 1] << 16) | + (src[(srcPitch * 3) + 2] << 24); + dst += 3; + src += srcPitch * 4; + } + srcPtr += pSiS->Rotate * 3; + dstPtr += dstPitch; + } + + pbox++; + } +} + +void +SISRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + SISPtr pSiS = SISPTR(pScrn); + int count, width, height, dstPitch, srcPitch; + CARD32 *dstPtr, *srcPtr, *src, *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -pSiS->Rotate * pSiS->ShadowPitch >> 2; + + while(num--) { + width = pbox->x2 - pbox->x1; + height = pbox->y2 - pbox->y1; + + if(pSiS->Rotate == 1) { + dstPtr = (CARD32*)pSiS->FbBase + + (pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2; + srcPtr = (CARD32*)pSiS->ShadowPtr + + ((1 - pbox->y2) * srcPitch) + pbox->x1; + } else { + dstPtr = (CARD32*)pSiS->FbBase + + ((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1; + srcPtr = (CARD32*)pSiS->ShadowPtr + + (pbox->y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = dstPtr; + count = height; + while(count--) { + *(dst++) = *src; + src += srcPitch; + } + srcPtr += pSiS->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} diff --git a/src/sis_vb.c b/src/sis_vb.c new file mode 100644 index 0000000..d8ed114 --- /dev/null +++ b/src/sis_vb.c @@ -0,0 +1,353 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_vb.c,v 1.10 2003/01/29 15:42:17 eich Exp $ */ +/* + * Video bridge detection and configuration for 300 and 310/325 series + * + * Copyright 2002 by Thomas Winischhofer, Vienna, Austria + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Thomas Winischhofer not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Winischhofer makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS WINISCHHOFER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS WINISCHHOFER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * (Completely rewritten) + */ + +#include "xf86.h" +#include "xf86_ansic.h" +#include "compiler.h" +#include "xf86PciInfo.h" + +#include "sis.h" +#include "sis_regs.h" +#include "sis_vb.h" + +static const SiS_LCD_StStruct SiS300_LCD_Type[]= +{ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1}, /* 0 - invalid */ + { VB_LCD_800x600, 800, 600, LCD_800x600, 0}, /* 1 */ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1}, /* 2 */ + { VB_LCD_1280x1024,1280, 1024, LCD_1280x1024, 2}, /* 3 */ + { VB_LCD_1280x960, 1280, 960, LCD_1280x960, 3}, /* 4 */ + { VB_LCD_640x480, 640, 480, LCD_640x480, 4}, /* 5 */ + { VB_LCD_1024x600, 1024, 600, LCD_1024x600, 10}, /* 6 */ + { VB_LCD_1152x768, 1152, 768, LCD_1152x768, 7}, /* 7 */ + { VB_LCD_320x480, 320, 480, LCD_320x480, 6}, /* 8 */ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1}, /* 9 */ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1}, /* a */ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1}, /* b */ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1}, /* c */ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1}, /* d */ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1}, /* e */ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1}, /* f */ +}; + +static const SiS_LCD_StStruct SiS310_LCD_Type[]= +{ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1}, /* 0 - invalid */ + { VB_LCD_800x600, 800, 600, LCD_800x600, 0}, /* 1 */ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1}, /* 2 */ + { VB_LCD_1280x1024, 1280,1024, LCD_1280x1024, 2}, /* 3 */ + { VB_LCD_640x480, 640, 480, LCD_640x480, 4}, /* 4 */ + { VB_LCD_1024x600, 1024, 600, LCD_1024x600, 10}, /* 5 */ + { VB_LCD_1152x864, 1152, 864, LCD_1152x864, 11}, /* 6 */ + { VB_LCD_1280x960, 1280, 960, LCD_1280x960, 3}, /* 7 */ + { VB_LCD_1152x768, 1152, 768, LCD_1152x768, 7}, /* 8 */ + { VB_LCD_1400x1050, 1400,1050, LCD_1400x1050, 8}, /* 9 */ + { VB_LCD_1280x768, 1280, 768, LCD_1280x768, 9}, /* a */ + { VB_LCD_1600x1200, 1600,1200, LCD_1600x1200, 5}, /* b */ + { VB_LCD_320x480, 320, 480, LCD_320x480, 6}, /* c */ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1}, /* d */ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1}, /* e */ + { VB_LCD_1024x768, 1024, 768, LCD_1024x768, 1} /* f */ +}; + +static const char *panelres[] = { + "800x600", + "1024x768", + "1280x1024", + "1280x960", + "640x480", + "1600x1200", + "320x480", + "1152x768", + "1400x1050", + "1280x768", + "1024x600", + "1152x864" +}; + +/* Detect CRT1 */ +void SISCRT1PreInit(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char CR32, SR17; + unsigned char CRT1Detected = 0; + unsigned char OtherDevices = 0; + + if(!(pSiS->VBFlags & VB_VIDEOBRIDGE)) { + pSiS->CRT1off = 0; + return; + } + +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode && pSiS->SecondHead) { + pSiS->CRT1off = 0; + return; + } +#endif + + inSISIDXREG(SISCR, 0x32, CR32); + inSISIDXREG(SISSR, 0x17, SR17); + + if ( (pSiS->VGAEngine == SIS_300_VGA) && + (pSiS->Chipset != PCI_CHIP_SIS300) && + (SR17 & 0x0F) ) { + + if(SR17 & 0x01) CRT1Detected = 1; + if(SR17 & 0x0E) OtherDevices = 1; + + } else { + + if(CR32 & 0x20) CRT1Detected = 1; + if(CR32 & 0x5F) OtherDevices = 1; + + } + + if(pSiS->CRT1off == -1) { + if(!CRT1Detected) { + + /* BIOS detected no CRT1. */ + /* If other devices exist, switch it off */ + if(OtherDevices) pSiS->CRT1off = 1; + else pSiS->CRT1off = 0; + + } else { + + /* BIOS detected CRT1, leave/switch it on */ + pSiS->CRT1off = 0; + + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "%sCRT1 connection detected\n", + CRT1Detected ? "" : "No "); +} + +/* Detect CRT2-LCD and LCD size */ +void SISLCDPreInit(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char CR32, SR17, CR36, CR37; + USHORT textindex; + + if(!(pSiS->VBFlags & VB_VIDEOBRIDGE)) { + return; + } + + inSISIDXREG(SISCR, 0x32, CR32); + inSISIDXREG(SISSR, 0x17, SR17); + + if( (pSiS->VGAEngine == SIS_300_VGA) && + (pSiS->Chipset != PCI_CHIP_SIS300) && + (SR17 & 0x0F) ) { + if(SR17 & 0x02) + pSiS->VBFlags |= CRT2_LCD; + } else { + if(CR32 & 0x08) + pSiS->VBFlags |= CRT2_LCD; + } + + if(pSiS->VBFlags & CRT2_LCD) { + inSISIDXREG(SISCR, 0x36, CR36); + inSISIDXREG(SISCR, 0x37, CR37); + if((pSiS->VGAEngine == SIS_315_VGA) && (!CR36)) { + /* TW: Old 650/301LV BIOS version "forgot" to set CR36, CR37 */ + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "BIOS-provided LCD information invalid, probing myself...\n"); + if(pSiS->VBFlags & VB_LVDS) pSiS->SiS_Pr->SiS_IF_DEF_LVDS = 1; + else pSiS->SiS_Pr->SiS_IF_DEF_LVDS = 0; + SiS_GetPanelID(pSiS->SiS_Pr, &pSiS->sishw_ext); + inSISIDXREG(SISCR, 0x36, CR36); + inSISIDXREG(SISCR, 0x37, CR37); + } + if(pSiS->VGAEngine == SIS_300_VGA) { + pSiS->VBLCDFlags |= SiS300_LCD_Type[(CR36 & 0x0f)].VBLCD_lcdflag; + pSiS->LCDheight = SiS300_LCD_Type[(CR36 & 0x0f)].LCDheight; + pSiS->LCDwidth = SiS300_LCD_Type[(CR36 & 0x0f)].LCDwidth; + pSiS->sishw_ext.ulCRT2LCDType = SiS300_LCD_Type[(CR36 & 0x0f)].LCDtype; + textindex = SiS300_LCD_Type[(CR36 & 0x0f)].LCDrestextindex; + } else { + pSiS->VBLCDFlags |= SiS310_LCD_Type[(CR36 & 0x0f)].VBLCD_lcdflag; + pSiS->LCDheight = SiS310_LCD_Type[(CR36 & 0x0f)].LCDheight; + pSiS->LCDwidth = SiS310_LCD_Type[(CR36 & 0x0f)].LCDwidth; + pSiS->sishw_ext.ulCRT2LCDType = SiS310_LCD_Type[(CR36 & 0x0f)].LCDtype; + textindex = SiS310_LCD_Type[(CR36 & 0x0f)].LCDrestextindex; + } + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected LCD panel resolution %s (type %d, %s%s)\n", + panelres[textindex], + (pSiS->VGAEngine == SIS_315_VGA) ? ((CR36 & 0x0f) - 1) : ((CR36 & 0xf0) >> 4), + (pSiS->VBFlags & VB_LVDS) ? + (CR37 & 0x10 ? "non-expanding, " : "expanding, ") : + ( ((pSiS->VBFlags & VB_301B) && (pSiS->VGAEngine == SIS_300_VGA)) ? + (CR37 & 0x10 ? "non-expanding, " : "expanding, ") : + (CR37 & 0x10 ? "self-scaling, " : "non-self-scaling, ") ), + CR37 & 0x01 ? "RGB18" : "RGB24"); + } +} + +/* Detect CRT2-TV connector type and PAL/NTSC flag */ +void SISTVPreInit(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char SR16, SR17, SR38, CR32, CR38=0, CR79; + int temp = 0; + + if(!(pSiS->VBFlags & VB_VIDEOBRIDGE)) + return; + + inSISIDXREG(SISCR, 0x32, CR32); + inSISIDXREG(SISSR, 0x17, SR17); + inSISIDXREG(SISSR, 0x16, SR16); + inSISIDXREG(SISSR, 0x38, SR38); + switch(pSiS->VGAEngine) { + case SIS_300_VGA: + if(pSiS->Chipset != PCI_CHIP_SIS300) temp = 0x35; + break; + case SIS_315_VGA: + temp = 0x38; + break; + } + if(temp) { + inSISIDXREG(SISCR, temp, CR38); + } + +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "(vb.c: SR17=%02x CR32=%02x)\n", SR17, CR32); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "(vb.c: SR16=%02x SR38=%02x)\n", SR16, SR38); +#endif + + if( (pSiS->VGAEngine == SIS_300_VGA) && + (pSiS->Chipset != PCI_CHIP_SIS300) && + (SR17 & 0x0F) ) { + + if(SR17 & 0x04) + pSiS->VBFlags |= CRT2_TV; + + if(SR17 & 0x20) + pSiS->VBFlags |= TV_SVIDEO; + else if (SR17 & 0x10) + pSiS->VBFlags |= TV_AVIDEO; + + if(pSiS->VBFlags & (TV_SVIDEO | TV_AVIDEO)) { + if(SR16 & 0x20) + pSiS->VBFlags |= TV_PAL; + else + pSiS->VBFlags |= TV_NTSC; + } + + } else { + + if(CR32 & 0x47) + pSiS->VBFlags |= CRT2_TV; + + if(CR32 & 0x04) + pSiS->VBFlags |= TV_SCART; + else if(CR32 & 0x02) + pSiS->VBFlags |= TV_SVIDEO; + else if(CR32 & 0x01) + pSiS->VBFlags |= TV_AVIDEO; + else if(CR32 & 0x40) + pSiS->VBFlags |= (TV_SVIDEO | TV_HIVISION); + else if((CR38 & 0x04) && (pSiS->VBFlags & VB_CHRONTEL)) + pSiS->VBFlags |= (TV_CHSCART | TV_PAL); + else if((CR38 & 0x08) && (pSiS->VBFlags & VB_CHRONTEL)) + pSiS->VBFlags |= (TV_CHHDTV | TV_NTSC); + + if(pSiS->VBFlags & (TV_SCART | TV_SVIDEO | TV_AVIDEO | TV_HIVISION)) { + if( (pSiS->Chipset == PCI_CHIP_SIS550) || /* TW: ? */ + (pSiS->Chipset == PCI_CHIP_SIS650) ) { + inSISIDXREG(SISCR, 0x79, CR79); + if(CR79 & 0x20) { + pSiS->VBFlags |= TV_PAL; + if(CR38 & 0x40) pSiS->VBFlags |= TV_PALM; + else if(CR38 & 0x80) pSiS->VBFlags |= TV_PALN; + } else + pSiS->VBFlags |= TV_NTSC; + } else if(pSiS->VGAEngine == SIS_300_VGA) { + /* TW: Should be SR38 here as well, but this + * does not work. Looks like a BIOS bug (2.04.5c). + */ + if(SR16 & 0x20) + pSiS->VBFlags |= TV_PAL; + else + pSiS->VBFlags |= TV_NTSC; + } else { /* 315, 330 */ + if(SR38 & 0x01) { + pSiS->VBFlags |= TV_PAL; + if(CR38 & 0x40) pSiS->VBFlags |= TV_PALM; + else if(CR38 & 0x80) pSiS->VBFlags |= TV_PALN; + } else + pSiS->VBFlags |= TV_NTSC; + } + } + } + if(pSiS->VBFlags & (TV_SCART | TV_SVIDEO | TV_AVIDEO | TV_HIVISION | TV_CHSCART | TV_CHHDTV)) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "%sTV standard %s\n", + (pSiS->VBFlags & (TV_CHSCART | TV_CHHDTV)) ? "Using " : "Detected default ", + (pSiS->VBFlags & TV_NTSC) ? + ((pSiS->VBFlags & TV_CHHDTV) ? "480i HDTV" : "NTSC") : + ((pSiS->VBFlags & TV_PALM) ? "PALM" : + ((pSiS->VBFlags & TV_PALN) ? "PALN" : "PAL"))); + } +} + +/* Detect CRT2-VGA */ +void SISCRT2PreInit(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char SR17, CR32; + + if (!(pSiS->VBFlags & VB_VIDEOBRIDGE)) + return; + + /* CRT2-VGA not supported on LVDS and 30xLV(X) */ + if (pSiS->VBFlags & (VB_LVDS|VB_30xLV|VB_30xLVX)) + return; + + inSISIDXREG(SISCR, 0x32, CR32); + inSISIDXREG(SISSR, 0x17, SR17); + + if( (pSiS->VGAEngine == SIS_300_VGA) && + (pSiS->Chipset != PCI_CHIP_SIS300) && + (SR17 & 0x0F) ) { + + if(SR17 & 0x08) + pSiS->VBFlags |= CRT2_VGA; + + } else { + + if(CR32 & 0x10) + pSiS->VBFlags |= CRT2_VGA; + + } +} + + + diff --git a/src/sis_vga.c b/src/sis_vga.c new file mode 100644 index 0000000..0ab8b8d --- /dev/null +++ b/src/sis_vga.c @@ -0,0 +1,1535 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_vga.c,v 1.16 2003/01/29 15:42:17 eich Exp $ */ +/* + * Mode setup and video bridge detection + * + * Copyright 1998,1999 by Alan Hourihane, Wigan, England. + * Parts Copyright 2001, 2002 by Thomas Winischhofer, Vienna, Austria. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holder not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The copyright holder makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk + * Mike Chapman <mike@paranoia.com>, + * Juanjo Santamarta <santamarta@ctv.es>, + * Mitani Hiroshi <hmitani@drl.mei.co.jp> + * David Thomas <davtom@dream.org.uk>. + * Thomas Winischhofer <thomas@winischhofer.net> + */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Version.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" + +#include "sis.h" +#include "sis_regs.h" +#include "sis_dac.h" + +#define Midx 0 +#define Nidx 1 +#define VLDidx 2 +#define Pidx 3 +#define PSNidx 4 +#define Fref 14318180 +/* stability constraints for internal VCO -- MAX_VCO also determines + * the maximum Video pixel clock */ +#define MIN_VCO Fref +#define MAX_VCO 135000000 +#define MAX_VCO_5597 353000000 +#define MAX_PSN 0 /* no pre scaler for this chip */ +#define TOLERANCE 0.01 /* search smallest M and N in this tolerance */ + + +static Bool SISInit(ScrnInfoPtr pScrn, DisplayModePtr mode); +static Bool SIS300Init(ScrnInfoPtr pScrn, DisplayModePtr mode); +/* TW: To be used internally only */ +int SISDoSense(ScrnInfoPtr pScrn, int tempbl, int tempbh, int tempcl, int tempch); +void SISSense30x(ScrnInfoPtr pScrn); +int SIS6326DoSense(ScrnInfoPtr pScrn, int tempbh, int tempbl, int tempch, int tempcl); +void SISSense6326(ScrnInfoPtr pScrn); +static void SiS6326TVDelay(ScrnInfoPtr pScrn, int delay); + +const CARD8 SiS6326TVRegs1_NTSC[6][14] = { + {0x81,0x3f,0x49,0x1b,0xa9,0x03,0x00,0x09,0x08,0x7d,0x00,0x88,0x30,0x60}, + {0x81,0x3f,0x49,0x1d,0xa0,0x03,0x00,0x09,0x08,0x7d,0x00,0x88,0x30,0x60}, + {0x81,0x45,0x24,0x8e,0x26,0x0b,0x00,0x09,0x02,0xfe,0x00,0x09,0x51,0x60}, + {0x81,0x45,0x24,0x8e,0x26,0x07,0x00,0x29,0x04,0x30,0x10,0x3b,0x61,0x60}, + {0x81,0x3f,0x24,0x8e,0x26,0x09,0x00,0x09,0x02,0x30,0x10,0x3b,0x51,0x60}, + {0x83,0x5d,0x21,0xbe,0x75,0x03,0x00,0x09,0x08,0x42,0x10,0x4d,0x61,0x79} /* 640x480u */ +}; + +const CARD8 SiS6326TVRegs2_NTSC[6][54] = { + {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, + 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, + 0xFC, 0xDF, 0x94, 0x1F, 0x4A, 0x03, 0x71, 0x07, 0x97, 0x10, 0x40, + 0x48, 0x00, 0x26, 0xB6, 0x10, 0x5C, 0xEC, 0x21, 0x2E, 0xBE, 0x10, + 0x64, 0xF4, 0x21, 0x13, 0x75, 0x08, 0x31, 0x6A, 0x01, 0xA0}, + {0x11, 0x17, 0x03, 0x0A, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, + 0x0D, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, + 0xFF, 0xDF, 0x94, 0x1F, 0x4A, 0x03, 0x71, 0x07, 0x97, 0x10, 0x40, + 0x48, 0x00, 0x26, 0xB6, 0x10, 0x5C, 0xEC, 0x21, 0x2E, 0xBE, 0x10, + 0x64, 0xF4, 0x21, 0x13, 0x75, 0x08, 0x31, 0x6A, 0x01, 0xA0}, + {0x11, 0x17, 0x03, 0x0A, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, + 0x0D, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, + 0xFF, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73, + 0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30, + 0xBA, 0xDA, 0x52, 0xDC, 0x02, 0xD1, 0x53, 0xF7, 0x02, 0xA0}, + {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, + 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, + 0xDC, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73, + 0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30, + 0xBA, 0xDA, 0x52, 0x00, 0x02, 0xF5, 0x53, 0xF7, 0x02, 0xA0}, + {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, + 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, + 0xDC, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73, + 0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30, + 0xBA, 0xDA, 0x52, 0xDC, 0x02, 0xD1, 0x53, 0xF7, 0x02, 0xA0}, + {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, /* 640x480u */ + 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, + 0xDC, 0xDF, 0x94, 0xAF, 0x95, 0x06, 0xDD, 0x07, 0x5F, 0x30, 0x7E, + 0x86, 0x00, 0x4C, 0xA4, 0x30, 0xE3, 0x3B, 0x62, 0x54, 0xAC, 0x30, + 0xEB, 0x43, 0x62, 0x48, 0x34, 0x3D, 0x63, 0x29, 0x03, 0xA0} +}; + +const CARD8 SiS6326TVRegs1_PAL[6][14] = { + {0x81,0x2d,0xc8,0x07,0xb2,0x0b,0x00,0x09,0x02,0xed,0x00,0xf8,0x30,0x40}, + {0x80,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0xed,0x10,0xf8,0x71,0x40}, + {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0xed,0x10,0xf8,0x71,0x40}, + {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0x8f,0x10,0x9a,0x71,0x40}, + {0x83,0x63,0xa1,0x7a,0xa3,0x0a,0x00,0x09,0x02,0xb5,0x11,0xc0,0x81,0x59}, /* 800x600u */ + {0x81,0x63,0xa4,0x03,0xd9,0x01,0x00,0x09,0x10,0x9f,0x10,0xaa,0x71,0x59} /* 720x540 */ +}; + +const CARD8 SiS6326TVRegs2_PAL[6][54] = { + {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, + 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, + 0xE5, 0xDF, 0x94, 0xEF, 0x5A, 0x03, 0x7F, 0x07, 0xFF, 0x10, 0x4E, + 0x56, 0x00, 0x2B, 0x23, 0x20, 0xB4, 0xAC, 0x31, 0x33, 0x2B, 0x20, + 0xBC, 0xB4, 0x31, 0x83, 0xE1, 0x78, 0x31, 0xD6, 0x01, 0xA0}, + {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, + 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, + 0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90, + 0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40, + 0x6A, 0x5A, 0x73, 0x03, 0xC1, 0xF8, 0x63, 0xB6, 0x03, 0xA0}, + {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, + 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, + 0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90, + 0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40, + 0x6A, 0x5A, 0x73, 0x03, 0xC1, 0xF8, 0x63, 0xB6, 0x03, 0xA0}, + {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, + 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, + 0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90, + 0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40, + 0x6A, 0x5A, 0x73, 0xA0, 0xC1, 0x95, 0x73, 0xB6, 0x03, 0xA0}, + {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 800x600u */ + 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, + 0xE5, 0xDF, 0x94, 0x7F, 0xBD, 0x08, 0x0E, 0x07, 0x47, 0x40, 0x9D, + 0xA5, 0x00, 0x54, 0x94, 0x40, 0xA4, 0xE4, 0x73, 0x5C, 0x9C, 0x40, + 0xAC, 0xEC, 0x73, 0x0B, 0x0E, 0x00, 0x84, 0x03, 0x04, 0xA0}, + {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 720x540 */ + 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, + 0xE5, 0xDF, 0x94, 0xDF, 0xB0, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x9D, + 0xA5, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40, + 0x6A, 0x5A, 0x73, 0xA0, 0xC1, 0x95, 0x73, 0xB6, 0x03, 0xA0} +}; + +const CARD8 SiS6326TVRegs1[14] = { + 0x00,0x01,0x02,0x03,0x04,0x11,0x12,0x13,0x21,0x26,0x27,0x3a,0x3c,0x43 +}; + +const CARD8 SiS6326CR[9][15] = { + {0x79,0x63,0x64,0x1d,0x6a,0x93,0x00,0x6f,0xf0,0x58,0x8a,0x57,0x57,0x70,0x20}, /* PAL 800x600 */ + {0x79,0x4f,0x50,0x95,0x60,0x93,0x00,0x6f,0xba,0x14,0x86,0xdf,0xe0,0x30,0x00}, /* PAL 640x480 */ + {0x5f,0x4f,0x50,0x82,0x53,0x9f,0x00,0x0b,0x3e,0xe9,0x8b,0xdf,0xe7,0x04,0x00}, /* NTSC 640x480 */ + {0x5f,0x4f,0x50,0x82,0x53,0x9f,0x00,0x0b,0x3e,0xcb,0x8d,0x8f,0x96,0xe9,0x00}, /* NTSC 640x400 */ + {0x83,0x63,0x64,0x1f,0x6d,0x9b,0x00,0x6f,0xf0,0x48,0x0a,0x23,0x57,0x70,0x20}, /* PAL 800x600u */ + {0x79,0x59,0x5b,0x1d,0x66,0x93,0x00,0x6f,0xf0,0x42,0x04,0x1b,0x40,0x70,0x20}, /* PAL 720x540 */ + {0x66,0x4f,0x51,0x0a,0x57,0x89,0x00,0x0b,0x3e,0xd9,0x0b,0xb6,0xe7,0x04,0x00}, /* NTSC 640x480u */ + {0xce,0x9f,0x9f,0x92,0xa4,0x16,0x00,0x28,0x5a,0x00,0x04,0xff,0xff,0x29,0x39}, /* 1280x1024-75 */ + {0x09,0xc7,0xc7,0x0d,0xd2,0x0a,0x01,0xe0,0x10,0xb0,0x04,0xaf,0xaf,0xe1,0x1f} /* 1600x1200-60 */ +}; + +/* Initialize a display mode on 5597/5598, 6326 and 530/620 */ +static Bool +SISInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + SISPtr pSiS = SISPTR(pScrn); + SISRegPtr pReg = &pSiS->ModeReg; + vgaRegPtr vgaReg = &VGAHWPTR(pScrn)->ModeReg; + unsigned char temp; + int mclk = pSiS->MemClock; + int offset; + int clock = mode->Clock; + int width = mode->HDisplay; + int height = mode->VDisplay; + int rate = SiSCalcVRate(mode); + int buswidth = pSiS->BusWidth; + unsigned int vclk[5]; + unsigned short CRT_CPUthresholdLow; + unsigned short CRT_CPUthresholdHigh; + unsigned short CRT_ENGthreshold; + double a, b, c; + int d, factor; + int num, denum, div, sbit, scale; + BOOL sis6326tvmode, sis6326himode; + + PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "SISInit()\n")); + + /* Save the registers for further processing */ + (*pSiS->SiSSave)(pScrn, pReg); + + /* TW: Determine if chosen mode is suitable for TV on the 6326 + and if the mode is one of our special hi-res modes. + */ + sis6326tvmode = FALSE; + sis6326himode = FALSE; + if(pSiS->Chipset == PCI_CHIP_SIS6326) { + if(pSiS->SiS6326Flags & SIS6326_HASTV) { + if((pSiS->SiS6326Flags & SIS6326_TVDETECTED) && + ((strcmp(mode->name, "PAL800x600") == 0) || /* TW: Special TV modes */ + (strcmp(mode->name, "PAL800x600U") == 0) || + (strcmp(mode->name, "PAL720x540") == 0) || + (strcmp(mode->name, "PAL640x480") == 0) || + (strcmp(mode->name, "NTSC640x480") == 0) || + (strcmp(mode->name, "NTSC640x480U") == 0) || + (strcmp(mode->name, "NTSC640x400") == 0))) { + sis6326tvmode = TRUE; + } else { + pReg->sis6326tv[0x00] &= 0xfb; + } + } + if((strcmp(mode->name, "SIS1280x1024-75") == 0) || /* TW: Special high-res modes */ + (strcmp(mode->name, "SIS1600x1200-60") == 0)) { + sis6326himode = TRUE; + } + } + +#ifdef UNLOCK_ALWAYS + outSISIDXREG(SISSR, 0x05, 0x86); +#endif + + pReg->sisRegs3C4[0x06] &= 0x01; + + /* set interlace */ + if(!(mode->Flags & V_INTERLACE)) { + offset = pSiS->CurrentLayout.displayWidth >> 3; + } else { + offset = pSiS->CurrentLayout.displayWidth >> 2; + pReg->sisRegs3C4[0x06] |= 0x20; + } + + /* Enable Linear and Enhanced Gfx Mode */ + pReg->sisRegs3C4[0x06] |= 0x82; + + /* Enable MMIO at PCI Register 14H (D[6:5]: 11) */ + pReg->sisRegs3C4[0x0B] |= 0x60; + + /* Enable 32bit mem access (D7), read-ahead cache (D4) */ + pReg->sisRegs3C4[0x0C] |= 0xA0; + + /* TW: Some speed-up stuff */ + switch(pSiS->Chipset) { + case PCI_CHIP_SIS5597: + /* TW: enable host bus */ + if(pSiS->NoHostBus) { + pReg->sisRegs3C4[0x34] &= ~0x08; + } else { + pReg->sisRegs3C4[0x34] |= 0x08; + } + /* TW: fall through */ + case PCI_CHIP_SIS6326: + case PCI_CHIP_SIS530: + /* TW: Enable "dual segment register mode" (D2) and "i/o gating while + * write buffer is not empty" (D3) + */ + pReg->sisRegs3C4[0x0B] |= 0x0C; + } + + /* set colordepth */ + if(pSiS->Chipset == PCI_CHIP_SIS530) { + pReg->sisRegs3C4[0x09] &= 0x7F; + } + switch(pSiS->CurrentLayout.bitsPerPixel) { + case 8: + break; + case 16: + offset <<= 1; + if(pSiS->CurrentLayout.depth == 15) + pReg->sisRegs3C4[0x06] |= 0x04; + else + pReg->sisRegs3C4[0x06] |= 0x08; + break; + case 24: + offset += (offset << 1); + pReg->sisRegs3C4[0x06] |= 0x10; + pReg->sisRegs3C4[0x0B] |= 0x90; + break; + case 32: + if(pSiS->Chipset == PCI_CHIP_SIS530) { + offset <<= 2; + pReg->sisRegs3C4[0x06] |= 0x10; + pReg->sisRegs3C4[0x0B] |= 0x90; + pReg->sisRegs3C4[0x09] |= 0x80; + } else return FALSE; + break; + } + + /* save screen pitch for acceleration functions */ + pSiS->scrnOffset = pSiS->CurrentLayout.displayWidth * + ((pSiS->CurrentLayout.bitsPerPixel + 7) / 8); + + /* set linear framebuffer addresses */ + switch(pScrn->videoRam) { + case 512: + temp = 0x00; break; + case 1024: + temp = 0x20; break; + case 2048: + temp = 0x40; break; + case 4096: + temp = 0x60; break; + case 8192: + temp = 0x80; break; + default: + temp = 0x20; + } + pReg->sisRegs3C4[0x20] = (pSiS->FbAddress & 0x07F80000) >> 19; + pReg->sisRegs3C4[0x21] = ((pSiS->FbAddress & 0xF8000000) >> 27) | temp; + + /* Set screen offset */ + vgaReg->CRTC[0x13] = offset & 0xFF; + + /* Set CR registers for our built-in TV and hi-res modes */ + if((sis6326tvmode) || (sis6326himode)) { + + int index,i; + + /* TW: We need our very private data for hi-res and TV modes */ + if(sis6326himode) { + if(strcmp(mode->name, "SIS1280x1024-75") == 0) index = 7; + else index = 8; + } else { + if(pSiS->SiS6326Flags & SIS6326_TVPAL) { + switch(width) { + case 800: + if((strcmp(mode->name, "PAL800x600U") == 0)) + index = 4; + else + index = 0; + break; + case 720: + index = 5; + break; + case 640: + default: + index = 1; + } + } else { + switch(height) { + case 400: + index = 3; + break; + case 480: + default: + if((strcmp(mode->name, "NTSC640x480U") == 0)) + index = 6; + else + index = 2; + } + } + } + for(i=0; i<=5; i++) { + vgaReg->CRTC[i] = SiS6326CR[index][i]; + } + pReg->sisRegs3C4[0x12] = SiS6326CR[index][6]; + vgaReg->CRTC[6] = SiS6326CR[index][7]; + vgaReg->CRTC[7] = SiS6326CR[index][8]; + vgaReg->CRTC[0x10] = SiS6326CR[index][9]; + vgaReg->CRTC[0x11] = SiS6326CR[index][10]; + vgaReg->CRTC[0x12] = SiS6326CR[index][11]; + vgaReg->CRTC[0x15] = SiS6326CR[index][12]; + vgaReg->CRTC[0x16] = SiS6326CR[index][13]; + vgaReg->CRTC[9] &= ~0x20; + vgaReg->CRTC[9] |= (SiS6326CR[index][14] & 0x20); + pReg->sisRegs3C4[0x0A] = ((offset & 0xF00) >> 4) | (SiS6326CR[index][14] & 0x0f); + + } else { + + /* Set extended vertical overflow register */ + pReg->sisRegs3C4[0x0A] = ((offset & 0xF00) >> 4) | + (((mode->CrtcVTotal-2) & 0x400) >> 10 ) | + (((mode->CrtcVDisplay-1) & 0x400) >> 9 ) | +/* (((mode->CrtcVSyncStart-1) & 0x400) >> 8 ) | */ + (((mode->CrtcVBlankStart-1)& 0x400) >> 8 ) | +/* (((mode->CrtcVBlankStart-1)& 0x400) >> 7 ); */ + (((mode->CrtcVSyncStart) & 0x400) >> 7 ); + + /* Set extended horizontal overflow register */ + pReg->sisRegs3C4[0x12] &= 0xE0; + pReg->sisRegs3C4[0x12] |= ( + (((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8 | + (((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7 | +/* (((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6 | */ + (((mode->CrtcHBlankStart >> 3) - 1) & 0x100) >> 6 | + ((mode->CrtcHSyncStart >> 3) & 0x100) >> 5 | + (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 2); + } + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "HDisplay %d HSyncStart %d HSyncEnd %d HTotal %d\n", + mode->CrtcHDisplay, mode->CrtcHSyncStart, + mode->CrtcHSyncEnd, mode->CrtcHTotal); + xf86DrvMsg(0, X_INFO, "HBlankSt %d HBlankE %d\n", + mode->CrtcHBlankStart, mode->CrtcHBlankEnd); + + xf86DrvMsg(0, X_INFO, "VDisplay %d VSyncStart %d VSyncEnd %d VTotal %d\n", + mode->CrtcVDisplay, mode->CrtcVSyncStart, + mode->CrtcVSyncEnd, mode->CrtcVTotal); + xf86DrvMsg(0, X_INFO, "VBlankSt %d VBlankE %d\n", + mode->CrtcVBlankStart, mode->CrtcVBlankEnd); +#endif + + /* enable (or disable) line compare */ + if(mode->CrtcVDisplay >= 1024) + pReg->sisRegs3C4[0x38] |= 0x04; + else + pReg->sisRegs3C4[0x38] &= 0xFB; + + /* Enable (or disable) high speed DCLK (some 6326 and 530/620 only) */ + if( ( (pSiS->Chipset == PCI_CHIP_SIS6326) && + ( (pSiS->ChipRev == 0xd0) || (pSiS->ChipRev == 0xd1) || + (pSiS->ChipRev == 0xd2) || (pSiS->ChipRev == 0x92) || + (pSiS->Flags & A6326REVAB) ) ) || + (pSiS->oldChipset > OC_SIS6326) ) { + if( (pSiS->CurrentLayout.bitsPerPixel == 24) || + (pSiS->CurrentLayout.bitsPerPixel == 32) || + (mode->CrtcHDisplay >= 1280) ) + pReg->sisRegs3C4[0x3E] |= 0x01; + else + pReg->sisRegs3C4[0x3E] &= 0xFE; + } + + /* We use the internal VCLK */ + pReg->sisRegs3C4[0x38] &= 0xFC; + + /* Set VCLK */ + if((sis6326tvmode) || (sis6326himode)) { + /* TW: For our built-in modes, the calculation is not suitable */ + if(sis6326himode) { + if((strcmp(mode->name, "SIS1280x1024-75") == 0)) { + pReg->sisRegs3C4[0x2A] = 0x5d; /* 1280x1024-75 */ + pReg->sisRegs3C4[0x2B] = 0xa4; + } else { + pReg->sisRegs3C4[0x2A] = 0x59; /* 1600x1200-60 */ + pReg->sisRegs3C4[0x2B] = 0xa3; + } + pReg->sisRegs3C4[0x13] &= ~0x40; + } else { + if(pSiS->SiS6326Flags & SIS6326_TVPAL) { + /* PAL: 31.500 Mhz */ + if((strcmp(mode->name, "PAL800x600U") == 0)) { + pReg->sisRegs3C4[0x2A] = 0x46; + pReg->sisRegs3C4[0x2B] = 0x49; + } else { + pReg->sisRegs3C4[0x2A] = 0xab; + pReg->sisRegs3C4[0x2B] = 0xe9; + } + pReg->sisRegs3C4[0x13] &= ~0x40; + } else { + /* NTSC: 27.000 Mhz */ + if((strcmp(mode->name, "NTSC640x480U") == 0)) { + pReg->sisRegs3C4[0x2A] = 0x5a; + pReg->sisRegs3C4[0x2B] = 0x65; + } else { + pReg->sisRegs3C4[0x2A] = 0x29; + pReg->sisRegs3C4[0x2B] = 0xe2; + } + pReg->sisRegs3C4[0x13] |= 0x40; + } + } + } else if(SiS_compute_vclk(clock, &num, &denum, &div, &sbit, &scale)) { + pReg->sisRegs3C4[0x2A] = (num - 1) & 0x7f ; + pReg->sisRegs3C4[0x2A] |= (div == 2) ? 0x80 : 0; + pReg->sisRegs3C4[0x2B] = ((denum - 1) & 0x1f); + pReg->sisRegs3C4[0x2B] |= (((scale -1) & 3) << 5); + + /* When setting VCLK, we should set SR13 first */ + if(sbit) + pReg->sisRegs3C4[0x13] |= 0x40; + else + pReg->sisRegs3C4[0x13] &= 0xBF; + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "2a: %x 2b: %x 13: %x clock %d\n", + pReg->sisRegs3C4[0x2A], pReg->sisRegs3C4[0x2B], pReg->sisRegs3C4[0x13], clock); +#endif + + } else { + /* if SiS_compute_vclk cannot handle the requested clock, try sisCalcClock */ + SiSCalcClock(pScrn, clock, 2, vclk); + + pReg->sisRegs3C4[0x2A] = (vclk[Midx] - 1) & 0x7f; + pReg->sisRegs3C4[0x2A] |= ((vclk[VLDidx] == 2) ? 1 : 0) << 7; + + /* bits [4:0] contain denumerator */ + pReg->sisRegs3C4[0x2B] = (vclk[Nidx] - 1) & 0x1f; + + if (vclk[Pidx] <= 4){ + /* postscale 1,2,3,4 */ + pReg->sisRegs3C4[0x2B] |= (vclk[Pidx] - 1) << 5; + pReg->sisRegs3C4[0x13] &= 0xBF; + } else { + /* postscale 6,8 */ + pReg->sisRegs3C4[0x2B] |= ((vclk[Pidx] / 2) - 1) << 5; + pReg->sisRegs3C4[0x13] |= 0x40; + } + pReg->sisRegs3C4[0x2B] |= 0x80 ; /* gain for high frequency */ + } + + /* High speed DAC */ + if(clock > 135000) + pReg->sisRegs3C4[0x07] |= 0x02; + + /* Programmable Clock */ + pReg->sisRegs3C2 = inb(SISMISCR) | 0x0C; + + /* 1 or 2 cycle DRAM (set by option FastVram) */ + if(pSiS->newFastVram == -1) { + pReg->sisRegs3C4[0x34] |= 0x80; + pReg->sisRegs3C4[0x34] &= ~0x40; + } else if(pSiS->newFastVram == 1) + pReg->sisRegs3C4[0x34] |= 0xC0; + else + pReg->sisRegs3C4[0x34] &= ~0xC0; + + /* Logical line length */ + pSiS->ValidWidth = TRUE; + pReg->sisRegs3C4[0x27] &= 0xCF; + if(pSiS->CurrentLayout.bitsPerPixel == 24) { + /* Invalid logical width */ + pReg->sisRegs3C4[0x27] |= 0x30; + pSiS->ValidWidth = FALSE; + } else { + switch(pScrn->virtualX * (pSiS->CurrentLayout.bitsPerPixel >> 3)) { + case 1024: + pReg->sisRegs3C4[0x27] |= 0x00; + break; + case 2048: + pReg->sisRegs3C4[0x27] |= 0x10; + break; + case 4096: + pReg->sisRegs3C4[0x27] |= 0x20; + break; + default: + /* Invalid logical width */ + pReg->sisRegs3C4[0x27] |= 0x30; + pSiS->ValidWidth = FALSE; + break; + } + } + + /* Acceleration stuff */ + if(!pSiS->NoAccel) { + pReg->sisRegs3C4[0x27] |= 0x40; /* Enable engine programming registers */ + if( (pSiS->TurboQueue) && /* Handle TurboQueue */ + ( (pSiS->Chipset != PCI_CHIP_SIS530) || + (pSiS->CurrentLayout.bitsPerPixel != 24) ) ) { + pReg->sisRegs3C4[0x27] |= 0x80; /* Enable TQ */ + if((pSiS->Chipset == PCI_CHIP_SIS530) || + ((pSiS->Chipset == PCI_CHIP_SIS6326 && + (pSiS->ChipRev == 0xd0 || pSiS->ChipRev == 0xd1 || + pSiS->ChipRev == 0xd2 || pSiS->ChipRev == 0x92 || + pSiS->ChipRev == 0x0a || pSiS->ChipRev == 0x1a || + pSiS->ChipRev == 0x2a || pSiS->ChipRev == 0x0b || + pSiS->ChipRev == 0x1b || pSiS->ChipRev == 0x2b) ) ) ) { + /* pReg->sisRegs3C4[0x3D] |= 0x80; */ /* Queue is 62K (530/620 specs) */ + pReg->sisRegs3C4[0x3D] &= 0x7F; /* Queue is 30K (530/620 specs) */ + } + /* TW: Locate the TQ at the beginning of the last 64K block of + * video RAM. The address is to be specified in 32K steps. + */ + pReg->sisRegs3C4[0x2C] = (pScrn->videoRam - 64) / 32; + if(pSiS->Chipset != PCI_CHIP_SIS530) { /* 530/620: Reserved (don't touch) */ + pReg->sisRegs3C4[0x3C] &= 0xFC; /* 6326: Queue is all for 2D */ + } /* 5597: Must be 0 */ + } else { + pReg->sisRegs3C4[0x27] &= 0x7F; + } + } + + /* TW: No idea what this does. The Windows driver does it, so we do it as well */ + if(pSiS->Chipset == PCI_CHIP_SIS6326) { + if((pSiS->ChipRev == 0xd0) || (pSiS->ChipRev == 0xd1) || + (pSiS->ChipRev == 0xd2) || (pSiS->ChipRev == 0x92) || + (pSiS->Flags & A6326REVAB)) { + if((pSiS->Flags & (SYNCDRAM | RAMFLAG)) == (SYNCDRAM | RAMFLAG)) { + if(!(pReg->sisRegs3C4[0x0E] & 0x03)) { + pReg->sisRegs3C4[0x3E] |= 0x02; + } + } + } + } + + + /* Set memclock */ +#if 0 + /* TW: We don't need to do this; the SetMClk option was not used since 4.0. */ + if((pSiS->Chipset == PCI_CHIP_SIS5597) || (pSiS->Chipset == PCI_CHIP_SIS6326)) { + if(pSiS->MemClock > 66000) { + SiSCalcClock(pScrn, pSiS->MemClock, 1, vclk); + + pReg->sisRegs3C4[0x28] = (vclk[Midx] - 1) & 0x7f ; + pReg->sisRegs3C4[0x28] |= ((vclk[VLDidx] == 2 ) ? 1 : 0 ) << 7 ; + pReg->sisRegs3C4[0x29] = (vclk[Nidx] -1) & 0x1f ; /* bits [4:0] contain denumerator -MC */ + if(vclk[Pidx] <= 4) { + pReg->sisRegs3C4[0x29] |= (vclk[Pidx] - 1) << 5 ; /* postscale 1,2,3,4 */ + pReg->sisRegs3C4[0x13] &= 0x7F; + } else { + pReg->sisRegs3C4[0x29] |= ((vclk[Pidx] / 2) - 1) << 5 ; /* postscale 6,8 */ + pReg->sisRegs3C4[0x13] |= 0x80; + } + /* Check programmed memory clock. Enable only to check the above code */ +/* + mclk = 14318 * ((pReg->sisRegs3C4[0x28] & 0x7f) + 1); + mclk /= ((pReg->sisRegs3C4[0x29] & 0x0f) + 1); + if(!(pReg->sisRegs3C4[0x13] & 0x80)) { + mclk /= (((pReg->sisRegs3C4[0x29] & 0x60) >> 5) + 1); + } else { + if ((pReg->sisRegs3C4[0x29] & 0x60) == 0x40) mclk /= 6; + if ((pReg->sisRegs3C4[0x29] & 0x60) == 0x60) mclk /= 8; + } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,2, + "Setting memory clock to %.3f MHz\n", + mclk/1000.0); +*/ + } + } +#endif + + /* TW: set threshold values (rewritten) */ + /* + * CPU/CRT Threshold: FIFO + * MCLK ___________ VCLK + * cpu/engine <---o o--------->|___________| -----------> CRT + * ^ ^ ^ ^ + * \ / | | + * \ / |< gap >| + * \ / | | + * selector switch Thrsh. low high + * + * CRT consumes the data in the FIFO during scanline display. When the + * amount of data in the FIFO reaches the Threshold low value, the selector + * switch will switch to the right, and the FIFO will be refilled with data. + * When the amount of data in the FIFO reaches the Threshold high value, the + * selector switch will switch to the left and allows the CPU and the chip + * engines to access video RAM. + * + * The Threshold low values should be increased at higher bpps, simply because + * there is more data needed for the CRT. When Threshold low and high are very + * close to each other, the selector switch will be activated more often, which + * decreases performance. + * + */ + switch(pSiS->Chipset) { + case PCI_CHIP_SIS5597: factor = 65; break; + case PCI_CHIP_SIS6326: factor = 30; break; + case PCI_CHIP_SIS530: factor = (pSiS->Flags & UMA) ? 60 : 30; break; + default: factor = (pScrn->videoRam > (1024*1024)) ? 24 : 12; + } + a = width * height * rate * 1.40 * factor * ((pSiS->CurrentLayout.bitsPerPixel + 1) / 8); + b = (mclk / 1000) * 999488.0 * (buswidth / 8); + c = ((a / b) + 1.0) / 2; + d = (int)c + 2; + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, + "Debug: w %d h %d r %d mclk %d bus %d factor %d bpp %d\n", + width, height, rate, mclk/1000, buswidth, factor, + pSiS->CurrentLayout.bitsPerPixel); + xf86DrvMsg(0, X_INFO, "Debug: a %f b %f c %f d %d (flags %x)\n", + a, b, c, d, pSiS->Flags); +#endif + + CRT_CPUthresholdLow = d; + if((pSiS->Flags & (RAMFLAG | SYNCDRAM)) == (RAMFLAG | SYNCDRAM)) { + CRT_CPUthresholdLow += 2; + } + CRT_CPUthresholdHigh = CRT_CPUthresholdLow + 3; + + CRT_ENGthreshold = 0x0F; + +#ifdef TWDEBUG + xf86DrvMsg(0, X_INFO, "Debug: Thlow %d thhigh %d\n", + CRT_CPUthresholdLow, CRT_CPUthresholdHigh); +#endif + +#if 0 /* TW: See comment in sis_dac.c on why this is commented */ + if(pSiS->Chipset == PCI_CHIP_SIS530) { + if((pSiS->oldChipset == OC_SIS530A) && + (pSiS->Flags & UMA) && + (mclk == 100000) && + (pSiS->Flags & ESS137xPRESENT)) { + if(!(pSiS->Flags & SECRETFLAG)) index = 0; + if((temp = SiS_CalcSpecial530Threshold(pSiS, mode, index)) { + CRT_CPUthresholdLow = temp; + break; + } + } + } +#endif + + switch(pSiS->Chipset) { + case PCI_CHIP_SIS530: + if(CRT_CPUthresholdLow > 0x1f) CRT_CPUthresholdLow = 0x1f; + CRT_CPUthresholdHigh = 0x1f; + break; + case PCI_CHIP_SIS5597: + case PCI_CHIP_SIS6326: + default: + if(CRT_CPUthresholdLow > 0x0f) CRT_CPUthresholdLow = 0x0f; + if(CRT_CPUthresholdHigh > 0x0f) CRT_CPUthresholdHigh = 0x0f; + } + + pReg->sisRegs3C4[0x08] = ((CRT_CPUthresholdLow & 0x0F) << 4) | + (CRT_ENGthreshold & 0x0F); + + pReg->sisRegs3C4[0x09] &= 0xF0; + pReg->sisRegs3C4[0x09] |= (CRT_CPUthresholdHigh & 0x0F); + + pReg->sisRegs3C4[0x3F] &= 0xEB; + pReg->sisRegs3C4[0x3F] |= (CRT_CPUthresholdHigh & 0x10) | + ((CRT_CPUthresholdLow & 0x10) >> 2); + + if(pSiS->oldChipset >= OC_SIS530A) { + pReg->sisRegs3C4[0x3F] &= 0xDF; + pReg->sisRegs3C4[0x3F] |= 0x58; + } + + /* TW: Set SiS6326 TV registers */ + if((pSiS->Chipset == PCI_CHIP_SIS6326) && (sis6326tvmode)) { + unsigned char tmp; + int index=0, i, j, k; + + if(pSiS->SiS6326Flags & SIS6326_TVPAL) { + pReg->sisRegs3C4[0x0D] |= 0x04; + switch(width) { + case 800: + if((strcmp(mode->name, "PAL800x600U") == 0)) index = 4; + else index = 3; + break; + case 720: + index = 5; + break; + case 640: + default: + index = 2; + break; + } + for(i=0; i<14; i++) { + pReg->sis6326tv[SiS6326TVRegs1[i]] = SiS6326TVRegs1_PAL[index][i]; + } + } else { + pReg->sisRegs3C4[0x0D] &= ~0x04; + if((strcmp(mode->name, "NTSC640x480U") == 0)) index = 5; + else index = 4; + for(i=0; i<14; i++) { + pReg->sis6326tv[SiS6326TVRegs1[i]] = SiS6326TVRegs1_NTSC[index][i]; + } + } + tmp = pReg->sis6326tv[0x43]; + if(pSiS->SiS6326Flags & SIS6326_TVCVBS) tmp |= 0x10; + tmp |= 0x08; + pReg->sis6326tv[0x43] = tmp; + j = 0; k = 0; + for(i=0; i<=0x44; i++) { + if(SiS6326TVRegs1[j] == i) { + j++; + continue; + } + if(pSiS->SiS6326Flags & SIS6326_TVPAL) { + tmp = SiS6326TVRegs2_PAL[index][k]; + } else { + tmp = SiS6326TVRegs2_NTSC[index][k]; + } + pReg->sis6326tv[i] = tmp; + k++; + } + pReg->sis6326tv[0x43] |= 0x08; + if((pSiS->ChipRev == 0xc1) || (pSiS->ChipRev == 0xc2)) { + pReg->sis6326tv[0x43] &= ~0x08; + } + + tmp = pReg->sis6326tv[0]; + tmp |= 0x18; + if(pSiS->SiS6326Flags & SIS6326_TVCVBS) tmp &= ~0x10; + else tmp &= ~0x08; + tmp |= 0x04; + pReg->sis6326tv[0] = tmp; + } + + return(TRUE); +} + +/* TW: Init a mode for SiS 300 and 310/325 series + * The original intention of the followling procedure was + * to initialize various registers for the selected mode. + * This was actually done to a structure, not the hardware. + * (SiSRestore would write the structure to the hardware + * registers.) + * This function is now only used for setting up some + * variables (eg. scrnOffset). + */ +Bool +SIS300Init(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + SISPtr pSiS = SISPTR(pScrn); + SISRegPtr pReg = &pSiS->ModeReg; + unsigned short temp; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, "SIS300Init()\n"); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, + "virtualX = %d depth = %d Logical width = %d\n", + pScrn->virtualX, pSiS->CurrentLayout.bitsPerPixel, + pScrn->virtualX * pSiS->CurrentLayout.bitsPerPixel/8); + + /* Copy current register settings to structure */ + (*pSiS->SiSSave)(pScrn, pReg); + + /* TW: Calculate Offset/Display Pitch */ + pSiS->scrnOffset = pSiS->CurrentLayout.displayWidth * + ((pSiS->CurrentLayout.bitsPerPixel+7)/8); + pSiS->scrnPitch = pSiS->scrnOffset; + if (mode->Flags & V_INTERLACE) pSiS->scrnPitch <<= 1; + +#ifdef UNLOCK_ALWAYS + outSISIDXREG(SISSR, 0x05, 0x86); +#endif + + switch(pSiS->CurrentLayout.bitsPerPixel) { + case 8: + pSiS->DstColor = 0x0000; + pSiS->SiS310_AccelDepth = 0x00000000; + break; + case 16: + if(pSiS->CurrentLayout.depth == 15) + pSiS->DstColor = (short) 0x4000; + else + pSiS->DstColor = (short) 0x8000; + pSiS->SiS310_AccelDepth = 0x00010000; + break; + case 24: + break; + case 32: + pSiS->DstColor = (short) 0xC000; + pSiS->SiS310_AccelDepth = 0x00020000; + break; + } + + /* TW: Enable PCI LINEAR ADDRESSING (0x80), MMIO (0x01), PCI_IO (0x20) */ + pReg->sisRegs3C4[0x20] = 0xA1; + +/* TW: Now initialize TurboQueue. TB is always located at the very top of + * the videoRAM (notably NOT the x framebuffer memory, which can/should + * be limited by MaxXFbMem when using DRI). Also, enable the accelerators. + */ + if (!pSiS->NoAccel) { + pReg->sisRegs3C4[0x1E] |= 0x42; /* TW: Enable 2D accelerator */ + pReg->sisRegs3C4[0x1E] |= 0x18; /* TW: Enable 3D accelerator */ + switch (pSiS->VGAEngine) { + case SIS_300_VGA: + if(pSiS->TurboQueue) { /* set Turbo Queue as 512k */ + temp = ((pScrn->videoRam/64)-8); /* TW: 8=512k, 4=256k, 2=128k, 1=64k */ + pReg->sisRegs3C4[0x26] = temp & 0xFF; + pReg->sisRegs3C4[0x27] = + (pReg->sisRegs3C4[0x27] & 0xfc) | (((temp >> 8) & 3) | 0xF0); + } /* TW: line above new for saving D2&3 of status register */ + break; + case SIS_315_VGA: + /* See comments in sis_driver.c */ + pReg->sisRegs3C4[0x27] = 0x1F; + pReg->sisRegs3C4[0x26] = 0x22; + pReg->sisMMIO85C0 = (pScrn->videoRam - 512) * 1024; + break; + } + } + + return(TRUE); +} + +int +SISDoSense(ScrnInfoPtr pScrn, int tempbl, int tempbh, int tempcl, int tempch) +{ + SISPtr pSiS = SISPTR(pScrn); + int temp; + + outSISIDXREG(SISPART4,0x11,tempbl); + temp = tempbh | tempcl; + setSISIDXREG(SISPART4,0x10,0xe0,temp); + usleep(200000); + tempch &= 0x7f; + inSISIDXREG(SISPART4,0x03,temp); + temp ^= 0x0e; + temp &= tempch; + return(temp); +} + +/* TW: Sense connected devices on 30x */ +void SISSense30x(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char backupP4_0d,biosflag; + unsigned char testsvhs_tempbl, testsvhs_tempbh; + unsigned char testsvhs_tempcl, testsvhs_tempch; + unsigned char testcvbs_tempbl, testcvbs_tempbh; + unsigned char testcvbs_tempcl, testcvbs_tempch; + unsigned char testvga2_tempbl, testvga2_tempbh; + unsigned char testvga2_tempcl, testvga2_tempch; + int myflag, result; + unsigned short temp; + + inSISIDXREG(SISPART4,0x0d,backupP4_0d); + outSISIDXREG(SISPART4,0x0d,(backupP4_0d | 0x04)); + + if(pSiS->VGAEngine == SIS_315_VGA) { + if(pSiS->sishw_ext.UseROM) { + temp = 0xf3; + if(pSiS->Chipset == PCI_CHIP_SIS330) temp = 0x11b; + if(pSiS->BIOS[temp] & 0x08) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "SiS30x: Video bridge has (unsupported) DVI combo connector\n"); + orSISIDXREG(SISCR, 0x32, 0x80); + } else { + andSISIDXREG(SISCR, 0x32, 0x7f); + } + } + } + + if(pSiS->VGAEngine == SIS_300_VGA) { + + if(pSiS->sishw_ext.UseROM) { + testvga2_tempbh = pSiS->BIOS[0xf9]; testvga2_tempbl = pSiS->BIOS[0xf8]; + testsvhs_tempbh = pSiS->BIOS[0xfb]; testsvhs_tempbl = pSiS->BIOS[0xfa]; + testcvbs_tempbh = pSiS->BIOS[0xfd]; testcvbs_tempbl = pSiS->BIOS[0xfc]; + biosflag = pSiS->BIOS[0xfe]; + } else { + testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1; + testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9; + testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3; + biosflag = 0; + } + if(pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) { + testvga2_tempbh = 0x01; testvga2_tempbl = 0x90; + testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b; + testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74; + } + inSISIDXREG(SISPART4,0x01,myflag); + if(myflag & 0x04) { + testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd; + testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd; + testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee; + } + testvga2_tempch = 0x0e; testvga2_tempcl = 0x08; + testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04; + testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04; + + } else if((pSiS->Chipset == PCI_CHIP_SIS315) || + (pSiS->Chipset == PCI_CHIP_SIS315H) || + (pSiS->Chipset == PCI_CHIP_SIS315PRO)) { + + if(pSiS->sishw_ext.UseROM) { + testvga2_tempbh = pSiS->BIOS[0xbe]; testvga2_tempbl = pSiS->BIOS[0xbd]; + testsvhs_tempbh = pSiS->BIOS[0xc0]; testsvhs_tempbl = pSiS->BIOS[0xbf]; + testcvbs_tempbh = pSiS->BIOS[0xc2]; testcvbs_tempbl = pSiS->BIOS[0xc1]; + biosflag = pSiS->BIOS[0xf3]; + } else { + testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1; + testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9; + testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3; + biosflag = 0; + } + if(pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) { + if(pSiS->sishw_ext.UseROM) { + testvga2_tempbh = pSiS->BIOS[0xc4]; testvga2_tempbl = pSiS->BIOS[0xc3]; + testsvhs_tempbh = pSiS->BIOS[0xc6]; testsvhs_tempbl = pSiS->BIOS[0xc5]; + testcvbs_tempbh = pSiS->BIOS[0xc8]; testcvbs_tempbl = pSiS->BIOS[0xc7]; + } else { + testvga2_tempbh = 0x01; testvga2_tempbl = 0x90; + testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b; + testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74; + } + } + inSISIDXREG(SISPART4,0x01,myflag); + if(myflag & 0x04) { + testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd; + testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd; + testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee; + } + testvga2_tempch = 0x0e; testvga2_tempcl = 0x08; + testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04; + testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04; + + } else if(pSiS->Chipset == PCI_CHIP_SIS330) { + + if(pSiS->sishw_ext.UseROM) { + testvga2_tempbh = pSiS->BIOS[0xe6]; testvga2_tempbl = pSiS->BIOS[0xe5]; + testsvhs_tempbh = pSiS->BIOS[0xe8]; testsvhs_tempbl = pSiS->BIOS[0xe7]; + testcvbs_tempbh = pSiS->BIOS[0xea]; testcvbs_tempbl = pSiS->BIOS[0xe9]; + biosflag = pSiS->BIOS[0x11b]; + } else { + testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1; + testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9; + testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3; + biosflag = 0; + } + if(pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) { + if(pSiS->sishw_ext.UseROM) { + testvga2_tempbh = pSiS->BIOS[0xec]; testvga2_tempbl = pSiS->BIOS[0xeb]; + testsvhs_tempbh = pSiS->BIOS[0xee]; testsvhs_tempbl = pSiS->BIOS[0xed]; + testcvbs_tempbh = pSiS->BIOS[0xf0]; testcvbs_tempbl = pSiS->BIOS[0xef]; + } else { + testvga2_tempbh = 0x01; testvga2_tempbl = 0x90; + testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b; + testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74; + } + } + inSISIDXREG(SISPART4,0x01,myflag); + if(myflag & 0x04) { + testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd; + testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd; + testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee; + } + testvga2_tempch = 0x0e; testvga2_tempcl = 0x08; + testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04; + testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04; + + } else { /* 550?, 650, 740 */ + + if(pSiS->sishw_ext.UseROM) { + testvga2_tempbh = pSiS->BIOS[0xbe]; testvga2_tempbl = pSiS->BIOS[0xbd]; + testsvhs_tempbh = pSiS->BIOS[0xc0]; testsvhs_tempbl = pSiS->BIOS[0xbf]; + testcvbs_tempbh = pSiS->BIOS[0xc2]; testcvbs_tempbl = pSiS->BIOS[0xc1]; + biosflag = pSiS->BIOS[0xf3]; + } else { + testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1; + testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9; + testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3; + biosflag = 0; + } + testvga2_tempch = 0x0e; testvga2_tempcl = 0x08; + testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04; + testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04; + + /* TW: Different BIOS versions use different values for the 301LV. + These values are from the newest versions 1.10.6? and 1.10.7?. + I have no idea if these values are suitable for the 301B as well. + */ + + if(pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) { + if(pSiS->sishw_ext.UseROM) { + testvga2_tempbh = pSiS->BIOS[0xc4]; testvga2_tempbl = pSiS->BIOS[0xc3]; + testsvhs_tempbh = pSiS->BIOS[0xc6]; testsvhs_tempbl = pSiS->BIOS[0xc5]; + testcvbs_tempbh = pSiS->BIOS[0xc8]; testcvbs_tempbl = pSiS->BIOS[0xc7]; + biosflag = pSiS->BIOS[0xf3]; + } else { + testvga2_tempbh = 0x01; testvga2_tempbl = 0x90; + testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00; + testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00; + biosflag = 0; + } + testvga2_tempch = 0x0e; testvga2_tempcl = 0x08; + testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08; + testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08; + } + + } + + /* TW: No VGA2 or SCART on LV bridges */ + if(pSiS->VBFlags & (VB_30xLV|VB_30xLVX)) { + testvga2_tempbh = testvga2_tempbl = 0x00; + testvga2_tempch = testvga2_tempcl = 0x00; + } + + if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) { +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "SiS30x: Scanning for VGA2/SCART (%x %x %x %x)\n", + testvga2_tempbh, testvga2_tempbl, testvga2_tempch, testvga2_tempcl); +#endif + + result = SISDoSense(pScrn, testvga2_tempbl, testvga2_tempbh, + testvga2_tempcl, testvga2_tempch); + if(result) { + if(biosflag & 0x01) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "SiS30x: Detected TV connected to SCART output\n"); + pSiS->VBFlags |= TV_SCART; + orSISIDXREG(SISCR, 0x32, 0x04); + pSiS->postVBCR32 |= 0x04; + } else if(!(pSiS->VBFlags & (VB_30xLV|VB_30xLVX))) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "SiS30x: Detected secondary VGA connection\n"); + pSiS->VBFlags |= VGA2_CONNECTED; + orSISIDXREG(SISCR, 0x32, 0x10); + pSiS->postVBCR32 |= 0x10; + } + } + } + +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "SiS30x: Scanning for TV (%x %x %x %x; %x %x %x %x)\n", + testsvhs_tempbh, testsvhs_tempbl, testsvhs_tempch, testsvhs_tempcl, + testcvbs_tempbh, testcvbs_tempbl, testcvbs_tempch, testcvbs_tempcl); +#endif + + result = SISDoSense(pScrn, testsvhs_tempbl, testsvhs_tempbh, + testsvhs_tempcl, testsvhs_tempch); + if(result) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "SiS30x: Detected TV connected to SVIDEO output\n"); + /* TW: So we can be sure that there IS a SVIDEO output */ + pSiS->VBFlags |= TV_SVIDEO; + orSISIDXREG(SISCR, 0x32, 0x02); + pSiS->postVBCR32 |= 0x02; + } + + if((biosflag & 0x02) || (!(result))) { + + result = SISDoSense(pScrn, testcvbs_tempbl, testcvbs_tempbh, + testcvbs_tempcl, testcvbs_tempch); + if(result) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "SiS30x: Detected TV connected to COMPOSITE output\n"); + /* TW: So we can be sure that there IS a CVBS output */ + pSiS->VBFlags |= TV_AVIDEO; + orSISIDXREG(SISCR, 0x32, 0x01); + pSiS->postVBCR32 |= 0x01; + } + } + SISDoSense(pScrn, 0, 0, 0, 0); + + outSISIDXREG(SISPART4,0x0d,backupP4_0d); +} + +static void +SiS6326TVDelay(ScrnInfoPtr pScrn, int delay) +{ + SISPtr pSiS = SISPTR(pScrn); + int i; + unsigned char temp; + + for(i=0; i<delay; i++) { + inSISIDXREG(SISSR, 0x05, temp); + } +} + +int +SIS6326DoSense(ScrnInfoPtr pScrn, int tempbh, int tempbl, int tempch, int tempcl) +{ + unsigned char temp; + + SiS6326SetTVReg(pScrn, 0x42, tempbl); + temp = SiS6326GetTVReg(pScrn, 0x43); + temp &= 0xfc; + temp |= tempbh; + SiS6326SetTVReg(pScrn, 0x43, temp); + SiS6326TVDelay(pScrn, 0x1000); + temp = SiS6326GetTVReg(pScrn, 0x43); + temp |= 0x04; + SiS6326SetTVReg(pScrn, 0x43, temp); + SiS6326TVDelay(pScrn, 0x8000); + temp = SiS6326GetTVReg(pScrn, 0x44); + if(!(tempch & temp)) tempcl = 0; + return(tempcl); +} + +void +SISSense6326(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + unsigned char temp; + int result; + + pSiS->SiS6326Flags &= (SIS6326_HASTV | SIS6326_TVPAL); + temp = SiS6326GetTVReg(pScrn, 0x43); + temp &= 0xfb; + SiS6326SetTVReg(pScrn, 0x43, temp); + result = SIS6326DoSense(pScrn, 0x01, 0xb0, 0x06, SIS6326_TVSVIDEO); /* 0x02 */ + pSiS->SiS6326Flags |= result; + result = SIS6326DoSense(pScrn, 0x01, 0xa0, 0x01, SIS6326_TVCVBS); /* 0x04 */ + pSiS->SiS6326Flags |= result; + temp = SiS6326GetTVReg(pScrn, 0x43); + temp &= 0xfb; + SiS6326SetTVReg(pScrn, 0x43, temp); + if(pSiS->SiS6326Flags & (SIS6326_TVSVIDEO | SIS6326_TVCVBS)) { + pSiS->SiS6326Flags |= SIS6326_TVDETECTED; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "SiS6326: Detected TV connected to %s output\n", + (pSiS->SiS6326Flags & SIS6326_TVSVIDEO) ? + "SVIDEO" : "COMPOSITE"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "SiS6326: No TV detected\n"); + } +} + +/* TW: Detect video bridge and set VBFlags accordingly */ +void SISVGAPreInit(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + int temp,temp1,temp2; + int upperlimitlvds, lowerlimitlvds; + int upperlimitch, lowerlimitch; + int chronteltype, chrontelidreg; + static const char *ChrontelTypeStr[] = { + "7004", + "7005", + "7007", + "7006", + "7008", + "7013", + "7019", + "7020", + "(unknown)" + }; + + switch (pSiS->Chipset) { + case PCI_CHIP_SIS300: + case PCI_CHIP_SIS630: + case PCI_CHIP_SIS540: + case PCI_CHIP_SIS550: + case PCI_CHIP_SIS650: + case PCI_CHIP_SIS315: + case PCI_CHIP_SIS315H: + case PCI_CHIP_SIS315PRO: + case PCI_CHIP_SIS330: + pSiS->ModeInit = SIS300Init; + break; + default: + pSiS->ModeInit = SISInit; + } + + if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { + unsigned char sr0d; + inSISIDXREG(SISSR, 0x0d, sr0d); + if(sr0d & 0x04) { + pSiS->SiS6326Flags |= SIS6326_TVPAL; + } + SISSense6326(pScrn); + } + + pSiS->VBFlags = 0; /* reset VBFlags */ + + /* TW: Videobridges only available for 300/310/325 series */ + if((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) + return; + + inSISIDXREG(SISPART4, 0x00, temp); + temp &= 0x0F; + if (temp == 1) { + inSISIDXREG(SISPART4, 0x01, temp1); + temp1 &= 0xff; + if (temp1 >= 0xE0) { + pSiS->VBFlags |= VB_30xLVX; + pSiS->sishw_ext.ujVBChipID = VB_CHIP_301LVX; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected SiS301LVX video bridge (Revision 0x%x)\n", + temp1); + } else if (temp1 >= 0xD0) { + pSiS->VBFlags |= VB_30xLV; + pSiS->sishw_ext.ujVBChipID = VB_CHIP_301LV; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected SiS301LV video bridge (Revision 0x%x)\n", + temp1); + } else if (temp1 >= 0xB0) { + pSiS->VBFlags |= VB_301B; + pSiS->sishw_ext.ujVBChipID = VB_CHIP_301B; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected SiS301B video bridge (Revision 0x%x)\n", + temp1); + } else { + pSiS->VBFlags |= VB_301; + pSiS->sishw_ext.ujVBChipID = VB_CHIP_301; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected SiS301 video bridge (Revision 0x%x)\n", + temp1); + } + if (pSiS->VBFlags & (VB_30xLV | VB_30xLVX)) { + inSISIDXREG(SISCR, 0x38, temp); + if((temp & 0x03) == 0x03) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "[SiS301LV/LVX: LCD channel A]\n"); + } + } + + SISSense30x(pScrn); + + } else if (temp == 2) { + + inSISIDXREG(SISPART4, 0x01, temp1); + temp1 &= 0xff; + if (temp1 >= 0xE0) { + pSiS->VBFlags |= VB_30xLVX; + pSiS->sishw_ext.ujVBChipID = VB_CHIP_302LVX; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected SiS302LVX video bridge (Revision 0x%x)\n", + temp1); + } else if (temp1 >= 0xD0) { + pSiS->VBFlags |= VB_30xLV; + pSiS->sishw_ext.ujVBChipID = VB_CHIP_302LV; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected SiS302LV video bridge (Revision 0x%x)\n", + temp1); + } else { + pSiS->VBFlags |= VB_302B; + pSiS->sishw_ext.ujVBChipID = VB_CHIP_302B; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected SiS302B video bridge (Revision 0x%x)\n", + temp1); + } + if (pSiS->VBFlags & (VB_302B | VB_30xLV | VB_30xLVX)) { + inSISIDXREG(SISCR, 0x38, temp); + if((temp & 0x03) == 0x03) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "[SiS302B/LV/LVX: LCD channel A]\n"); + } + } + + SISSense30x(pScrn); + + } else if (temp == 3) { + + pSiS->VBFlags |= VB_303; + pSiS->sishw_ext.ujVBChipID = VB_CHIP_303; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected SiS303 video bridge\n"); + + } else { + + pSiS->sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN; + inSISIDXREG(SISCR, 0x37, temp); + temp = (temp >> 1) & 0x07; +#if 0 /* TW: This does not seem to be used on any machine */ + if ( (temp == 0) || (temp == 1)) { + pSiS->VBFlags|=VB_301; /* TW: 301 ? */ + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected SiS301 video bridge (Irregular bridge type %d)\n", temp); + } +#endif + if(pSiS->VGAEngine == SIS_300_VGA) { + lowerlimitlvds = 2; upperlimitlvds = 4; + lowerlimitch = 4; upperlimitch = 5; + chronteltype = 1; chrontelidreg = 0x25; + } else { + lowerlimitlvds = 2; upperlimitlvds = 3; + lowerlimitch = 3; upperlimitch = 3; + chronteltype = 2; chrontelidreg = 0x4b; + } + + if((temp >= lowerlimitlvds) && (temp <= upperlimitlvds)) { + pSiS->VBFlags |= VB_LVDS; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected LVDS transmitter (Bridge type %d)\n", temp); + if(pSiS->Chipset == PCI_CHIP_SIS650) { + inSISIDXREG(SISCR, 0x38, temp1); + if(temp1 & 0x02) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "[LVDS: LCD channel A]\n"); + } + if(temp1 & 0x08) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "[LVDS: HDTV]\n"); + } + if(temp1 & 0x08) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "[LVDS: SCART]\n"); + } + } + } + if((temp >= lowerlimitch) && (temp <= upperlimitch)) { + /* TW: Set global for init301.c */ + pSiS->SiS_Pr->SiS_IF_DEF_CH70xx = chronteltype; + + if(chronteltype == 1) { + /* TW: Do something mysterious (found in Mitac BIOS) */ + SiS_WhatIsThis(pSiS->SiS_Pr, 0x9c); + } + + /* TW: Read Chrontel version number */ + temp1 = SiS_GetCH70xx(pSiS->SiS_Pr, chrontelidreg); + if(chronteltype == 1) { + /* TW: See Chrontel TB31 for explanation */ + temp2 = SiS_GetCH700x(pSiS->SiS_Pr, 0x0e); + if(((temp2 & 0x07) == 0x01) || (temp & 0x04)) { + SiS_SetCH700x(pSiS->SiS_Pr, 0x0b0e); + SiS_DDC2Delay(pSiS->SiS_Pr, 300); + } + temp2 = SiS_GetCH70xx(pSiS->SiS_Pr, chrontelidreg); + if(temp2 != temp1) temp1 = temp2; + } + if(temp1 == 0xFFFF) { /* 0xFFFF = error reading DDC port */ + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Detected Chrontel 70xx, but encountered error reading I2C port\n"); + } + /* TW: We only support device ids 0x19-200; other values may indicate DDC problems */ + else if((temp1 >= 0x19) && (temp1 <= 200)) { + pSiS->VBFlags |= VB_CHRONTEL; + switch (temp1) { + case 0x32: temp2 = 0; pSiS->ChrontelType = CHRONTEL_700x; break; + case 0x3A: temp2 = 1; pSiS->ChrontelType = CHRONTEL_700x; break; + case 0x50: temp2 = 2; pSiS->ChrontelType = CHRONTEL_700x; break; + case 0x2A: temp2 = 3; pSiS->ChrontelType = CHRONTEL_700x; break; + case 0x40: temp2 = 4; pSiS->ChrontelType = CHRONTEL_700x; break; + case 0x22: temp2 = 5; pSiS->ChrontelType = CHRONTEL_700x; break; + case 0x19: temp2 = 6; pSiS->ChrontelType = CHRONTEL_701x; break; + case 0x20: temp2 = 7; pSiS->ChrontelType = CHRONTEL_701x; break; /* ID for 7020? */ + default: temp2 = 8; pSiS->ChrontelType = CHRONTEL_701x; break; + } + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected Chrontel %s TV encoder (ID 0x%02x; bridge type %d)\n", + ChrontelTypeStr[temp2], temp1, temp); + + /* TW: Sense connected TV's */ + + if(chronteltype == 1) { + + /* Chrontel 700x */ + + /* TW: Read power status */ + temp1 = SiS_GetCH700x(pSiS->SiS_Pr, 0x0e); /* Power status */ + if((temp1 & 0x03) != 0x03) { + /* TW: Power all outputs */ + SiS_SetCH700x(pSiS->SiS_Pr, 0x0B0E); + SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); + } + /* TW: Sense connected TV devices */ + SiS_SetCH700x(pSiS->SiS_Pr, 0x0110); + SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); + SiS_SetCH700x(pSiS->SiS_Pr, 0x0010); + SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); + temp1 = SiS_GetCH700x(pSiS->SiS_Pr, 0x10); + if(!(temp1 & 0x08)) temp1 = 0x02; + else if(!(temp1 & 0x02)) temp1 = 0x01; + else temp1 = 0; + + } else { + + /* Chrontel 701x */ + + /* TW: Backup Power register */ + temp1 = SiS_GetCH701x(pSiS->SiS_Pr, 0x49); + + /* TW: Enable TV path */ + SiS_SetCH701x(pSiS->SiS_Pr, 0x2049); + + SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); + + /* TW: Sense connected TV devices */ + temp2 = SiS_GetCH701x(pSiS->SiS_Pr, 0x20); + temp2 |= 0x01; + SiS_SetCH701x(pSiS->SiS_Pr, (temp2 << 8) | 0x20); + + SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); + + temp2 ^= 0x01; + SiS_SetCH701x(pSiS->SiS_Pr, (temp2 << 8) | 0x20); + + SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); + + temp2 = SiS_GetCH701x(pSiS->SiS_Pr, 0x20); + + /* TW: Restore Power register */ + SiS_SetCH701x(pSiS->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: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Chrontel: Detected TV connected to COMPOSITE output\n"); + /* TW: So we can be sure that there IS a CVBS output */ + pSiS->VBFlags |= TV_AVIDEO; + orSISIDXREG(SISCR, 0x32, 0x01); + pSiS->postVBCR32 |= 0x01; + break; + case 0x02: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Chrontel: Detected TV connected to SVIDEO output\n"); + /* TW: So we can be sure that there IS a SVIDEO output */ + pSiS->VBFlags |= TV_SVIDEO; + orSISIDXREG(SISCR, 0x32, 0x02); + pSiS->postVBCR32 |= 0x02; + break; + case 0x04: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Chrontel: Detected TV connected to SCART output or 480i HDTV\n"); + if(pSiS->chtvtype == -1) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Chrontel: Use CHTVType option to select either SCART or HDTV\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Chrontel: Using SCART by default\n"); + pSiS->chtvtype = 1; + } + if(pSiS->chtvtype) + pSiS->VBFlags |= TV_CHSCART; + else + pSiS->VBFlags |= TV_CHHDTV; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Chrontel: No TV detected.\n"); + } + + } else if(temp1==0) { + /* TW: This indicates a communication problem, but it only occures if there + * is no TV attached. + */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Detected Chrontel TV encoder in promiscuous state (DDC/I2C mix-up)\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Chrontel: Unsupported device id (%d) detected\n",temp1); + } + if(chronteltype == 1) { + /* TW: Do something mysterious (found in Mitac BIOS) */ + SiS_WhatIsThis(pSiS->SiS_Pr, 0x00); + } + } + if ((pSiS->VGAEngine == SIS_300_VGA) && (temp == 3)) { + pSiS->VBFlags |= VB_TRUMPION; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Detected Trumpion Zurac (I/II/III) LVDS scaler\n"); + } + if (temp > upperlimitlvds) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Detected unknown bridge type (%d)\n", temp); + } + } +} + + diff --git a/src/sis_video.c b/src/sis_video.c new file mode 100644 index 0000000..35a14a7 --- /dev/null +++ b/src/sis_video.c @@ -0,0 +1,2454 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_video.c,v 1.10 2003/02/04 02:44:29 dawes Exp $ */ +/* + * Xv driver for SiS 300 and 310/325 series. + * + * (Based on the mga Xv driver by Mark Vojkovich and i810 Xv + * driver by Jonathan Bian <jonathan.bian@intel.com>.) + * + * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. + * Copyright 2002,2003 by Thomas Winischhofer, Vienna, Austria. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Sung-Ching Lin <sclin@sis.com.tw> + * + * Thomas Winischhofer <thomas@winischhofer.net>: + * - 310/325 series (315/550/650/651/740/M650) support + * - (possibly incomplete) Xabre (SiS330) support + * - new mode switching code for 300, 310/325 and 330 series + * - many fixes for 300/540/630/730 chipsets, + * - many fixes for 5597/5598, 6326 and 530/620 chipsets, + * - VESA mode switching (deprecated), + * - extended CRT2/video bridge handling support, + * - dual head support on 300, 310/325 and 330 series + * - 650/LVDS (up to 1400x1050), 650/Chrontel 701x support + * - 30xB/30xLV/30xLVX video bridge support (300, 310/325, 330 series) + * - Xv support for 5597/5598, 6326, 530/620 and 310/325 series + * - video overlay enhancements for 300 series + * - TV and hi-res support for the 6326 + * - etc. + * + * TW: This supports the following chipsets: + * SiS300: No registers >0x65, offers one overlay + * SiS630/730: No registers >0x6b, offers two overlays (one used for CRT1, one for CRT2) + * SiS550: Full register range, offers two overlays (one used for CRT1, one for CRT2) + * SiS315: Full register range, offers one overlay (used for both CRT1 and CRT2 alt.) + * SiS650/740: Full register range, offers one overlay (used for both CRT1 and CRT2 alt.) + * SiSM650/651: Full register range, two overlays (one used for CRT1, one for CRT2) + * + * Help for reading the code: + * 315/550/650/740/M650/651 = SIS_315_VGA + * 300/630/730 = SIS_300_VGA + * For chipsets with 2 overlays, hasTwoOverlays will be true + */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "compiler.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "xf86fbman.h" +#include "regionstr.h" + +#include "sis.h" +#include "xf86xv.h" +#include "Xv.h" +#include "xaa.h" +#include "xaalocal.h" +#include "dixstruct.h" +#include "fourcc.h" + +#include "sis_regs.h" + +#define OFF_DELAY 200 /* milliseconds */ +#define FREE_DELAY 60000 + +#define OFF_TIMER 0x01 +#define FREE_TIMER 0x02 +#define CLIENT_VIDEO_ON 0x04 + +#define TIMER_MASK (OFF_TIMER | FREE_TIMER) + +#define WATCHDOG_DELAY 500000 /* Watchdog counter for Vertical Restrace waiting */ + +static XF86VideoAdaptorPtr SISSetupImageVideo(ScreenPtr); +static void SISStopVideo(ScrnInfoPtr, pointer, Bool); +static int SISSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); +static int SISGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); +static void SISQueryBestSize(ScrnInfoPtr, Bool, short, short, short, + short, unsigned int *,unsigned int *, pointer); +static int SISPutImage( ScrnInfoPtr, + short, short, short, short, short, short, short, short, + int, unsigned char*, short, short, Bool, RegionPtr, pointer); +static int SISQueryImageAttributes(ScrnInfoPtr, + int, unsigned short *, unsigned short *, int *, int *); +static void SISVideoTimerCallback(ScrnInfoPtr pScrn, Time now); +static void SISInitOffscreenImages(ScreenPtr pScrn); + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +extern BOOLEAN SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn); + +#define IMAGE_MIN_WIDTH 32 /* Minimum and maximum source image sizes */ +#define IMAGE_MIN_HEIGHT 24 +#define IMAGE_MAX_WIDTH 720 +#define IMAGE_MAX_HEIGHT 576 +#define IMAGE_MAX_WIDTH_M650 1920 +#define IMAGE_MAX_HEIGHT_M650 1080 + +#define OVERLAY_MIN_WIDTH 32 /* Minimum overlay sizes */ +#define OVERLAY_MIN_HEIGHT 24 + +#define DISPMODE_SINGLE1 0x1 /* TW: CRT1 only */ +#define DISPMODE_SINGLE2 0x2 /* TW: CRT2 only */ +#define DISPMODE_MIRROR 0x4 /* TW: CRT1 + CRT2 MIRROR (see note below) */ + +#ifdef SISDUALHEAD +#define HEADOFFSET (pSiS->dhmOffset) +#endif + +/* TW: Note on "MIRROR": + * When using VESA on machines with an enabled video bridge, this means + * a real mirror. CRT1 and CRT2 have the exact same resolution and + * refresh rate. The same applies to modes which require the bridge to + * operate in slave mode. + * When not using VESA and the bridge is not in slave mode otherwise, + * CRT1 and CRT2 have the same resolution but possibly a different + * refresh rate. + */ + +/**************************************************************************** + * Raw register access : These routines directly interact with the sis's + * control aperature. Must not be called until after + * the board's pci memory has been mapped. + ****************************************************************************/ + +#if 0 +static CARD32 _sisread(SISPtr pSiS, CARD32 reg) +{ + return *(pSiS->IOBase + reg); +} + +static void _siswrite(SISPtr pSiS, CARD32 reg, CARD32 data) +{ + *(pSiS->IOBase + reg) = data; +} +#endif + +static CARD8 getvideoreg(SISPtr pSiS, CARD8 reg) +{ + CARD8 ret; + inSISIDXREG(SISVID, reg, ret); + return(ret); +} + +static void setvideoreg(SISPtr pSiS, CARD8 reg, CARD8 data) +{ + outSISIDXREG(SISVID, reg, data); +} + +static void setvideoregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask) +{ + CARD8 old; + + inSISIDXREG(SISVID, reg, old); + data = (data & mask) | (old & (~mask)); + outSISIDXREG(SISVID, reg, data); +} + +static void setsrregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask) +{ + CARD8 old; + + inSISIDXREG(SISSR, reg, old); + data = (data & mask) | (old & (~mask)); + outSISIDXREG(SISSR, reg, data); +} + +#if 0 +static CARD8 getsisreg(SISPtr pSiS, CARD8 index_offset, CARD8 reg) +{ + CARD8 ret; + inSISIDXREG(index_offset, reg, ret); + return(ret); +} +#endif + +/* VBlank */ +static CARD8 vblank_active_CRT1(SISPtr pSiS) +{ + return (inSISREG(SISINPSTAT) & 0x08); +} + +static CARD8 vblank_active_CRT2(SISPtr pSiS) +{ + CARD8 ret; + if(pSiS->VGAEngine == SIS_315_VGA) { + inSISIDXREG(SISPART1, Index_310_CRT2_FC_VR, ret); + } else { + inSISIDXREG(SISPART1, Index_CRT2_FC_VR, ret); + } + return((ret & 0x02) ^ 0x02); +} + +/* Scanline - unused */ +#if 0 +static CARD32 get_scanline_CRT1(SISPtr pSiS) +{ + CARD32 line; + + _siswrite (pSiS, REG_PRIM_CRT_COUNTER, 0x00000001); + line = _sisread (pSiS, REG_PRIM_CRT_COUNTER); + + return ((line >> 16) & 0x07FF); +} + +static CARD32 get_scanline_CRT2(SISPtr pSiS) +{ + CARD32 line; + + line = (CARD32)(getsisreg(pSiS, SISPART1, Index_CRT2_FC_VCount1) & 0x70) * 16 + + getsisreg(pSiS, SISPART1, Index_CRT2_FC_VCount); + + return line; +} +#endif + +void SISInitVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; + XF86VideoAdaptorPtr newAdaptor = NULL; + int num_adaptors; + + newAdaptor = SISSetupImageVideo(pScreen); + if(newAdaptor) + SISInitOffscreenImages(pScreen); + + num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); + + if(newAdaptor) { + if(!num_adaptors) { + num_adaptors = 1; + adaptors = &newAdaptor; + } else { + /* need to free this someplace */ + newAdaptors = xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); + if(newAdaptors) { + memcpy(newAdaptors, adaptors, num_adaptors * + sizeof(XF86VideoAdaptorPtr)); + newAdaptors[num_adaptors] = newAdaptor; + adaptors = newAdaptors; + num_adaptors++; + } + } + } + + if(num_adaptors) + xf86XVScreenInit(pScreen, adaptors, num_adaptors); + + if(newAdaptors) + xfree(newAdaptors); +} + +/* client libraries expect an encoding */ +static XF86VideoEncodingRec DummyEncoding = +{ + 0, + "XV_IMAGE", + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + {1, 1} +}; + +static XF86VideoEncodingRec DummyEncoding_M650 = +{ + 0, + "XV_IMAGE", + IMAGE_MAX_WIDTH_M650, IMAGE_MAX_HEIGHT_M650, + {1, 1} +}; + +#define NUM_FORMATS 3 + +static XF86VideoFormatRec SISFormats[NUM_FORMATS] = +{ + { 8, PseudoColor}, + {16, TrueColor}, + {24, TrueColor} +}; + +#define NUM_ATTRIBUTES_300 5 +#define NUM_ATTRIBUTES_325 7 + +static XF86AttributeRec SISAttributes_300[NUM_ATTRIBUTES_300] = +{ + {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, + {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, 0, 7, "XV_CONTRAST"}, + {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, + {XvSettable , 0, 0, "XV_SET_DEFAULTS"} +}; + +static XF86AttributeRec SISAttributes_325[NUM_ATTRIBUTES_325] = +{ + {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, + {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, 0, 7, "XV_CONTRAST"}, + {XvSettable | XvGettable, -7, 7, "XV_SATURATION"}, + {XvSettable | XvGettable, -8, 7, "XV_HUE"}, + {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, + {XvSettable , 0, 0, "XV_SET_DEFAULTS"} +}; + +#define NUM_IMAGES 6 +#define PIXEL_FMT_YV12 FOURCC_YV12 /* 0x32315659 */ +#define PIXEL_FMT_UYVY FOURCC_UYVY /* 0x59565955 */ +#define PIXEL_FMT_YUY2 FOURCC_YUY2 /* 0x32595559 */ +#define PIXEL_FMT_I420 FOURCC_I420 /* 0x30323449 */ +#define PIXEL_FMT_RGB5 0x35315652 +#define PIXEL_FMT_RGB6 0x36315652 + +static XF86ImageRec SISImages[NUM_IMAGES] = +{ + XVIMAGE_YUY2, /* TW: If order is changed, SISOffscreenImages must be adapted */ + XVIMAGE_YV12, + XVIMAGE_UYVY, + XVIMAGE_I420 + , + { /* RGB 555 */ + 0x35315652, + XvRGB, + LSBFirst, + {'R','V','1','5', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, +/* 15, 0x001F, 0x03E0, 0x7C00, - incorrect! */ + 15, 0x7C00, 0x03E0, 0x001F, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R', 'V', 'B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + }, + { /* RGB 565 */ + 0x36315652, + XvRGB, + LSBFirst, + {'R','V','1','6', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, +/* 16, 0x001F, 0x07E0, 0xF800, - incorrect! */ + 16, 0xF800, 0x07E0, 0x001F, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R', 'V', 'B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + } +}; + +typedef struct { + int pixelFormat; + + CARD16 pitch; + CARD16 origPitch; + + CARD8 keyOP; + CARD16 HUSF; + CARD16 VUSF; + CARD8 IntBit; + CARD8 wHPre; + + CARD16 srcW; + CARD16 srcH; + + BoxRec dstBox; + + CARD32 PSY; + CARD32 PSV; + CARD32 PSU; + CARD8 bobEnable; + + CARD8 contrastCtrl; + CARD8 contrastFactor; + + CARD8 lineBufSize; + + CARD8 (*VBlankActiveFunc)(SISPtr); +#if 0 + CARD32 (*GetScanLineFunc)(SISPtr pSiS); +#endif + + CARD16 SCREENheight; + +#if 0 + /* TW: The following are not used yet */ + CARD16 SubPictHUSF; /* Subpicture scaling */ + CARD16 SubpictVUSF; + CARD8 SubpictIntBit; + CARD8 SubPictwHPre; + CARD16 SubPictsrcW; /* Subpicture source width */ + CARD16 SubPictsrcH; /* Subpicture source height */ + BoxRec SubPictdstBox; /* SubPicture destination box */ + CARD32 SubPictAddr; /* SubPicture address */ + CARD32 SubPictPitch; /* SubPicture pitch */ + CARD32 SubPictOrigPitch; /* SubPicture real pitch (needed for scaling twice) */ + CARD32 SubPictPreset; /* Subpicture Preset */ + + CARD32 MPEG_Y; /* MPEG Y Buffer Addr */ + CARD32 MPEG_UV; /* MPEG UV Buffer Addr */ +#endif + +} SISOverlayRec, *SISOverlayPtr; + +typedef struct { + FBLinearPtr linear; /* TW: We now use Linear, not Area */ + CARD32 bufAddr[2]; + + unsigned char currentBuf; + + short drw_x, drw_y, drw_w, drw_h; + short src_x, src_y, src_w, src_h; + int id; + short srcPitch, height; + + char brightness; + unsigned char contrast; + char hue; + char saturation; + + RegionRec clip; + CARD32 colorKey; + Bool autopaintColorKey; + + CARD32 videoStatus; + Time offTime; + Time freeTime; + + CARD32 displayMode; + Bool bridgeIsSlave; + + Bool hasTwoOverlays; /* TW: Chipset has two overlays */ + Bool dualHeadMode; /* TW: We're running in DHM */ + + Bool needToScale; /* TW: Need to scale video */ + + int shiftValue; /* 550/650 need word addr/pitch, 630 double word */ + + short oldx1, oldx2, oldy1, oldy2; + int mustwait; + + Bool grabbedByV4L; /* V4L stuff */ + int pitch; + int offset; + +} SISPortPrivRec, *SISPortPrivPtr; + +#define GET_PORT_PRIVATE(pScrn) \ + (SISPortPrivPtr)((SISPTR(pScrn))->adaptor->pPortPrivates[0].ptr) + +static void +SISSetPortDefaults (ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) +{ + pPriv->colorKey = 0x000101fe; + pPriv->videoStatus = 0; + pPriv->brightness = 0; + pPriv->contrast = 4; + pPriv->hue = 0; + pPriv->saturation = 0; + pPriv->autopaintColorKey = TRUE; +} + +static void +SISResetVideo(ScrnInfoPtr pScrn) +{ + SISPtr pSiS = SISPTR(pScrn); + SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); + + /* Unlock registers */ +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + if (getvideoreg (pSiS, Index_VI_Passwd) != 0xa1) { + setvideoreg (pSiS, Index_VI_Passwd, 0x86); + if (getvideoreg (pSiS, Index_VI_Passwd) != 0xa1) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Xv: Video password could not unlock registers\n"); + } + + /* Initialize first overlay (CRT1) ------------------------------- */ + + /* Write-enable video registers */ + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x80, 0x81); + + /* Disable overlay */ + setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); + + /* Disable bobEnable */ + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x02, 0x02); + + /* Reset scale control and contrast */ + setvideoregmask(pSiS, Index_VI_Scale_Control, 0x60, 0x60); + setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x1F); + + setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Low, 0x00); + setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Middle, 0x00); + setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Low, 0x00); + setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Middle, 0x00); + setvideoreg(pSiS, Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00); + setvideoreg(pSiS, Index_VI_Play_Threshold_Low, 0x00); + setvideoreg(pSiS, Index_VI_Play_Threshold_High, 0x00); + + /* Initialize second overlay (CRT2) ---- only for 630/730, 550, M650/651 */ + if (pPriv->hasTwoOverlays) { + /* Write-enable video registers */ + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x81, 0x81); + + /* Disable overlay */ + setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); + + /* Disable bobEnable */ + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x02, 0x02); + + /* Reset scale control and contrast */ + setvideoregmask(pSiS, Index_VI_Scale_Control, 0x60, 0x60); + setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x1F); + + setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Low, 0x00); + setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Middle, 0x00); + setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Low, 0x00); + setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Middle, 0x00); + setvideoreg(pSiS, Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00); + setvideoreg(pSiS, Index_VI_Play_Threshold_Low, 0x00); + setvideoreg(pSiS, Index_VI_Play_Threshold_High, 0x00); + } + + /* set default properties for overlay 1 (CRT1) -------------------------- */ + setvideoregmask (pSiS, Index_VI_Control_Misc2, 0x00, 0x01); + setvideoregmask (pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x07); + setvideoreg (pSiS, Index_VI_Brightness, 0x20); + if (pSiS->VGAEngine == SIS_315_VGA) { + setvideoreg (pSiS, Index_VI_Hue, 0x00); + setvideoreg (pSiS, Index_VI_Saturation, 0x00); + } + + /* set default properties for overlay 2(CRT2) only 630/730 and 550 ------ */ + if (pPriv->hasTwoOverlays) { + setvideoregmask (pSiS, Index_VI_Control_Misc2, 0x01, 0x01); + setvideoregmask (pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x07); + setvideoreg (pSiS, Index_VI_Brightness, 0x20); + if (pSiS->VGAEngine == SIS_315_VGA) { + setvideoreg (pSiS, Index_VI_Hue, 0x00); + setvideoreg (pSiS, Index_VI_Saturation, 0x00); + } + } +} + +/* TW: Set display mode (single CRT1/CRT2, mirror). + * MIRROR mode is only available on chipsets with two overlays. + * On the other chipsets, if only CRT1 or only CRT2 are used, + * the correct display CRT is chosen automatically. If both + * CRT1 and CRT2 are connected, the user can choose between CRT1 and + * CRT2 by using the option XvOnCRT2. + */ +static void +set_dispmode(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) +{ + SISPtr pSiS = SISPTR(pScrn); + + pPriv->dualHeadMode = pPriv->bridgeIsSlave = FALSE; + + if(SiSBridgeIsInSlaveMode(pScrn)) pPriv->bridgeIsSlave = TRUE; + + if( (pSiS->VBFlags & VB_DISPMODE_MIRROR) || + ((pPriv->bridgeIsSlave) && (pSiS->VBFlags & DISPTYPE_DISP2)) ) { + if(pPriv->hasTwoOverlays) + pPriv->displayMode = DISPMODE_MIRROR; /* TW: CRT1 + CRT2 (2 overlays) */ + else if(pSiS->XvOnCRT2) + pPriv->displayMode = DISPMODE_SINGLE2; + else + pPriv->displayMode = DISPMODE_SINGLE1; + } else { +#ifdef SISDUALHEAD + if(pSiS->DualHeadMode) { + pPriv->dualHeadMode = TRUE; + if(pSiS->SecondHead) + /* TW: Slave is always CRT1 */ + pPriv->displayMode = DISPMODE_SINGLE1; + else + /* TW: Master is always CRT2 */ + pPriv->displayMode = DISPMODE_SINGLE2; + } else +#endif + if(pSiS->VBFlags & DISPTYPE_DISP1) { + pPriv->displayMode = DISPMODE_SINGLE1; /* TW: CRT1 only */ + } else { + pPriv->displayMode = DISPMODE_SINGLE2; /* TW: CRT2 only */ + } + } +} + +static void +set_disptype_regs(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) +{ + SISPtr pSiS = SISPTR(pScrn); + + /* TW: + * SR06[7:6] + * Bit 7: Enable overlay 2 on CRT2 + * Bit 6: Enable overlay 1 on CRT2 + * SR32[7:6] + * Bit 7: DCLK/TCLK overlay 2 + * 0=DCLK (overlay on CRT1) + * 1=TCLK (overlay on CRT2) + * Bit 6: DCLK/TCLK overlay 1 + * 0=DCLK (overlay on CRT1) + * 1=TCLK (overlay on CRT2) + * + * On chipsets with two overlays, we can freely select and also + * have a mirror mode. However, we use overlay 1 for CRT1 and + * overlay 2 for CRT2. + * For chipsets with only one overlay, user must choose whether + * to display the overlay on CRT1 or CRT2 by setting XvOnCRT2 + * to TRUE (CRT2) or FALSE (CRT1). The hardware does not + * support any kind of "Mirror" mode on these chipsets. + */ +#ifdef UNLOCK_ALWAYS + sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL); +#endif + switch (pPriv->displayMode) + { + case DISPMODE_SINGLE1: /* TW: CRT1 only */ + if (pPriv->hasTwoOverlays) { + if (pPriv->dualHeadMode) { + setsrregmask (pSiS, 0x06, 0x00, 0x40); + setsrregmask (pSiS, 0x32, 0x00, 0x40); + } else { + setsrregmask (pSiS, 0x06, 0x00, 0xc0); + setsrregmask (pSiS, 0x32, 0x00, 0xc0); + } + } else { + setsrregmask (pSiS, 0x06, 0x00, 0xc0); + setsrregmask (pSiS, 0x32, 0x00, 0xc0); + } + break; + case DISPMODE_SINGLE2: /* TW: CRT2 only */ + if (pPriv->hasTwoOverlays) { + if (pPriv->dualHeadMode) { + setsrregmask (pSiS, 0x06, 0x80, 0x80); + setsrregmask (pSiS, 0x32, 0x80, 0x80); + } else { + setsrregmask (pSiS, 0x06, 0x80, 0xc0); + setsrregmask (pSiS, 0x32, 0x80, 0xc0); + } + } else { + setsrregmask (pSiS, 0x06, 0x40, 0xc0); + setsrregmask (pSiS, 0x32, 0x40, 0xc0); + } + break; + case DISPMODE_MIRROR: /* TW: CRT1 + CRT2 */ + default: + setsrregmask (pSiS, 0x06, 0x80, 0xc0); + setsrregmask (pSiS, 0x32, 0x80, 0xc0); + break; + } +} + +static XF86VideoAdaptorPtr +SISSetupImageVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + XF86VideoAdaptorPtr adapt; + SISPortPrivPtr pPriv; + + if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + + sizeof(SISPortPrivRec) + + sizeof(DevUnion)))) + return NULL; + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->name = "SIS 300/310/325 series Video Overlay"; + adapt->nEncodings = 1; + if(pSiS->Flags650 & SiS650_LARGEOVERLAY) { + adapt->pEncodings = &DummyEncoding_M650; + } else { + adapt->pEncodings = &DummyEncoding; + } + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = SISFormats; + adapt->nPorts = 1; + adapt->pPortPrivates = (DevUnion*)(&adapt[1]); + + pPriv = (SISPortPrivPtr)(&adapt->pPortPrivates[1]); + + adapt->pPortPrivates[0].ptr = (pointer)(pPriv); + adapt->nImages = NUM_IMAGES; + if(pSiS->VGAEngine == SIS_300_VGA) { + adapt->pAttributes = SISAttributes_300; + adapt->nAttributes = NUM_ATTRIBUTES_300; + } else { + adapt->pAttributes = SISAttributes_325; + adapt->nAttributes = NUM_ATTRIBUTES_325; + } + adapt->pImages = SISImages; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = SISStopVideo; + adapt->SetPortAttribute = SISSetPortAttribute; + adapt->GetPortAttribute = SISGetPortAttribute; + adapt->QueryBestSize = SISQueryBestSize; + adapt->PutImage = SISPutImage; + adapt->QueryImageAttributes = SISQueryImageAttributes; + + pPriv->videoStatus = 0; + pPriv->currentBuf = 0; + pPriv->linear = NULL; + pPriv->grabbedByV4L= FALSE; + + SISSetPortDefaults(pScrn, pPriv); + + /* gotta uninit this someplace */ + REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); + + pSiS->adaptor = adapt; + + pSiS->xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + pSiS->xvContrast = MAKE_ATOM("XV_CONTRAST"); + pSiS->xvColorKey = MAKE_ATOM("XV_COLORKEY"); + if(pSiS->VGAEngine == SIS_315_VGA) { + pSiS->xvSaturation = MAKE_ATOM("XV_SATURATION"); + pSiS->xvHue = MAKE_ATOM("XV_HUE"); + } + pSiS->xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); + pSiS->xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); + + /* TW: Setup chipset type helpers */ + if (pSiS->hasTwoOverlays) + pPriv->hasTwoOverlays = TRUE; + else + pPriv->hasTwoOverlays = FALSE; + + /* TW: 300 series require double words for addresses and pitches, + * 310/325 series accept word. + */ + switch (pSiS->VGAEngine) { + case SIS_315_VGA: + pPriv->shiftValue = 1; + break; + case SIS_300_VGA: + default: + pPriv->shiftValue = 2; + break; + } + + /* Set displayMode according to VBFlags */ + set_dispmode(pScrn, pPriv); + + /* Set SR(06, 32) registers according to DISPMODE */ + set_disptype_regs(pScrn, pPriv); + + SISResetVideo(pScrn); + + return adapt; +} + +static Bool +RegionsEqual(RegionPtr A, RegionPtr B) +{ + int *dataA, *dataB; + int num; + + num = REGION_NUM_RECTS(A); + if(num != REGION_NUM_RECTS(B)) + return FALSE; + + if((A->extents.x1 != B->extents.x1) || + (A->extents.x2 != B->extents.x2) || + (A->extents.y1 != B->extents.y1) || + (A->extents.y2 != B->extents.y2)) + return FALSE; + + dataA = (int*)REGION_RECTS(A); + dataB = (int*)REGION_RECTS(B); + + while(num--) { + if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) + return FALSE; + dataA += 2; + dataB += 2; + } + + return TRUE; +} + +static int +SISSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 value, pointer data) +{ + SISPortPrivPtr pPriv = (SISPortPrivPtr)data; + SISPtr pSiS = SISPTR(pScrn); + + if(attribute == pSiS->xvBrightness) { + if((value < -128) || (value > 127)) + return BadValue; + pPriv->brightness = value; + } else if(attribute == pSiS->xvContrast) { + if((value < 0) || (value > 7)) + return BadValue; + pPriv->contrast = value; + } else if(attribute == pSiS->xvColorKey) { + pPriv->colorKey = value; + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + } else if(attribute == pSiS->xvAutopaintColorKey) { + if ((value < 0) || (value > 1)) + return BadValue; + pPriv->autopaintColorKey = value; + } else if(attribute == pSiS->xvSetDefaults) { + SISSetPortDefaults(pScrn, pPriv); + } else if(pSiS->VGAEngine == SIS_315_VGA) { + if(attribute == pSiS->xvHue) { + if((value < -8) || (value > 7)) + return BadValue; + pPriv->hue = value; + } else if(attribute == pSiS->xvSaturation) { + if((value < -7) || (value > 7)) + return BadValue; + pPriv->saturation = value; + } else return BadMatch; + } else return BadMatch; + return Success; +} + +static int +SISGetPortAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value, + pointer data +){ + SISPortPrivPtr pPriv = (SISPortPrivPtr)data; + SISPtr pSiS = SISPTR(pScrn); + + if(attribute == pSiS->xvBrightness) { + *value = pPriv->brightness; + } else if(attribute == pSiS->xvContrast) { + *value = pPriv->contrast; + } else if(attribute == pSiS->xvColorKey) { + *value = pPriv->colorKey; + } else if (attribute == pSiS->xvAutopaintColorKey) { + *value = (pPriv->autopaintColorKey) ? 1 : 0; + } else if(pSiS->VGAEngine == SIS_315_VGA) { + if(attribute == pSiS->xvHue) { + *value = pPriv->hue; + } else if(attribute == pSiS->xvSaturation) { + *value = pPriv->saturation; + } else return BadMatch; + } else return BadMatch; + return Success; +} + +static void +SISQueryBestSize( + ScrnInfoPtr pScrn, + Bool motion, + short vid_w, short vid_h, + short drw_w, short drw_h, + unsigned int *p_w, unsigned int *p_h, + pointer data +){ + *p_w = drw_w; + *p_h = drw_h; +} + +static void +calc_scale_factor(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn, + SISPortPrivPtr pPriv, int index, int iscrt2) +{ + SISPtr pSiS = SISPTR(pScrn); + CARD32 I=0,mult=0; + int flag=0; + + int dstW = pOverlay->dstBox.x2 - pOverlay->dstBox.x1; + int dstH = pOverlay->dstBox.y2 - pOverlay->dstBox.y1; + int srcW = pOverlay->srcW; + int srcH = pOverlay->srcH; + CARD16 LCDheight = pSiS->LCDheight; + int srcPitch = pOverlay->origPitch; + int origdstH = dstH; + + /* TW: Stretch image due to idiotic LCD "auto"-scaling on LVDS (and 630+301B) */ + if(pSiS->VBFlags & CRT2_LCD) { + if(pPriv->bridgeIsSlave) { + if(pSiS->VBFlags & VB_LVDS) { + dstH = (dstH * LCDheight) / pOverlay->SCREENheight; + } else if( (pSiS->VGAEngine == SIS_300_VGA) && + (pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) ) { + dstH = (dstH * LCDheight) / pOverlay->SCREENheight; + } + } else if(iscrt2) { + if (pSiS->VBFlags & VB_LVDS) { + dstH = (dstH * LCDheight) / pOverlay->SCREENheight; + if (pPriv->displayMode == DISPMODE_MIRROR) flag = 1; + } else if ( (pSiS->VGAEngine == SIS_300_VGA) && + (pSiS->VBFlags & (VB_301B|VB_302B|VB_30xLV|VB_30xLVX)) ) { + dstH = (dstH * LCDheight) / pOverlay->SCREENheight; + if (pPriv->displayMode == DISPMODE_MIRROR) flag = 1; + } + } + } + /* TW: For double scan modes, we need to double the height + * (Perhaps we also need to scale LVDS, but I'm not sure.) + * On 310/325 series, we need to double the width as well. + * Interlace mode vice versa. + */ + if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) { + dstH = origdstH << 1; + flag = 0; + if(pSiS->VGAEngine == SIS_315_VGA) { + dstW <<= 1; + } + } + if(pSiS->CurrentLayout.mode->Flags & V_INTERLACE) { + dstH = origdstH >> 1; + flag = 0; + } + + if(dstW < OVERLAY_MIN_WIDTH) dstW = OVERLAY_MIN_WIDTH; + if (dstW == srcW) { + pOverlay->HUSF = 0x00; + pOverlay->IntBit = 0x05; + pOverlay->wHPre = 0; + } else if (dstW > srcW) { + dstW += 2; + pOverlay->HUSF = (srcW << 16) / dstW; + pOverlay->IntBit = 0x04; + pOverlay->wHPre = 0; + } else { + int tmpW = dstW; + + /* TW: It seems, the hardware can't scale below factor .125 (=1/8) if the + pitch isn't a multiple of 256. + TODO: Test this on the 310/325 series! + */ + if((srcPitch % 256) || (srcPitch < 256)) { + if(((dstW * 1000) / srcW) < 125) dstW = tmpW = ((srcW * 125) / 1000) + 1; + } + + I = 0; + pOverlay->IntBit = 0x01; + while (srcW >= tmpW) { + tmpW <<= 1; + I++; + } + pOverlay->wHPre = (CARD8)(I - 1); + dstW <<= (I - 1); + if ((srcW % dstW)) + pOverlay->HUSF = ((srcW - dstW) << 16) / dstW; + else + pOverlay->HUSF = 0x00; + } + + if(dstH < OVERLAY_MIN_HEIGHT) dstH = OVERLAY_MIN_HEIGHT; + if (dstH == srcH) { + pOverlay->VUSF = 0x00; + pOverlay->IntBit |= 0x0A; + } else if (dstH > srcH) { + dstH += 0x02; + pOverlay->VUSF = (srcH << 16) / dstH; + pOverlay->IntBit |= 0x08; + } else { + CARD32 realI; + + I = realI = srcH / dstH; + pOverlay->IntBit |= 0x02; + + if (I < 2) { + pOverlay->VUSF = ((srcH - dstH) << 16) / dstH; + /* TW: Needed for LCD-scaling modes */ + if ((flag) && (mult = (srcH / origdstH)) >= 2) + pOverlay->pitch /= mult; + } else { +#if 0 + if (((pOverlay->bobEnable & 0x08) == 0x00) && + (((srcPitch * I)>>2) > 0xFFF)){ + pOverlay->bobEnable |= 0x08; + srcPitch >>= 1; + } +#endif + if (((srcPitch * I)>>2) > 0xFFF) { + I = (0xFFF*2/srcPitch); + pOverlay->VUSF = 0xFFFF; + } else { + dstH = I * dstH; + if (srcH % dstH) + pOverlay->VUSF = ((srcH - dstH) << 16) / dstH; + else + pOverlay->VUSF = 0x00; + } + /* set video frame buffer offset */ + pOverlay->pitch = (CARD16)(srcPitch*I); + } + } +} + +static void +set_line_buf_size(SISOverlayPtr pOverlay) +{ + CARD8 preHIDF; + CARD32 I; + CARD32 line = pOverlay->srcW; + + if ( (pOverlay->pixelFormat == PIXEL_FMT_YV12) || + (pOverlay->pixelFormat == PIXEL_FMT_I420) ) + { + preHIDF = pOverlay->wHPre & 0x07; + switch (preHIDF) + { + case 3 : + if ((line & 0xffffff00) == line) + I = (line >> 8); + else + I = (line >> 8) + 1; + pOverlay->lineBufSize = (CARD8)(I * 32 - 1); + break; + case 4 : + if ((line & 0xfffffe00) == line) + I = (line >> 9); + else + I = (line >> 9) + 1; + pOverlay->lineBufSize = (CARD8)(I * 64 - 1); + break; + case 5 : + if ((line & 0xfffffc00) == line) + I = (line >> 10); + else + I = (line >> 10) + 1; + pOverlay->lineBufSize = (CARD8)(I * 128 - 1); + break; + case 6 : + if ((line & 0xfffff800) == line) + I = (line >> 11); + else + I = (line >> 11) + 1; + pOverlay->lineBufSize = (CARD8)(I * 256 - 1); + break; + default : + if ((line & 0xffffff80) == line) + I = (line >> 7); + else + I = (line >> 7) + 1; + pOverlay->lineBufSize = (CARD8)(I * 16 - 1); + break; + } + } else { /* YUV2, UYVY */ + if ((line & 0xffffff8) == line) + I = (line >> 3); + else + I = (line >> 3) + 1; + pOverlay->lineBufSize = (CARD8)(I - 1); + } +} + +static void +merge_line_buf(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable) +{ + if(enable) { + switch (pPriv->displayMode){ + case DISPMODE_SINGLE1: + if (pPriv->hasTwoOverlays) { + if (pPriv->dualHeadMode) { + /* line merge */ + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x11); + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04); + } else { + /* dual line merge */ + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x10, 0x11); + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); + } + } else { + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x10, 0x11); + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); + } + break; + case DISPMODE_SINGLE2: + if (pPriv->hasTwoOverlays) { + if (pPriv->dualHeadMode) { + /* line merge */ + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x11); + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04); + } else { + /* line merge */ + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x11); + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04); + } + } else { + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x10, 0x11); + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); + } + break; + case DISPMODE_MIRROR: + default: + /* line merge */ + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x11); + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04); + if (pPriv->hasTwoOverlays) { + /* line merge */ + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x11); + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04); + } + break; + } + } else { + switch (pPriv->displayMode) { + case DISPMODE_SINGLE1: + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x11); + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); + break; + case DISPMODE_SINGLE2: + if (pPriv->hasTwoOverlays) { + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x11); + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); + } else { + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x11); + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); + } + break; + case DISPMODE_MIRROR: + default: + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x11); + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); + if (pPriv->hasTwoOverlays) { + setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x11); + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04); + } + break; + } + } +} + +static void +set_format(SISPtr pSiS, SISOverlayPtr pOverlay) +{ + CARD8 fmt; + + switch (pOverlay->pixelFormat){ + case PIXEL_FMT_YV12: + case PIXEL_FMT_I420: + fmt = 0x0c; + break; + case PIXEL_FMT_YUY2: + fmt = 0x28; + break; + case PIXEL_FMT_UYVY: + fmt = 0x08; + break; + case PIXEL_FMT_RGB5: /* D[5:4] : 00 RGB555, 01 RGB 565 */ + fmt = 0x00; + break; + case PIXEL_FMT_RGB6: + fmt = 0x10; + break; + default: + fmt = 0x00; + break; + } + setvideoregmask(pSiS, Index_VI_Control_Misc0, fmt, 0x7c); +} + +static void +set_colorkey(SISPtr pSiS, CARD32 colorkey) +{ + CARD8 r, g, b; + + b = (CARD8)(colorkey & 0xFF); + g = (CARD8)((colorkey>>8) & 0xFF); + r = (CARD8)((colorkey>>16) & 0xFF); + + /* Activate the colorkey mode */ + setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Blue_Min ,(CARD8)b); + setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Green_Min ,(CARD8)g); + setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Red_Min ,(CARD8)r); + + setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Blue_Max ,(CARD8)b); + setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Green_Max ,(CARD8)g); + setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Red_Max ,(CARD8)r); +} + +static void +set_brightness(SISPtr pSiS, CARD8 brightness) +{ + setvideoreg(pSiS, Index_VI_Brightness, brightness); +} + +static void +set_contrast(SISPtr pSiS, CARD8 contrast) +{ + setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, contrast, 0x07); +} + +/* 310/325 series only */ +static void +set_saturation(SISPtr pSiS, char saturation) +{ + CARD8 temp = 0; + + if(saturation < 0) { + temp |= 0x88; + saturation = -saturation; + } + temp |= (saturation & 0x07); + temp |= ((saturation & 0x07) << 4); + + setvideoreg(pSiS, Index_VI_Saturation, temp); +} + +/* 310/325 series only */ +static void +set_hue(SISPtr pSiS, CARD8 hue) +{ + setvideoreg(pSiS, Index_VI_Hue, (hue & 0x08) ? (hue ^ 0x07) : hue); +} + +#ifdef NOT_YET_IMPLEMENTED /* ----------- TW: FOR FUTURE USE -------------------- */ + +/* TW: Set Alpha */ +static void +set_alpha(SISPtr pSiS, CARD8 alpha) +{ + CARD8 data; + + data = getvideoreg(pSiS, Index_VI_Key_Overlay_OP); + data &= 0x0F; + setvideoreg(pSiS,Index_VI_Key_Overlay_OP, data | (alpha << 4)); +} + +/* TW: Set SubPicture Start Address (yet unused) */ +static void +set_subpict_start_offset(SISPtr pSiS, SISOverlayPtr pOverlay, int index) +{ + CARD32 temp; + CARD8 data; + + temp = pOverlay->SubPictAddr >> 4; /* TW: 630 <-> 315 shiftValue? */ + + setvideoreg(pSiS,Index_VI_SubPict_Buf_Start_Low, temp & 0xFF); + setvideoreg(pSiS,Index_VI_SubPict_Buf_Start_Middle, (temp>>8) & 0xFF); + setvideoreg(pSiS,Index_VI_SubPict_Buf_Start_High, (temp>>16) & 0x3F); + if (pSiS->VGAEngine == SIS_315_VGA) { + setvideoreg(pSiS,Index_VI_SubPict_Start_Over, (temp>>22) & 0x01); + /* Submit SubPict offset ? */ + /* data=getvideoreg(pSiS,Index_VI_Control_Misc3); */ + setvideoreg(pSiS,Index_VI_Control_Misc3, (1 << index) | 0x04); + } +} + +/* TW: Set SubPicture Pitch (yet unused) */ +static void +set_subpict_pitch(SISPtr pSiS, SISOverlayPtr pOverlay, int index) +{ + CARD32 temp; + CARD8 data; + + temp = pOverlay->SubPictPitch >> 4; /* TW: 630 <-> 315 shiftValue? */ + + setvideoreg(pSiS,Index_VI_SubPict_Buf_Pitch, temp & 0xFF); + if (pSiS->VGAEngine == SIS_315_VGA) { + setvideoreg(pSiS,Index_VI_SubPict_Buf_Pitch_High, (temp>>8) & 0xFF); + /* Submit SubPict pitch ? */ + /* data=getvideoreg(pSiS,Index_VI_Control_Misc3); */ + setvideoreg(pSiS,Index_VI_Control_Misc3, (1 << index) | 0x04); + } +} + +/* TW: Calculate and set SubPicture scaling (untested, unused yet) */ +static void +set_subpict_scale_factor(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn, + SISPortPrivPtr pPriv, int index, int iscrt2) +{ + SISPtr pSiS = SISPTR(pScrn); + CARD32 I=0,mult=0; + int flag=0; + + int dstW = pOverlay->SubPictdstBox.x2 - pOverlay->SubPictdstBox.x1; + int dstH = pOverlay->SubPictdstBox.y2 - pOverlay->SubPictdstBox.y1; + int srcW = pOverlay->SubPictsrcW; + int srcH = pOverlay->SubPictsrcH; + CARD16 LCDheight = pSiS->LCDheight; + int srcPitch = pOverlay->SubPictOrigPitch; + int origdstH = dstH; + + /* TW: Stretch image due to idiotic LCD "auto"-scaling */ + /* INCOMPLETE - See set_scale_factor() */ + if ( (pPriv->bridgeIsSlave) && (pSiS->VBFlags & CRT2_LCD) ) { + dstH = (dstH * LCDheight) / pOverlay->SCREENheight; + } else if ((index) && (pSiS->VBFlags & CRT2_LCD)) { + dstH = (dstH * LCDheight) / pOverlay->SCREENheight; + if (pPriv->displayMode == DISPMODE_MIRROR) flag = 1; + } + + if (dstW == srcW) { + pOverlay->SubPictHUSF = 0x00; + pOverlay->SubPictIntBit = 0x01; + } else if (dstW > srcW) { + pOverlay->SubPictHUSF = (srcW << 16) / dstW; + pOverlay->SubPictIntBit = 0x00; + } else { + int tmpW = dstW; + + I = 0x00; + while (srcW >= tmpW) { + tmpW <<= 1; + I++; + } + pOverlay->SubPictwHPre = (CARD8)(I - 1); + dstW <<= (I - 1); + if ((srcW % dstW)) + pOverlay->SubPictHUSF = ((srcW - dstW) << 16) / dstW; + else + pOverlay->SubPictHUSF = 0x00; + + pOverlay->SubPictIntBit = 0x01; + } + + if (dstH == srcH) { + pOverlay->SubPictVUSF = 0x00; + pOverlay->SubPictIntBit |= 0x02; + } else if (dstH > srcH) { + dstH += 0x02; + pOverlay->SubPictVUSF = (srcH << 16) / dstH; + /* pOverlay->SubPictIntBit |= 0x00; */ + } else { + CARD32 realI; + + I = realI = srcH / dstH; + pOverlay->SubPictIntBit |= 0x02; + + if (I < 2) { + pOverlay->SubPictVUSF = ((srcH - dstH) << 16) / dstH; + /* TW: Needed for LCD-scaling modes */ + if ((flag) && (mult = (srcH / origdstH)) >= 2) + pOverlay->SubPictPitch /= mult; + } else { + if (((srcPitch * I)>>2) > 0xFFF) { + I = (0xFFF*2/srcPitch); + pOverlay->SubPictVUSF = 0xFFFF; + } else { + dstH = I * dstH; + if (srcH % dstH) + pOverlay->SubPictVUSF = ((srcH - dstH) << 16) / dstH; + else + pOverlay->SubPictVUSF = 0x00; + } + /* set video frame buffer offset */ + pOverlay->SubPictPitch = (CARD16)(srcPitch*I); + } + } + /* set SubPicture scale factor */ + setvideoreg (pSiS, Index_VI_SubPict_Hor_Scale_Low, (CARD8)(pOverlay->SubPictHUSF)); + setvideoreg (pSiS, Index_VI_SubPict_Hor_Scale_High, (CARD8)((pOverlay->SubPictHUSF)>>8)); + setvideoreg (pSiS, Index_VI_SubPict_Vert_Scale_Low, (CARD8)(pOverlay->SubPictVUSF)); + setvideoreg (pSiS, Index_VI_SubPict_Vert_Scale_High,(CARD8)((pOverlay->SubPictVUSF)>>8)); + + setvideoregmask (pSiS, Index_VI_SubPict_Scale_Control, + (pOverlay->SubPictIntBit << 3) | + (pOverlay->SubPictwHPre), 0x7f); +} + +/* TW: Set SubPicture Preset (yet unused) */ +static void +set_subpict_preset(SISPtr pSiS, SISOverlayPtr pOverlay) +{ + CARD32 temp; + CARD8 data; + + temp = pOverlay->SubPictPreset >> 4; /* TW: 630 <-> 315 ? */ + + setvideoreg(pSiS,Index_VI_SubPict_Buf_Preset_Low, temp & 0xFF); + setvideoreg(pSiS,Index_VI_SubPict_Buf_Preset_Middle, (temp>>8) & 0xFF); + data = getvideoreg(pSiS,Index_VI_SubPict_Buf_Start_High); + if (temp > 0xFFFF) + data |= 0x40; + else + data &= ~0x40; + setvideoreg(pSiS,Index_VI_SubPict_Buf_Start_High, data); +} + +static void +enable_subpict_overlay(SISPtr pSiS, Bool enable) +{ + setvideoregmask(pSiS, Index_VI_SubPict_Scale_Control, + enable ? 0x40 : 0x00, + 0x40); +} + +/* TW: Set overlay for subpicture */ +static void +set_subpict_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index) +{ + ScrnInfoPtr pScrn = pSiS->pScrn; + + set_subpict_pitch(pSiS, &overlay, index); + set_subpict_start_offset(pSiS, &overlay, index); + set_subpict_scale_factor(&overlay, pScrn, pPriv, index); + /* set_subpict_preset(pSiS, &overlay); */ + /* enable_subpict_overlay(pSiS, 1); */ +} + + +/* TW: Set MPEG Field Preset (yet unused) */ +static void +set_mpegfield_preset(SISPtr pSiS, SISOverlayPtr pOverlay) +{ + setvideoreg(pSiS,Index_MPEG_Y_Buf_Preset_Low, pOverlay->MPEG_Y & 0xFF); + setvideoreg(pSiS,Index_MPEG_Y_Buf_Preset_Middle, (pOverlay->MPEG_Y>>8) & 0xFF); + + setvideoreg(pSiS,Index_MPEG_UV_Buf_Preset_Low, pOverlay->MPEG_UV & 0xFF); + setvideoreg(pSiS,Index_MPEG_UV_Buf_Preset_Middle, (pOverlay->MPEG_UV>>8) & 0xFF); + + setvideoreg(pSiS,Index_MPEG_Y_UV_Buf_Preset_High, + ((pOverlay->MPEG_Y>>16) & 0x0F) | ((pOverlay->MPEG_UV>>12) & 0xF0)); +} + +static void +set_mpegfield_scale(SISPtr pSiS, SISOverlayPtr pOverlay) +{ + /* Empty for now */ +} + +#endif /* ------------------------------------------------------------------- */ + +static void +set_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index) +{ + ScrnInfoPtr pScrn = pSiS->pScrn; + + CARD16 pitch=0; + CARD8 h_over=0, v_over=0; + CARD16 top, bottom, left, right; + CARD16 screenX = pSiS->CurrentLayout.mode->HDisplay; + CARD16 screenY = pSiS->CurrentLayout.mode->VDisplay; + CARD8 data; + CARD32 watchdog; + + top = pOverlay->dstBox.y1; + bottom = pOverlay->dstBox.y2; + if (bottom > screenY) { + bottom = screenY; + } + + left = pOverlay->dstBox.x1; + right = pOverlay->dstBox.x2; + if (right > screenX) { + right = screenX; + } + + /* TW: DoubleScan modes require Y coordinates * 2 */ + if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) { + top <<= 1; + bottom <<= 1; + } + /* TW: Interlace modes require Y coordinates / 2 */ + if(pSiS->CurrentLayout.mode->Flags & V_INTERLACE) { + top >>= 1; + bottom >>= 1; + } + + h_over = (((left>>8) & 0x0f) | ((right>>4) & 0xf0)); + v_over = (((top>>8) & 0x0f) | ((bottom>>4) & 0xf0)); + + pitch = pOverlay->pitch >> pPriv->shiftValue; + + /* set line buffer size */ + setvideoreg(pSiS, Index_VI_Line_Buffer_Size, pOverlay->lineBufSize); + + /* set color key mode */ + setvideoregmask (pSiS, Index_VI_Key_Overlay_OP, pOverlay->keyOP, 0x0f); + + /* TW: We don't have to wait for vertical retrace in all cases */ + if(pPriv->mustwait) { + watchdog = WATCHDOG_DELAY; + while (pOverlay->VBlankActiveFunc(pSiS) && --watchdog); + watchdog = WATCHDOG_DELAY; + while ((!pOverlay->VBlankActiveFunc(pSiS)) && --watchdog); + if (!watchdog) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Xv: Waiting for vertical retrace timed-out\n"); + } + + /* Unlock address registers */ + data = getvideoreg(pSiS, Index_VI_Control_Misc1); + setvideoreg (pSiS, Index_VI_Control_Misc1, data | 0x20); + /* TEST: Is this required? */ + setvideoreg (pSiS, Index_VI_Control_Misc1, data | 0x20); + /* TEST end */ + + /* TEST: Is this required? */ + if (pSiS->Chipset == SIS_315_VGA) + setvideoreg (pSiS, Index_VI_Control_Misc3, 0x00); + /* TEST end */ + + /* Set Y buf pitch */ + setvideoreg (pSiS, Index_VI_Disp_Y_Buf_Pitch_Low, (CARD8)(pitch)); + setvideoregmask (pSiS, Index_VI_Disp_Y_UV_Buf_Pitch_Middle, (CARD8)(pitch>>8), 0x0f); + + /* Set Y start address */ + setvideoreg (pSiS, Index_VI_Disp_Y_Buf_Start_Low, (CARD8)(pOverlay->PSY)); + setvideoreg (pSiS, Index_VI_Disp_Y_Buf_Start_Middle, (CARD8)((pOverlay->PSY)>>8)); + setvideoreg (pSiS, Index_VI_Disp_Y_Buf_Start_High, (CARD8)((pOverlay->PSY)>>16)); + + /* set 310/325 series overflow bits for Y plane */ + if (pSiS->VGAEngine == SIS_315_VGA) { + setvideoreg (pSiS, Index_VI_Disp_Y_Buf_Pitch_High, (CARD8)(pitch>>12)); + setvideoreg (pSiS, Index_VI_Y_Buf_Start_Over, ((CARD8)((pOverlay->PSY)>>24) & 0x01)); + } + + /* Set U/V data if using plane formats */ + if ( (pOverlay->pixelFormat == PIXEL_FMT_YV12) || + (pOverlay->pixelFormat == PIXEL_FMT_I420) ) { + + CARD32 PSU=0, PSV=0; + + PSU = pOverlay->PSU; + PSV = pOverlay->PSV; + + /* Set U/V pitch */ + setvideoreg (pSiS, Index_VI_Disp_UV_Buf_Pitch_Low, (CARD8)(pitch >> 1)); + setvideoregmask (pSiS, Index_VI_Disp_Y_UV_Buf_Pitch_Middle, (CARD8)(pitch >> 5), 0xf0); + + /* set U/V start address */ + setvideoreg (pSiS, Index_VI_U_Buf_Start_Low, (CARD8)PSU); + setvideoreg (pSiS, Index_VI_U_Buf_Start_Middle,(CARD8)(PSU>>8)); + setvideoreg (pSiS, Index_VI_U_Buf_Start_High, (CARD8)(PSU>>16)); + + setvideoreg (pSiS, Index_VI_V_Buf_Start_Low, (CARD8)PSV); + setvideoreg (pSiS, Index_VI_V_Buf_Start_Middle,(CARD8)(PSV>>8)); + setvideoreg (pSiS, Index_VI_V_Buf_Start_High, (CARD8)(PSV>>16)); + + /* 310/325 series overflow bits */ + if (pSiS->VGAEngine == SIS_315_VGA) { + setvideoreg (pSiS, Index_VI_Disp_UV_Buf_Pitch_High, (CARD8)(pitch>>13)); + setvideoreg (pSiS, Index_VI_U_Buf_Start_Over, ((CARD8)(PSU>>24) & 0x01)); + setvideoreg (pSiS, Index_VI_V_Buf_Start_Over, ((CARD8)(PSV>>24) & 0x01)); + } + } + + if (pSiS->VGAEngine == SIS_315_VGA) { + /* Trigger register copy for 310 series */ + setvideoreg(pSiS, Index_VI_Control_Misc3, 1 << index); + } + + /* set scale factor */ + setvideoreg (pSiS, Index_VI_Hor_Post_Up_Scale_Low, (CARD8)(pOverlay->HUSF)); + setvideoreg (pSiS, Index_VI_Hor_Post_Up_Scale_High,(CARD8)((pOverlay->HUSF)>>8)); + setvideoreg (pSiS, Index_VI_Ver_Up_Scale_Low, (CARD8)(pOverlay->VUSF)); + setvideoreg (pSiS, Index_VI_Ver_Up_Scale_High, (CARD8)((pOverlay->VUSF)>>8)); + + setvideoregmask (pSiS, Index_VI_Scale_Control, (pOverlay->IntBit << 3) + |(pOverlay->wHPre), 0x7f); + + /* set destination window position */ + setvideoreg(pSiS, Index_VI_Win_Hor_Disp_Start_Low, (CARD8)left); + setvideoreg(pSiS, Index_VI_Win_Hor_Disp_End_Low, (CARD8)right); + setvideoreg(pSiS, Index_VI_Win_Hor_Over, (CARD8)h_over); + + setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, (CARD8)top); + setvideoreg(pSiS, Index_VI_Win_Ver_Disp_End_Low, (CARD8)bottom); + setvideoreg(pSiS, Index_VI_Win_Ver_Over, (CARD8)v_over); + + setvideoregmask(pSiS, Index_VI_Control_Misc1, pOverlay->bobEnable, 0x1a); + + /* Lock the address registers */ + setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x20); +} + +/* TW: Overlay MUST NOT be switched off while beam is over it */ +static void +close_overlay(SISPtr pSiS, SISPortPrivPtr pPriv) +{ + CARD32 watchdog; + + if ((pPriv->displayMode == DISPMODE_SINGLE2) || + (pPriv->displayMode == DISPMODE_MIRROR)) { + if (pPriv->hasTwoOverlays) { + setvideoregmask (pSiS, Index_VI_Control_Misc2, 0x01, 0x01); + watchdog = WATCHDOG_DELAY; + while(vblank_active_CRT2(pSiS) && --watchdog); + watchdog = WATCHDOG_DELAY; + while((!vblank_active_CRT2(pSiS)) && --watchdog); + setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); + watchdog = WATCHDOG_DELAY; + while(vblank_active_CRT2(pSiS) && --watchdog); + watchdog = WATCHDOG_DELAY; + while((!vblank_active_CRT2(pSiS)) && --watchdog); + } else if (pPriv->displayMode == DISPMODE_SINGLE2) { + setvideoregmask (pSiS, Index_VI_Control_Misc2, 0x00, 0x01); + watchdog = WATCHDOG_DELAY; + while(vblank_active_CRT1(pSiS) && --watchdog); + watchdog = WATCHDOG_DELAY; + while((!vblank_active_CRT1(pSiS)) && --watchdog); + setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); + watchdog = WATCHDOG_DELAY; + while(vblank_active_CRT1(pSiS) && --watchdog); + watchdog = WATCHDOG_DELAY; + while((!vblank_active_CRT1(pSiS)) && --watchdog); + } + } + if ((pPriv->displayMode == DISPMODE_SINGLE1) || + (pPriv->displayMode == DISPMODE_MIRROR)) { + setvideoregmask (pSiS, Index_VI_Control_Misc2, 0x00, 0x01); + watchdog = WATCHDOG_DELAY; + while(vblank_active_CRT1(pSiS) && --watchdog); + watchdog = WATCHDOG_DELAY; + while((!vblank_active_CRT1(pSiS)) && --watchdog); + setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02); + watchdog = WATCHDOG_DELAY; + while(vblank_active_CRT1(pSiS) && --watchdog); + watchdog = WATCHDOG_DELAY; + while((!vblank_active_CRT1(pSiS)) && --watchdog); + } +} + +static void +SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv) +{ + SISPtr pSiS = SISPTR(pScrn); + + short srcPitch = pPriv->srcPitch; + short height = pPriv->height; + SISOverlayRec overlay; + int srcOffsetX=0, srcOffsetY=0; + int sx, sy; + int index = 0, iscrt2 = 0; + + memset(&overlay, 0, sizeof(overlay)); + overlay.pixelFormat = pPriv->id; + overlay.pitch = overlay.origPitch = srcPitch; + overlay.keyOP = 0x03; /* DestKey mode */ + /* overlay.bobEnable = 0x02; */ + overlay.bobEnable = 0x00; /* Disable BOB (whatever that is) */ + + overlay.SCREENheight = pSiS->CurrentLayout.mode->VDisplay; + + overlay.dstBox.x1 = pPriv->drw_x - pScrn->frameX0; + overlay.dstBox.x2 = pPriv->drw_x + pPriv->drw_w - pScrn->frameX0; + overlay.dstBox.y1 = pPriv->drw_y - pScrn->frameY0; + overlay.dstBox.y2 = pPriv->drw_y + pPriv->drw_h - pScrn->frameY0; + + if((overlay.dstBox.x1 > overlay.dstBox.x2) || + (overlay.dstBox.y1 > overlay.dstBox.y2)) + return; + + if((overlay.dstBox.x2 < 0) || (overlay.dstBox.y2 < 0)) + return; + + if(overlay.dstBox.x1 < 0) { + srcOffsetX = pPriv->src_w * (-overlay.dstBox.x1) / pPriv->drw_w; + overlay.dstBox.x1 = 0; + } + if(overlay.dstBox.y1 < 0) { + srcOffsetY = pPriv->src_h * (-overlay.dstBox.y1) / pPriv->drw_h; + overlay.dstBox.y1 = 0; + } + + switch(pPriv->id){ + case PIXEL_FMT_YV12: + sx = (pPriv->src_x + srcOffsetX) & ~7; + sy = (pPriv->src_y + srcOffsetY) & ~1; + overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch; + overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1); + overlay.PSU = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx + sy*srcPitch/2) >> 1); +#ifdef SISDUALHEAD + overlay.PSY += HEADOFFSET; + overlay.PSV += HEADOFFSET; + overlay.PSU += HEADOFFSET; +#endif + overlay.PSY >>= pPriv->shiftValue; + overlay.PSV >>= pPriv->shiftValue; + overlay.PSU >>= pPriv->shiftValue; + break; + case PIXEL_FMT_I420: + sx = (pPriv->src_x + srcOffsetX) & ~7; + sy = (pPriv->src_y + srcOffsetY) & ~1; + overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch; + overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx + sy*srcPitch/2) >> 1); + overlay.PSU = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1); +#ifdef SISDUALHEAD + overlay.PSY += HEADOFFSET; + overlay.PSV += HEADOFFSET; + overlay.PSU += HEADOFFSET; +#endif + overlay.PSY >>= pPriv->shiftValue; + overlay.PSV >>= pPriv->shiftValue; + overlay.PSU >>= pPriv->shiftValue; + break; + case PIXEL_FMT_YUY2: + case PIXEL_FMT_UYVY: + case PIXEL_FMT_RGB6: + case PIXEL_FMT_RGB5: + default: + sx = (pPriv->src_x + srcOffsetX) & ~1; + sy = (pPriv->src_y + srcOffsetY); + overlay.PSY = (pPriv->bufAddr[pPriv->currentBuf] + sx*2 + sy*srcPitch); +#ifdef SISDUALHEAD + overlay.PSY += HEADOFFSET; +#endif + overlay.PSY >>= pPriv->shiftValue; + break; + } + + /* FIXME: is it possible that srcW < 0 */ + overlay.srcW = pPriv->src_w - (sx - pPriv->src_x); + overlay.srcH = pPriv->src_h - (sy - pPriv->src_y); + + if ( (pPriv->oldx1 != overlay.dstBox.x1) || + (pPriv->oldx2 != overlay.dstBox.x2) || + (pPriv->oldy1 != overlay.dstBox.y1) || + (pPriv->oldy2 != overlay.dstBox.y2) ) { + pPriv->mustwait = 1; + pPriv->oldx1 = overlay.dstBox.x1; pPriv->oldx2 = overlay.dstBox.x2; + pPriv->oldy1 = overlay.dstBox.y1; pPriv->oldy2 = overlay.dstBox.y2; + } + + /* TW: setup dispmode (MIRROR, SINGLEx) */ + set_dispmode(pScrn, pPriv); + + /* TW: set display mode SR06,32 (CRT1, CRT2 or mirror) */ + set_disptype_regs(pScrn, pPriv); + + /* set (not only calc) merge line buffer */ + merge_line_buf(pSiS, pPriv, (overlay.srcW > 384)); + + /* calculate (not set!) line buffer length */ + set_line_buf_size(&overlay); + + if (pPriv->displayMode == DISPMODE_SINGLE2) { + if (pPriv->hasTwoOverlays) { + /* TW: On chips with two overlays we use + * overlay 2 for CRT2 */ + index = 1; iscrt2 = 1; + } else { + /* TW: On chips with only one overlay we + * use that only overlay for CRT2 */ + index = 0; iscrt2 = 1; + } + overlay.VBlankActiveFunc = vblank_active_CRT2; + /* overlay.GetScanLineFunc = get_scanline_CRT2; */ + } else { + index = 0; iscrt2 = 0; + overlay.VBlankActiveFunc = vblank_active_CRT1; + /* overlay.GetScanLineFunc = get_scanline_CRT1; */ + } + + /* TW: Do the following in a loop for CRT1 and CRT2 ----------------- */ +MIRROR: + + /* calculate (not set!) scale factor */ + calc_scale_factor(&overlay, pScrn, pPriv, index, iscrt2); + + /* Select video1 (used for CRT1) or video2 (used for CRT2) */ + setvideoregmask(pSiS, Index_VI_Control_Misc2, index, 0x01); + + /* set format */ + set_format(pSiS, &overlay); + + /* set color key */ + set_colorkey(pSiS, pPriv->colorKey); + + /* set brightness, contrast, hue and saturation */ + set_brightness(pSiS, pPriv->brightness); + set_contrast(pSiS, pPriv->contrast); + if (pSiS->VGAEngine == SIS_315_VGA) { + set_hue(pSiS, pPriv->hue); + set_saturation(pSiS, pPriv->saturation); + } + + /* set overlay */ + set_overlay(pSiS, &overlay, pPriv, index); + + /* enable overlay */ + setvideoregmask (pSiS, Index_VI_Control_Misc0, 0x02, 0x02); + + if(index == 0 && + pPriv->displayMode == DISPMODE_MIRROR && + pPriv->hasTwoOverlays) { + index = 1; iscrt2 = 1; + overlay.VBlankActiveFunc = vblank_active_CRT2; + /* overlay.GetScanLineFunc = get_scanline_CRT2; */ + goto MIRROR; + } + pPriv->mustwait = 0; +} + +static FBLinearPtr +SISAllocateOverlayMemory( + ScrnInfoPtr pScrn, + FBLinearPtr linear, + int size +){ + ScreenPtr pScreen; + FBLinearPtr new_linear; + + if(linear) { + if(linear->size >= size) + return linear; + + if(xf86ResizeOffscreenLinear(linear, size)) + return linear; + + xf86FreeOffscreenLinear(linear); + } + + pScreen = screenInfo.screens[pScrn->scrnIndex]; + + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, + NULL, NULL, NULL); + + if(!new_linear) { + int max_size; + + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, + PRIORITY_EXTREME); + + if(max_size < size) return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, + NULL, NULL, NULL); + } + if (!new_linear) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Xv: Failed to allocate %dK of video memory\n", size/1024); +#ifdef TWDEBUG + else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Xv: Allocated %dK of video memory\n", size/1024); +#endif + + return new_linear; +} + +static void +SISFreeOverlayMemory(ScrnInfoPtr pScrn) +{ + SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); + + if(pPriv->linear) { + xf86FreeOffscreenLinear(pPriv->linear); + pPriv->linear = NULL; + } +} + +static void +SISStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) +{ + SISPortPrivPtr pPriv = (SISPortPrivPtr)data; + SISPtr pSiS = SISPTR(pScrn); + + if(pPriv->grabbedByV4L) + return; + + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + + if(shutdown) { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + close_overlay(pSiS, pPriv); + pPriv->mustwait = 1; + } + SISFreeOverlayMemory(pScrn); + pPriv->videoStatus = 0; + pSiS->VideoTimerCallback = NULL; + } else { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON; + pPriv->offTime = currentTime.milliseconds + OFF_DELAY; + pSiS->VideoTimerCallback = SISVideoTimerCallback; + } + } +} + +static int +SISPutImage( + ScrnInfoPtr pScrn, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + int id, unsigned char* buf, + short width, short height, + Bool sync, + RegionPtr clipBoxes, pointer data +){ + SISPtr pSiS = SISPTR(pScrn); + SISPortPrivPtr pPriv = (SISPortPrivPtr)data; + + int totalSize=0; + int depth = pSiS->CurrentLayout.bitsPerPixel >> 3; + + if(pPriv->grabbedByV4L) + return Success; + + pPriv->drw_x = drw_x; + pPriv->drw_y = drw_y; + pPriv->drw_w = drw_w; + pPriv->drw_h = drw_h; + pPriv->src_x = src_x; + pPriv->src_y = src_y; + pPriv->src_w = src_w; + pPriv->src_h = src_h; + pPriv->id = id; + pPriv->height = height; + + /* TW: Pixel formats: + 1. YU12: 3 planes: H V + Y sample period 1 1 (8 bit per pixel) + V sample period 2 2 (8 bit per pixel, subsampled) + U sample period 2 2 (8 bit per pixel, subsampled) + + Y plane is fully sampled (width*height), U and V planes + are sampled in 2x2 blocks, hence a group of 4 pixels requires + 4 + 1 + 1 = 6 bytes. The data is planar, ie in single planes + for Y, U and V. + 2. UYVY: 3 planes: H V + Y sample period 1 1 (8 bit per pixel) + V sample period 2 1 (8 bit per pixel, subsampled) + U sample period 2 1 (8 bit per pixel, subsampled) + Y plane is fully sampled (width*height), U and V planes + are sampled in 2x1 blocks, hence a group of 4 pixels requires + 4 + 2 + 2 = 8 bytes. The data is bit packed, there are no separate + Y, U or V planes. + Bit order: U0 Y0 V0 Y1 U2 Y2 V2 Y3 ... + 3. I420: Like YU12, but planes U and V are in reverse order. + 4. YUY2: Like UYVY, but order is + Y0 U0 Y1 V0 Y2 U2 Y3 V2 ... + */ + + switch(id){ + case PIXEL_FMT_YV12: + case PIXEL_FMT_I420: + pPriv->srcPitch = (width + 7) & ~7; + /* Size = width * height * 3 / 2 */ + totalSize = (pPriv->srcPitch * height * 3) >> 1; /* Verified */ + break; + case PIXEL_FMT_YUY2: + case PIXEL_FMT_UYVY: + case PIXEL_FMT_RGB6: + case PIXEL_FMT_RGB5: + default: + pPriv->srcPitch = ((width << 1) + 3) & ~3; /* Verified */ + /* Size = width * 2 * height */ + totalSize = pPriv->srcPitch * height; + } + + /* allocate memory (we do doublebuffering) */ + if(!(pPriv->linear = SISAllocateOverlayMemory(pScrn, pPriv->linear, + totalSize<<1))) + return BadAlloc; + + /* fixup pointers */ + pPriv->bufAddr[0] = (pPriv->linear->offset * depth); + pPriv->bufAddr[1] = pPriv->bufAddr[0] + totalSize; + + /* copy data */ + /* TODO: subimage */ + memcpy(pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize); + + SISDisplayVideo(pScrn, pPriv); + + /* update cliplist */ + if(pPriv->autopaintColorKey && + (pPriv->grabbedByV4L || !RegionsEqual(&pPriv->clip, clipBoxes))) { + /* We always paint colorkey for V4L */ + if (!pPriv->grabbedByV4L) + REGION_COPY(pScreen, &pPriv->clip, clipBoxes); + /* draw these */ + /* xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); - for X4.2 */ + XAAFillSolidRects(pScrn, pPriv->colorKey, GXcopy, ~0, + REGION_NUM_RECTS(clipBoxes), + REGION_RECTS(clipBoxes)); + } + + pPriv->currentBuf ^= 1; + + pPriv->videoStatus = CLIENT_VIDEO_ON; + + pSiS->VideoTimerCallback = SISVideoTimerCallback; + + return Success; +} + +static int +SISQueryImageAttributes( + ScrnInfoPtr pScrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets +){ + int pitchY, pitchUV; + int size, sizeY, sizeUV; + SISPtr pSiS = SISPTR(pScrn); + + if(*w < IMAGE_MIN_WIDTH) *w = IMAGE_MIN_WIDTH; + if(*h < IMAGE_MIN_HEIGHT) *h = IMAGE_MIN_HEIGHT; + + if(pSiS->Flags650 & SiS650_LARGEOVERLAY) { + if(*w > IMAGE_MAX_WIDTH_M650) *w = IMAGE_MAX_WIDTH_M650; + if(*h > IMAGE_MAX_HEIGHT_M650) *h = IMAGE_MAX_HEIGHT_M650; + } else { + if(*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH; + if(*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT; + } + + switch(id) { + case PIXEL_FMT_YV12: + case PIXEL_FMT_I420: + *w = (*w + 7) & ~7; + *h = (*h + 1) & ~1; + pitchY = *w; + pitchUV = *w >> 1; + if(pitches) { + pitches[0] = pitchY; + pitches[1] = pitches[2] = pitchUV; + } + sizeY = pitchY * (*h); + sizeUV = pitchUV * ((*h) >> 1); + if(offsets) { + offsets[0] = 0; + offsets[1] = sizeY; + offsets[2] = sizeY + sizeUV; + } + size = sizeY + (sizeUV << 1); + break; + case PIXEL_FMT_YUY2: + case PIXEL_FMT_UYVY: + case PIXEL_FMT_RGB6: + case PIXEL_FMT_RGB5: + default: + *w = (*w + 1) & ~1; + pitchY = *w << 1; + if(pitches) pitches[0] = pitchY; + if(offsets) offsets[0] = 0; + size = pitchY * (*h); + break; + } + + return size; +} + +static void +SISVideoTimerCallback (ScrnInfoPtr pScrn, Time now) +{ + SISPtr pSiS = SISPTR(pScrn); + SISPortPrivPtr pPriv = NULL; + unsigned char sridx, cridx; + + pSiS->VideoTimerCallback = NULL; + + if(!pScrn->vtSema) return; + + if (pSiS->adaptor) { + pPriv = GET_PORT_PRIVATE(pScrn); + if(!pPriv->videoStatus) + pPriv = NULL; + } + + if (pPriv) { + if(pPriv->videoStatus & TIMER_MASK) { + UpdateCurrentTime(); + if(pPriv->offTime < currentTime.milliseconds) { + if(pPriv->videoStatus & OFF_TIMER) { + /* Turn off the overlay */ + sridx = inSISREG(SISSR); cridx = inSISREG(SISCR); + close_overlay(pSiS, pPriv); + outSISREG(SISSR, sridx); outSISREG(SISCR, cridx); + pPriv->mustwait = 1; + pPriv->videoStatus = FREE_TIMER; + pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; + pSiS->VideoTimerCallback = SISVideoTimerCallback; + } else + if(pPriv->videoStatus & FREE_TIMER) { + SISFreeOverlayMemory(pScrn); + pPriv->mustwait = 1; + pPriv->videoStatus = 0; + } + } else + pSiS->VideoTimerCallback = SISVideoTimerCallback; + } + } +} + +/* TW: Offscreen surface stuff */ + +static int +SISAllocSurface ( + ScrnInfoPtr pScrn, + int id, + unsigned short w, + unsigned short h, + XF86SurfacePtr surface +) +{ + SISPtr pSiS = SISPTR(pScrn); + SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); + int size, depth; + +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv: SISAllocSurface called\n"); +#endif + + if((w < IMAGE_MIN_WIDTH) || (h < IMAGE_MIN_HEIGHT)) + return BadValue; + if(pSiS->Flags650 & SiS650_LARGEOVERLAY) { + if((w > IMAGE_MAX_WIDTH_M650) || (h > IMAGE_MAX_HEIGHT_M650)) + return BadValue; + } else { + if((w > IMAGE_MAX_WIDTH) || (h > IMAGE_MAX_HEIGHT)) + return BadValue; + } + + if(pPriv->grabbedByV4L) + return BadAlloc; + + depth = pSiS->CurrentLayout.bitsPerPixel >> 3; + w = (w + 1) & ~1; + pPriv->pitch = ((w << 1) + 63) & ~63; /* Only packed pixel modes supported */ + size = h * pPriv->pitch; /* / depth; - Why? */ + pPriv->linear = SISAllocateOverlayMemory(pScrn, pPriv->linear, size); + if(!pPriv->linear) + return BadAlloc; + + pPriv->offset = pPriv->linear->offset * depth; + + surface->width = w; + surface->height = h; + surface->pScrn = pScrn; + surface->id = id; + surface->pitches = &pPriv->pitch; + surface->offsets = &pPriv->offset; + surface->devPrivate.ptr = (pointer)pPriv; + + close_overlay(pSiS, pPriv); + pPriv->videoStatus = 0; + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + pSiS->VideoTimerCallback = NULL; + pPriv->grabbedByV4L = TRUE; + return Success; +} + +static int +SISStopSurface (XF86SurfacePtr surface) +{ + SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); + SISPtr pSiS = SISPTR(surface->pScrn); + + if(pPriv->grabbedByV4L && pPriv->videoStatus) { + close_overlay(pSiS, pPriv); + pPriv->mustwait = 1; + pPriv->videoStatus = 0; + } + return Success; +} + +static int +SISFreeSurface (XF86SurfacePtr surface) +{ + SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); + + if(pPriv->grabbedByV4L) { + SISStopSurface(surface); + SISFreeOverlayMemory(surface->pScrn); + pPriv->grabbedByV4L = FALSE; + } + return Success; +} + +static int +SISGetSurfaceAttribute ( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value +) +{ + SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); + + return SISGetPortAttribute(pScrn, attribute, value, (pointer)pPriv); +} + +static int +SISSetSurfaceAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 value +) +{ + SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);; + + return SISSetPortAttribute(pScrn, attribute, value, (pointer)pPriv); +} + +static int +SISDisplaySurface ( + XF86SurfacePtr surface, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + RegionPtr clipBoxes +) +{ + ScrnInfoPtr pScrn = surface->pScrn; + SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr); + +#ifdef TWDEBUG + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv: DisplaySurface called\n"); +#endif + + if(!pPriv->grabbedByV4L) + return Success; + + pPriv->drw_x = drw_x; + pPriv->drw_y = drw_y; + pPriv->drw_w = drw_w; + pPriv->drw_h = drw_h; + pPriv->src_x = src_x; + pPriv->src_y = src_y; + pPriv->src_w = src_w; + pPriv->src_h = src_h; + pPriv->id = surface->id; + pPriv->height = surface->height; + pPriv->bufAddr[0] = surface->offsets[0]; + pPriv->currentBuf = 0; + pPriv->srcPitch = surface->pitches[0]; + + SISDisplayVideo(pScrn, pPriv); + + if(pPriv->autopaintColorKey) { + XAAFillSolidRects(pScrn, pPriv->colorKey, GXcopy, ~0, + REGION_NUM_RECTS(clipBoxes), + REGION_RECTS(clipBoxes)); + } + + pPriv->videoStatus = CLIENT_VIDEO_ON; + + return Success; +} + +#define NUMOFFSCRIMAGES 4 + +static XF86OffscreenImageRec SISOffscreenImages_300[NUMOFFSCRIMAGES] = +{ + { + &SISImages[0], /* YUV2 */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SISAllocSurface, + SISFreeSurface, + SISDisplaySurface, + SISStopSurface, + SISGetSurfaceAttribute, + SISSetSurfaceAttribute, + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + NUM_ATTRIBUTES_300, + &SISAttributes_300[0] /* Support all attributes */ + }, + { + &SISImages[2], /* UYVY */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SISAllocSurface, + SISFreeSurface, + SISDisplaySurface, + SISStopSurface, + SISGetSurfaceAttribute, + SISSetSurfaceAttribute, + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + NUM_ATTRIBUTES_300, + &SISAttributes_300[0] /* Support all attributes */ + } + , + { + &SISImages[4], /* RV15 */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SISAllocSurface, + SISFreeSurface, + SISDisplaySurface, + SISStopSurface, + SISGetSurfaceAttribute, + SISSetSurfaceAttribute, + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + NUM_ATTRIBUTES_300, + &SISAttributes_300[0] /* Support all attributes */ + }, + { + &SISImages[5], /* RV16 */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SISAllocSurface, + SISFreeSurface, + SISDisplaySurface, + SISStopSurface, + SISGetSurfaceAttribute, + SISSetSurfaceAttribute, + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + NUM_ATTRIBUTES_300, + &SISAttributes_300[0] /* Support all attributes */ + } +}; + +static XF86OffscreenImageRec SISOffscreenImages_325[NUMOFFSCRIMAGES] = +{ + { + &SISImages[0], /* YUV2 */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SISAllocSurface, + SISFreeSurface, + SISDisplaySurface, + SISStopSurface, + SISGetSurfaceAttribute, + SISSetSurfaceAttribute, + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + NUM_ATTRIBUTES_325, + &SISAttributes_325[0] /* Support all attributes */ + }, + { + &SISImages[2], /* UYVY */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SISAllocSurface, + SISFreeSurface, + SISDisplaySurface, + SISStopSurface, + SISGetSurfaceAttribute, + SISSetSurfaceAttribute, + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + NUM_ATTRIBUTES_325, + &SISAttributes_325[0] /* Support all attributes */ + } + , + { + &SISImages[4], /* RV15 */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SISAllocSurface, + SISFreeSurface, + SISDisplaySurface, + SISStopSurface, + SISGetSurfaceAttribute, + SISSetSurfaceAttribute, + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + NUM_ATTRIBUTES_325, + &SISAttributes_325[0] /* Support all attributes */ + }, + { + &SISImages[5], /* RV16 */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SISAllocSurface, + SISFreeSurface, + SISDisplaySurface, + SISStopSurface, + SISGetSurfaceAttribute, + SISSetSurfaceAttribute, + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + NUM_ATTRIBUTES_325, + &SISAttributes_325[0] /* Support all attributes */ + } +}; + +static XF86OffscreenImageRec SISOffscreenImages_M650[NUMOFFSCRIMAGES] = +{ + { + &SISImages[0], /* YUV2 */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SISAllocSurface, + SISFreeSurface, + SISDisplaySurface, + SISStopSurface, + SISGetSurfaceAttribute, + SISSetSurfaceAttribute, + IMAGE_MAX_WIDTH_M650, IMAGE_MAX_HEIGHT_M650, + NUM_ATTRIBUTES_325, + &SISAttributes_325[0] /* Support all attributes */ + }, + { + &SISImages[2], /* UYVY */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SISAllocSurface, + SISFreeSurface, + SISDisplaySurface, + SISStopSurface, + SISGetSurfaceAttribute, + SISSetSurfaceAttribute, + IMAGE_MAX_WIDTH_M650, IMAGE_MAX_HEIGHT_M650, + NUM_ATTRIBUTES_325, + &SISAttributes_325[0] /* Support all attributes */ + } + , + { + &SISImages[4], /* RV15 */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SISAllocSurface, + SISFreeSurface, + SISDisplaySurface, + SISStopSurface, + SISGetSurfaceAttribute, + SISSetSurfaceAttribute, + IMAGE_MAX_WIDTH_M650, IMAGE_MAX_HEIGHT_M650, + NUM_ATTRIBUTES_325, + &SISAttributes_325[0] /* Support all attributes */ + }, + { + &SISImages[5], /* RV16 */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + SISAllocSurface, + SISFreeSurface, + SISDisplaySurface, + SISStopSurface, + SISGetSurfaceAttribute, + SISSetSurfaceAttribute, + IMAGE_MAX_WIDTH_M650, IMAGE_MAX_HEIGHT_M650, + NUM_ATTRIBUTES_325, + &SISAttributes_325[0] /* Support all attributes */ + } +}; + +static void +SISInitOffscreenImages(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + SISPtr pSiS = SISPTR(pScrn); + + if(pSiS->VGAEngine == SIS_300_VGA) { + xf86XVRegisterOffscreenImages(pScreen, SISOffscreenImages_300, NUMOFFSCRIMAGES); + } else { + if(pSiS->Flags650 & SiS650_LARGEOVERLAY) { + xf86XVRegisterOffscreenImages(pScreen, SISOffscreenImages_M650, NUMOFFSCRIMAGES); + } else { + xf86XVRegisterOffscreenImages(pScreen, SISOffscreenImages_325, NUMOFFSCRIMAGES); + } + } +} diff --git a/src/vgatypes.h b/src/vgatypes.h new file mode 100644 index 0000000..d377dee --- /dev/null +++ b/src/vgatypes.h @@ -0,0 +1,368 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/vgatypes.h,v 1.3 2003/02/10 01:14:16 tsi Exp $ */ + +#ifndef _VGATYPES_ +#define _VGATYPES_ + +#ifdef LINUX_XF86 +#include "xf86Pci.h" +#endif + +#ifdef LINUX_KERNEL /* TW: We don't want the X driver to depend on kernel source */ +#include <linux/ioctl.h> +#endif + +#ifndef TC +#define far +#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 PUCHAR +typedef UCHAR far *PUCHAR; +#endif + +#ifndef PUSHORT +typedef USHORT far *PUSHORT; +#endif + +#ifndef PULONG +typedef ULONG far *PULONG; +#endif + +#ifndef PVOID +typedef void far *PVOID; +#endif +#ifndef VOID +typedef void VOID; +#endif + +#ifndef BOOLEAN +typedef UCHAR BOOLEAN; +#endif + +#ifndef WINCE_HEADER +#ifndef bool +typedef UCHAR bool; +#endif +#endif /*WINCE_HEADER*/ + +#ifndef VBIOS_VER_MAX_LENGTH +#define VBIOS_VER_MAX_LENGTH 4 +#endif + +#ifndef LINUX_KERNEL /* For kernel, this is defined in sisfb.h */ +#ifndef WIN2000 +#ifndef SIS_CHIP_TYPE +typedef enum _SIS_CHIP_TYPE { + SIS_VGALegacy = 0, +#ifdef LINUX_XF86 + SIS_530, /* TW */ + SIS_OLD, /* TW */ +#endif + SIS_300, + SIS_630, + SIS_730, + SIS_540, + SIS_315H, /* SiS 310 */ + SIS_315, + SIS_315PRO, /* SiS 325 */ + SIS_550, + SIS_650, + SIS_740, + SIS_330, + MAX_SIS_CHIP +} SIS_CHIP_TYPE; +#endif +#endif +#endif + +#ifndef WIN2000 +#ifndef SIS_VB_CHIP_TYPE +typedef enum _SIS_VB_CHIP_TYPE { + VB_CHIP_Legacy = 0, + VB_CHIP_301, + VB_CHIP_301B, + VB_CHIP_301LV, + VB_CHIP_301LVX, + VB_CHIP_302, + VB_CHIP_302B, + VB_CHIP_302LV, + VB_CHIP_302LVX, + VB_CHIP_303, + VB_CHIP_UNKNOWN, /* other video bridge or no video bridge */ + MAX_VB_CHIP +} SIS_VB_CHIP_TYPE; +#endif +#endif + +#ifndef WIN2000 +#ifndef SIS_LCD_TYPE +typedef 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, /* TW: FSTN */ + LCD_1400x1050, + LCD_1152x864, + LCD_1152x768, + LCD_1280x768, + LCD_1024x600, + LCD_UNKNOWN +} SIS_LCD_TYPE; +#endif +#endif + +#ifndef WIN2000 /* mark by Paul, Move definition to sisv.h*/ +#ifndef PSIS_DSReg +typedef struct _SIS_DSReg +{ + UCHAR jIdx; + UCHAR jVal; +} SIS_DSReg, *PSIS_DSReg; +#endif + +#ifndef SIS_HW_DEVICE_INFO + +typedef struct _SIS_HW_DEVICE_INFO SIS_HW_DEVICE_INFO, *PSIS_HW_DEVICE_INFO; + +typedef BOOLEAN (*PSIS_QUERYSPACE) (PSIS_HW_DEVICE_INFO, ULONG, ULONG, ULONG *); + + +struct _SIS_HW_DEVICE_INFO +{ + PVOID pDevice; /* The pointer to the physical device data structure + in each OS or NULL for unused. */ + UCHAR *pjVirtualRomBase; /* base virtual address of VBIOS ROM Space */ + /* or base virtual address of ROM image file. */ + /* if NULL, then read from pjROMImage; */ + /* Note:ROM image file is the file of VBIOS ROM */ + + BOOLEAN UseROM; /* TW: Use the ROM image if provided */ + + UCHAR *pjCustomizedROMImage;/* base virtual address of ROM image file. */ + /* wincE:ROM image file is the file for OEM */ + /* customized table */ + /* Linux: not used */ + /* NT : not used */ + /* Note : pjCustomizedROMImage=NULL if no ROM image file */ + + UCHAR *pjVideoMemoryAddress;/* base virtual memory address */ + /* of Linear VGA memory */ + + ULONG ulVideoMemorySize; /* size, in bytes, of the memory on the board */ + ULONG ulIOAddress; /* base I/O address of VGA ports (0x3B0) */ + UCHAR jChipType; /* Used to Identify SiS Graphics Chip */ + /* defined in the data structure type */ + /* "SIS_CHIP_TYPE" */ + + UCHAR jChipRevision; /* Used to Identify SiS Graphics Chip Revision */ + UCHAR ujVBChipID; /* the ID of video bridge */ + /* defined in the data structure type */ + /* "SIS_VB_CHIP_TYPE" */ + + USHORT usExternalChip; /* NO VB or other video bridge(not */ + /* SiS video bridge) */ + /* if ujVBChipID = VB_CHIP_UNKNOWN, */ + /* then bit0=1 : LVDS,bit1=1 : trumpion, */ + /* bit2=1 : CH7005 & no video bridge if */ + /* usExternalChip = 0. */ + /* Note: CR37[3:1]: */ + /* 001:SiS 301 */ + /* 010:LVDS */ + /* 011:Trumpion LVDS Scaling Chip */ + /* 100:LVDS(LCD-out)+Chrontel 7005 */ + /* 101:Single Chrontel 7005 */ + /* TW: This has changed on 310/325 series! */ + + ULONG ulCRT2LCDType; /* defined in the data structure type */ + /* "SIS_LCD_TYPE" */ + + BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */ + + BOOLEAN bSkipDramSizing; /* True: Skip video memory sizing. */ + PSIS_DSReg pSR; /* restore SR registers in initial function. */ + /* end data :(idx, val) = (FF, FF). */ + /* Note : restore SR registers if */ + /* bSkipDramSizing = TRUE */ + + PSIS_DSReg pCR; /* restore CR registers in initial function. */ + /* end data :(idx, val) = (FF, FF) */ + /* Note : restore cR registers if */ + /* bSkipDramSizing = TRUE */ + + PSIS_QUERYSPACE pQueryVGAConfigSpace; /* Get/Set VGA Configuration */ + /* space */ + + PSIS_QUERYSPACE pQueryNorthBridgeSpace;/* Get/Set North Bridge */ + /* space */ + + UCHAR szVBIOSVer[VBIOS_VER_MAX_LENGTH]; + + UCHAR pdc; /* TW: PanelDelayCompensation */ + +#ifdef LINUX_XF86 + PCITAG PciTag; /* PCI Tag for Linux XF86 */ +#endif +}; +#endif +#endif + + +/* TW: Addtional IOCTL 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 */ + +/* TW: ioctl for identifying and giving some info (esp. memory heap start) */ +#define SISFB_GET_INFO 0x80046ef8 /* Wow, what a terrible hack... */ + +/* TW: Structure argument for SISFB_GET_INFO ioctl */ +typedef struct _SISFB_INFO sisfb_info, *psisfb_info; + +struct _SISFB_INFO { + unsigned long sisfb_id; /* for identifying sisfb */ +#ifndef SISFB_ID +#define SISFB_ID 0x53495346 /* Identify myself with 'SISF' */ +#endif + int chip_id; /* PCI ID of detected chip */ + int memory; /* video memory in KB which sisfb manages */ + int heapstart; /* heap start (= sisfb "mem" argument) in KB */ + unsigned char fbvidmode; /* current sisfb mode */ + + unsigned char sisfb_version; + unsigned char sisfb_revision; + unsigned char sisfb_patchlevel; + + unsigned char sisfb_caps; /* sisfb's capabilities */ + + int sisfb_tqlen; /* turbo queue length (in KB) */ + + unsigned int sisfb_pcibus; /* The card's PCI ID */ + unsigned int sisfb_pcislot; + unsigned int sisfb_pcifunc; + + unsigned char sisfb_lcdpdc; + + char reserved[236]; /* for future use */ +}; +#endif + +#ifndef WIN2000 +#ifndef WINCE_HEADER +#ifndef BUS_DATA_TYPE +typedef enum _BUS_DATA_TYPE { + ConfigurationSpaceUndefined = -1, + Cmos, + EisaConfiguration, + Pos, + CbusConfiguration, + PCIConfiguration, + VMEConfiguration, + NuBusConfiguration, + PCMCIAConfiguration, + MPIConfiguration, + MPSAConfiguration, + PNPISAConfiguration, + MaximumBusDataType +} BUS_DATA_TYPE, *PBUS_DATA_TYPE; +#endif +#endif /* WINCE_HEADER */ + +#ifndef PCI_TYPE0_ADDRESSES +#define PCI_TYPE0_ADDRESSES 6 +#endif + +#ifndef PCI_TYPE1_ADDRESSES +#define PCI_TYPE1_ADDRESSES 2 +#endif + +#ifndef WINCE_HEADER +#ifndef PCI_COMMON_CONFIG +typedef struct _PCI_COMMON_CONFIG { + USHORT VendorID; /* (ro) */ + USHORT DeviceID; /* (ro) */ + USHORT Command; /* Device control */ + USHORT Status; + UCHAR RevisionID; /* (ro) */ + UCHAR ProgIf; /* (ro) */ + UCHAR SubClass; /* (ro) */ + UCHAR BaseClass; /* (ro) */ + UCHAR CacheLineSize; /* (ro+) */ + UCHAR LatencyTimer; /* (ro+) */ + UCHAR HeaderType; /* (ro) */ + UCHAR BIST; /* Built in self test */ + + union { + struct _PCI_HEADER_TYPE_0 { + ULONG BaseAddresses[PCI_TYPE0_ADDRESSES]; + ULONG CIS; + USHORT SubVendorID; + USHORT SubSystemID; + ULONG ROMBaseAddress; + ULONG Reserved2[2]; + + UCHAR InterruptLine; /* */ + UCHAR InterruptPin; /* (ro) */ + UCHAR MinimumGrant; /* (ro) */ + UCHAR MaximumLatency; /* (ro) */ + } type0; + + + } u; + + UCHAR DeviceSpecific[192]; + +} PCI_COMMON_CONFIG, *PPCI_COMMON_CONFIG; +#endif +#endif /* WINCE_HEADER */ + +#ifndef FIELD_OFFSET +#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field)) +#endif + +#ifndef PCI_COMMON_HDR_LENGTH +#define PCI_COMMON_HDR_LENGTH (FIELD_OFFSET (PCI_COMMON_CONFIG, DeviceSpecific)) +#endif +#endif + +#endif diff --git a/src/vstruct.h b/src/vstruct.h new file mode 100644 index 0000000..7005986 --- /dev/null +++ b/src/vstruct.h @@ -0,0 +1,571 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/vstruct.h,v 1.3 2003/02/10 01:14:17 tsi Exp $ */ + +#ifdef _INIT_ +#define EXTERN +#else +#define EXTERN extern +#endif /* _INIT_ */ + +#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; + +/*add for LCDA*/ +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; +} 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_ModeInfo; + USHORT Ext_Point; + USHORT Ext_VESAID; + UCHAR Ext_VESAMEMSize; + UCHAR Ext_RESINFO; + UCHAR VB_ExtTVFlickerIndex; + UCHAR VB_ExtTVEdgeIndex; + UCHAR VB_ExtTVYFilterIndex; + UCHAR REFindex; +} SiS_ExtStruct; + +typedef struct _SiS_Ext2Struct +{ + USHORT Ext_InfoFlag; + UCHAR Ext_CRT1CRTC; + UCHAR Ext_CRTVCLK; + UCHAR Ext_CRT2CRTC; + UCHAR ModeID; + USHORT XRes; + USHORT YRes; + USHORT ROM_OFFSET; +} 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_ECLKDataStruct +{ + UCHAR SR2E,SR2F,SR30; + USHORT CLOCK; +} SiS_ECLKDataStruct; + +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]; + +typedef struct _SiS_Private +{ +#ifdef LINUX_KERNEL + USHORT RelIO; +#endif + USHORT SiS_P3c4; + USHORT SiS_P3d4; + USHORT SiS_P3c0; + USHORT SiS_P3ce; + USHORT SiS_P3c2; + USHORT SiS_P3ca; + USHORT SiS_P3c6; + USHORT SiS_P3c7; + USHORT SiS_P3c8; + USHORT SiS_P3c9; + USHORT SiS_P3da; + USHORT SiS_Part1Port; + USHORT SiS_Part2Port; + USHORT SiS_Part3Port; + USHORT SiS_Part4Port; + USHORT SiS_Part5Port; + USHORT SiS_IF_DEF_LVDS; + USHORT SiS_IF_DEF_TRUMPION; + USHORT SiS_IF_DEF_DSTN; + USHORT SiS_IF_DEF_FSTN; + USHORT SiS_IF_DEF_CH70xx; + USHORT SiS_IF_DEF_HiVision; + UCHAR SiS_VGAINFO; + BOOLEAN SiS_UseROM; + int SiS_CHOverScan; + BOOLEAN SiS_CHSOverScan; + BOOLEAN SiS_ChSW; + int SiS_UseOEM; + USHORT SiS_Backup70xx; + USHORT SiS_CRT1Mode; + USHORT SiS_flag_clearbuffer; + int SiS_RAMType; + UCHAR SiS_ChannelAB; + UCHAR SiS_DataBusWidth; + USHORT SiS_ModeType; + USHORT SiS_VBInfo; + USHORT SiS_LCDResInfo; + USHORT SiS_LCDTypeInfo; + USHORT SiS_LCDInfo; + USHORT SiS_VBType; + USHORT SiS_VBExtInfo; + USHORT SiS_HiVision; + 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_Clk; + USHORT SiS_DDC_DataShift; + USHORT SiS_DDC_DeviceAddr; + USHORT SiS_DDC_ReadAddr; + USHORT SiS_DDC_SecAddr; + USHORT SiS_Panel800x600; + USHORT SiS_Panel1024x768; + USHORT SiS_Panel1280x1024; + USHORT SiS_Panel1600x1200; + USHORT SiS_Panel1280x960; + USHORT SiS_Panel1400x1050; + USHORT SiS_Panel320x480; + USHORT SiS_Panel1152x768; + USHORT SiS_Panel1280x768; + USHORT SiS_Panel1024x600; + USHORT SiS_Panel640x480; + USHORT SiS_Panel1152x864; + USHORT SiS_PanelMax; + USHORT SiS_PanelMinLVDS; + USHORT SiS_PanelMin301; + USHORT SiS_ChrontelInit; + + /* Pointers: */ + 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; + const SiS_ECLKDataStruct *SiS_ECLKData; + const SiS_VCLKDataStruct *SiS_VCLKData; + const SiS_VBVCLKDataStruct *SiS_VBVCLKData; + const SiS_StResInfoStruct *SiS_StResInfo; + const SiS_ModeResInfoStruct *SiS_ModeResInfo; + const UCHAR *SiS_ScreenOffset; + + const UCHAR *pSiS_OutputSelect; + const UCHAR *pSiS_SoftSetting; + + const DRAM4Type *SiS_SR15; /* pointer : point to array */ +#ifndef LINUX_XF86 + 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; /*301b*/ + const USHORT *pSiS_VideoSenseData2; + const USHORT *pSiS_YCSenseData2; +#endif + 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 SiS_LCDDataStruct *SiS_StLCD1024x768Data; + const SiS_LCDDataStruct *SiS_ExtLCD1024x768Data; + const SiS_LCDDataStruct *SiS_St2LCD1024x768Data; + const SiS_LCDDataStruct *SiS_StLCD1280x1024Data; + const SiS_LCDDataStruct *SiS_ExtLCD1280x1024Data; + const SiS_LCDDataStruct *SiS_St2LCD1280x1024Data; + const SiS_LCDDataStruct *SiS_NoScaleData1024x768; + const SiS_LCDDataStruct *SiS_NoScaleData1280x1024; + const SiS_LCDDataStruct *SiS_LCD1280x960Data; + const SiS_LCDDataStruct *SiS_NoScaleData1400x1050; + const SiS_LCDDataStruct *SiS_NoScaleData1600x1200; + const SiS_LCDDataStruct *SiS_StLCD1400x1050Data; + const SiS_LCDDataStruct *SiS_StLCD1600x1200Data; + const SiS_LCDDataStruct *SiS_ExtLCD1400x1050Data; + const SiS_LCDDataStruct *SiS_ExtLCD1600x1200Data; + const SiS_TVDataStruct *SiS_StPALData; + const SiS_TVDataStruct *SiS_ExtPALData; + const SiS_TVDataStruct *SiS_StNTSCData; + const SiS_TVDataStruct *SiS_ExtNTSCData; +#ifdef oldHV + const SiS_TVDataStruct *SiS_St1HiTVData; + const SiS_TVDataStruct *SiS_St2HiTVData; + const SiS_TVDataStruct *SiS_ExtHiTVData; +#endif + const UCHAR *SiS_NTSCTiming; + const UCHAR *SiS_PALTiming; +#ifdef oldHV + const UCHAR *SiS_HiTVExtTiming; + const UCHAR *SiS_HiTVSt1Timing; + const UCHAR *SiS_HiTVSt2Timing; + const UCHAR *SiS_HiTVTextTiming; + const UCHAR *SiS_HiTVGroup3Data; + const UCHAR *SiS_HiTVGroup3Simu; + const UCHAR *SiS_HiTVGroup3Text; +#endif + const SiS_PanelDelayTblStruct *SiS_PanelDelayTbl; + const SiS_PanelDelayTblStruct *SiS_PanelDelayTblLVDS; + 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_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_LVDS320x480Data_1; + const SiS_LVDSDataStruct *SiS_LCDA1400x1050Data_1; + const SiS_LVDSDataStruct *SiS_LCDA1400x1050Data_2; + const SiS_LVDSDataStruct *SiS_LCDA1600x1200Data_1; + const SiS_LVDSDataStruct *SiS_LCDA1600x1200Data_2; + const SiS_LVDSDataStruct *SiS_LVDSXXXxXXXData_1; + 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_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 *LVDS1024x768Des_1; + const SiS_LVDSDesStruct *LVDS1280x1024Des_1; + const SiS_LVDSDesStruct *LVDS1400x1050Des_1; + const SiS_LVDSDesStruct *LVDS1600x1200Des_1; + const SiS_LVDSDesStruct *LVDS1024x768Des_2; + const SiS_LVDSDesStruct *LVDS1280x1024Des_2; + const SiS_LVDSDesStruct *LVDS1400x1050Des_2; + const SiS_LVDSDesStruct *LVDS1600x1200Des_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_CHTVCRT1UNTSC; + const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1ONTSC; + const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1UPAL; + const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1OPAL; + const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1SOPAL; + + const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1320x480_1; + + const SiS_LCDACRT1DataStruct *SiS_LCDACRT1800x600_1; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11024x768_1; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11280x1024_1; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11400x1050_1; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11600x1200_1; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT1800x600_1_H; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11024x768_1_H; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11280x1024_1_H; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11400x1050_1_H; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11600x1200_1_H; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT1800x600_2; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11024x768_2; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11280x1024_2; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11400x1050_2; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11600x1200_2; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT1800x600_2_H; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11024x768_2_H; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11280x1024_2_H; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11400x1050_2_H; + const SiS_LCDACRT1DataStruct *SiS_LCDACRT11600x1200_2_H; + + /* TW: New for 650/301LV */ + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_1; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_1; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1400x1050_1; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1600x1200_1; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_2; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_2; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1400x1050_2; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1600x1200_2; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_3; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_3; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1400x1050_3; + const SiS_Part2PortTblStruct *SiS_CRT2Part2_1600x1200_3; + + 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; + + 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 CModeFlag; + USHORT CInfoFlag; + BOOLEAN SiS_CHPALM; + BOOLEAN SiS_CHPALN; +} SiS_Private; + +#endif + |