summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CALLMAP22
-rw-r--r--README76
-rw-r--r--Release.txt231
-rw-r--r--man/siliconmotion.man203
-rw-r--r--src/regsmi.h207
-rw-r--r--src/smi.h362
-rw-r--r--src/smi_accel.c1108
-rw-r--r--src/smi_dac.c99
-rw-r--r--src/smi_dga.c301
-rw-r--r--src/smi_driver.c3294
-rw-r--r--src/smi_hwcurs.c375
-rw-r--r--src/smi_i2c.c115
-rw-r--r--src/smi_shadow.c226
-rw-r--r--src/smi_video.c2548
-rw-r--r--src/smi_video.h103
15 files changed, 9270 insertions, 0 deletions
diff --git a/CALLMAP b/CALLMAP
new file mode 100644
index 0000000..b7c9043
--- /dev/null
+++ b/CALLMAP
@@ -0,0 +1,22 @@
+-- Only Once, calling order --
+ChipIdentify (SMIIdentify)
+ChipProbe (SMIProbe)
+ Passive only, no ram determination, no writing
+
+-- For each ScrnInfoRec, still calling order --
+ChipPreInit (SMIPreInit)
+ Allows probing and mapping, hardware must remain unchanged
+ ChipGetRec
+
+ChipScreenInit
+ ChipMapMem
+ ChipSave
+ vgaHWSaveMMIO
+ ChipModeInit
+ vtSema=TRUE
+ ChipWriteMode
+ vgaHWRestoreMMIO
+
+Header: \\Mercury\Projects\archives\XFree86 4.0\CALLMAP.-arc 1.1 13 Jul 2000 18:16:58 Frido $
+
+$XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/CALLMAP,v 1.1 2000/11/28 20:59:18 dawes Exp $
diff --git a/README b/README
new file mode 100644
index 0000000..d2f142d
--- /dev/null
+++ b/README
@@ -0,0 +1,76 @@
+What works:
+- Supports 8bpp, 16bpp and 24bpp. Heavy testing on SM720.
+
+XCONFIG options:
+
+The driver supports quite a few different XConfig options, which can
+be used to tune the driver and improve performance. Without any options,
+the driver will use conservative settings which should work on most
+hardware. Large improvements in performance are possible by selecting
+the proper options, which will probably work on most systems.
+
+Cursor:
+
+- "hwcursor" "off" behaves exactly like "swcursor". Default: "on"
+- "swcursor" will disable the HW Cursor. HW Cursor is used by default and
+ no option is needed to enable it.
+
+Display:
+
+- "ShadowFB" Use shadow framebuffer. Default: off.
+- "Rotate" "cw" | "ccw" Rotate the screen CW - clockwise or CCW - counter
+ clockwise. Uses ShadowFB. Default: no rotation.
+- "UseBIOS" Use BIOS to set modes. Default: on.
+- "ZoomOnLCD" Allow changing resolution on panel. Default: off.
+
+Overlays:
+
+- "VideoKey" Set chroma key for video. Default: Off blue.
+- "ByteSwap" Turn on YUV byte swapping. Defaul: off.
+
+Video memory:
+
+- "set_mclk" sets the memory clock, format is:
+ Option "set_mclk" "50000"
+ in the XF86Config file. Valid values are any
+ integer <= 100000, where 100000 == 100 MHz.
+
+Acceleration and graphic engine:
+
+- "NoAccel" turns off all acceleration
+- "fifo_aggressive", "fifo_moderate" and "fifo_conservative" alter the settings
+ for the threshold at which the pixel FIFO takes over the internal
+ memory bus to refill itself. The smaller this threshold, the better
+ the acceleration performance of the card. You may try the fastest
+ setting ("aggressive") and move down if you encounter pixel corruption.
+ The optimal setting will probably depend on dot-clock and on color
+ depth. Note that specifying any of these options will also alter other
+ memory settings which should increase performance, so you should at
+ least use "fifo_conservative" (this uses the chip defaults).
+- Common XAA acceleration options to disable primitives for test purposes:
+ "XaaNoScreenToScreenCopy"
+ "XaaNoSolidFillRect"
+ "XaaNoColor8x8PatternFillRect"
+ "XaaNoImageWriteRect"
+ "XaaNoPixmapCache"
+
+PCI bus:
+
+- "pci_burst" will enable PCI burst mode. This should work on all but a
+ few "broken" PCI chipsets, and will increase performance. Option may
+ take a parameter "on", "off", "yes", etc...
+- "pci_retry" will allow the driver to rely on PCI Retry to program the
+ ViRGE registers. "pci_burst" must be enabled for this to work.
+ This will increase performance, especially for small fills/blits,
+ because the driver does not have to poll the ViRGE before sending it
+ commands to make sure it is ready. It should work on most
+ recent PCI chipsets.
+
+Debug:
+
+- "ShowCache" Enable or disable viewing offscreen cache memory. A
+ development debug option. Default: off.
+
+Header: //Mercury/Projects/archives/XFree86/4.0/README.-arc 1.2 14 Sep 2000 12:28:36 Frido $
+
+$XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/README,v 1.3 2001/02/15 18:20:33 dawes Exp $
diff --git a/Release.txt b/Release.txt
new file mode 100644
index 0000000..204dba7
--- /dev/null
+++ b/Release.txt
@@ -0,0 +1,231 @@
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.1.0
+ Alpha Release 1.3.1cz, 11/12/2001
+-------------------------------------------------------------------------------
+
+Extensions:
+
+- gamma correction for 24 bit true color mode.
+
+Known problems:
+
+- gamma correction does not work for 16 bit true color mode:
+ LoadPalette gets a gamma correction color table for 5:6:5 RGB,
+ whereas the SMI RAMDAC wants a 8:8:8 RGB color table.
+
+- gamma correction only implemented for the Lynx3DM
+
+- StopVideo don't work. The graphics controller continues to write
+ into the capture buffer
+
+Fixed bugs (or new bugs :) ):
+
+- in SMI_ScreenInit frame buffer size calculation for video changed.
+
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.1.0
+ Alpha Release 1.3.0cz, 10/26/2001
+-------------------------------------------------------------------------------
+
+Fixed bugs:
+
+- XAA: clipping rectangle was clipped to visible screen, so offscreen
+ pixmaps could not been drawn at with accelerated drawing functions.
+
+Extensions:
+
+- smi_video: partly rewritten.
+ - Support for 7111
+ - interlaced video via
+ - XF86Config Option "Interlaced" or
+ - attribute XV_INTERLACED
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0.2
+ Alpha Release 1.2.2, 02/14/2001
+-------------------------------------------------------------------------------
+
+Fixed bugs:
+
+- #920 - Color change/flash at 8bpp when switch back to desktop in rotation
+ mode.
+- #932 - System hangs when enabling rotation in 24-bpp.
+- #941 - Overlay disappear in the virtual desktop when move the window.
+- #944 - Mouse pointer doesn't work properly in panning modes under rotation.
+- #950 - Garbage appears on desktop when click the Basic/Metal for the Theme
+ Selector.
+- #983 - Added ZoomOnLCD option.
+- #1058 - Desktop changes color when panning in 24-bpp mode.
+- #1069 - CRT is off after exit X on DSTN 800x600.
+- #1074 - Screen broken occurs in X when enable Rotation on DSTN 800x600.
+
+Known problems:
+
+- When video is playing in panning mode, it is not correctly clipped when you
+ move the panning window.
+- Sound breaks apart in Netscape when moving the window around.
+
+-------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0.2
+ Alpha Release 1.2.1, 01/03/2001
+--------------------------------------------------------------------------------
+
+Fixed bugs:
+
+- Severe corruption in 24-bpp across all chips.
+- Disable hardware cursor on older BIOSes.
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0.2
+ Alpha Release 1.2.0, 12/13/2000
+--------------------------------------------------------------------------------
+
+Fixed bugs:
+
+- When restoring from VESAFB graphics mode, the screen did not update with the
+ UseBIOS switch on.
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0.1
+ Alpha Release 1.1.9, 11/30/2000
+--------------------------------------------------------------------------------
+
+Fixed bugs:
+
+#581 - Need Linux driver to support zooming via ctrl+alt++ & ctrl+alt+-.
+#670 - Screen broken occurs when switch back to the Xwindow during in Rotation
+ mode.
+#671 - Very slow to pop up the Exit menu from X windows during in Rotation mode.
+#672 - It doesn't redraw properly in X windows during in Rotation mode.
+#689 - Screen broken when toggle between terminal and desktop during playing in
+ MPEG.
+#705 - Linux CRT only 800x600 or 1024x768 there is no display.
+#864 - Lockup when video is playing and switching to full-screen command shell.
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0.1
+ Alpha Release 1.1.8, 11/27/2000
+--------------------------------------------------------------------------------
+
+Fixed bugs:
+
+#640 - X windows shift to the right when start X or apply Rotation.
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0.1
+ Alpha Release 1.1.7, 11/17/2000
+--------------------------------------------------------------------------------
+
+Fixed bugs:
+
+#676 - Green color only shown in window when run Xlive in Linux.
+#835 - Screen black after DPMS on.
+
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0.1
+ Alpha Release 1.1.6, 11/03/2000
+--------------------------------------------------------------------------------
+
+Fixed bugs:
+
+#687 - Blue rectangle appears when video is clipped on thr right edge of screen.
+#735 - When resume from sleep, X does not wake up.
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0.1
+ Alpha Release 1.1.5, 10/06/2000
+--------------------------------------------------------------------------------
+
+Fixed bugs:
+
+#578 - Don't check for CRT-only when validating modes.
+#579 - Corrected DPI issue when DDC monitor is not attached.
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0.1
+ Alpha Release 1.1.4, 09/20/2000
+--------------------------------------------------------------------------------
+
+Fixed bugs:
+
+#521 - Screen corruption after return from X Server when vesafb is used.
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0.1
+ Alpha Release 1.1.3, 09/18/2000
+--------------------------------------------------------------------------------
+
+New features:
+
+- Added live video capture.
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0.1
+ Alpha Release 1.1.2, 09/14/2000
+--------------------------------------------------------------------------------
+
+Fixed bugs:
+
+#486 - Video scaling wrong on SM720.
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0.1
+ Alpha Release 1.1.1, 08/23/2000
+--------------------------------------------------------------------------------
+
+New features:
+
+- Added support for overlays.
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0.1
+ Alpha Release 1.1.0, 08/11/2000
+--------------------------------------------------------------------------------
+
+New features:
+
+- Added support for XFree86 4.0.1 server. This implies that support for the 4.0
+ server has gone. Hence the change in the alpha version number from 1.0.x to
+ 1.1.x.
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0
+ Alpha Release 1.0.2, 08/02/2000
+--------------------------------------------------------------------------------
+
+Fixed bugs:
+
+#161, Corruption when moving windows with a wallpaper background.
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0
+ Alpha Release 1.0.1, 07/27/2000
+--------------------------------------------------------------------------------
+
+Fixed bugs:
+
+#160, Mouse pointer sometimes in bad location.
+#258, Temporary corruption starting X.
+
+--------------------------------------------------------------------------------
+ Silicon Motion Driver for XFree86 4.0
+ Alpha Release 1.0.0, 06/05/2000
+--------------------------------------------------------------------------------
+
+This is alpha version 1.0.0 of the Silicon Motion drivers for the XFree86 4.0
+server. See the README file for general information.
+
+This ALPHA version has the following known problems:
+
+- During mode initialization, the screen shows temporary garbage.
+- Image Transfers are disabled in the hardware for now.
+
+This driver has been tested on the LynxEM+ 712 chip under 16-bit mode. Any other
+mode might still show lock-ups and/or garbage. Please report any problems to
+frido@siliconmotion.com.
+
+Header: //Mercury/Projects/archives/XFree86/4.0/Release.txt-arc 1.33 13 Dec 2000 09:52:48 Frido $
+
+$XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/Release.txt,v 1.7 2001/12/20 21:35:37 eich Exp $
diff --git a/man/siliconmotion.man b/man/siliconmotion.man
new file mode 100644
index 0000000..029b40a
--- /dev/null
+++ b/man/siliconmotion.man
@@ -0,0 +1,203 @@
+.\" Header: //Mercury/Projects/archives/XFree86/4.0/siliconmotion.cpp-arc 1.4 29 Nov 2000 14:12:56 Frido $
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/siliconmotion.man,v 1.4 2001/12/20 21:35:38 eich Exp $
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH siliconmotion __drivermansuffix__ __vendorversion__
+.SH NAME
+siliconmotion \- Silicon Motion video driver
+.SH SYNOPSIS
+.B "Section \*qDevice\*q"
+.br
+.BI " Identifier \*q" devname \*q
+.br
+.B " Driver \*qsiliconmotion\*q"
+.br
+\ \ ...
+.br
+\ \ [
+.B "Option"
+"optionname" ["optionvalue"]]
+.br
+.B EndSection
+.SH DESCRIPTION
+.B siliconmotion
+is an XFree86 driver for Silicon Motion based video cards. The driver is fully
+accelerated, and provides support for the following framebuffer depths:
+8, 16, and 24. All
+visual types are supported for depth 8, and TrueColor
+visuals are supported for the other depths.
+.SH SUPPORTED HARDWARE
+The
+.B siliconmotion
+driver supports PCI and AGP video cards based on the following Silicon Motion chips:
+.TP 12
+.B Lynx
+SM910
+.TP 12
+.B LynxE
+SM810
+.TP 12
+.B Lynx3D
+SM820
+.TP 12
+.B LynxEM
+SM710
+.TP 12
+.B LynxEM+
+SM712
+.TP 12
+.B Lynx3DM
+SM720
+.SH CONFIGURATION DETAILS
+Please refer to XF86Config(__filemansuffix__) for general configuration
+details. This section only covers configuration details specific to this
+driver. All options names are case and white space insensitive when
+parsed by the server, for example, "lynxe" and "LynxE" are equivalent.
+.PP
+The driver auto-detects the chipset type, but the following
+.B ChipSet
+names may optionally be specified in the config file
+.B \*qDevice\*q
+section, and will override the auto-detection:
+.PP
+.RS 4
+"lynx", "lynxe", "lynx3d", "lynxem", "lynxem+", "lynx3dm".
+.RE
+
+.PP
+The following Cursor
+.B Options
+are supported:
+.TP
+.BI "Option \*qHWCursor\*q \*q" boolean \*q
+Enable or disable the HW cursor. Default: on.
+.TP
+.BI "Option \*qSWCursor\*q \*q" boolean \*q
+Inverse of "HWCursor". Default: off.
+
+.PP
+The following display
+.B Options
+are supported:
+.TP
+.BI "Option \*qShadowFB\*q \*q" boolean \*q
+Use shadow framebuffer. Default: off.
+.TP
+.BI "Option \*qRotate\*q \*qCW\*q"
+.TP
+.BI "Option \*qRotate\*q \*qCCW\*q"
+Rotate the screen CW - clockwise or CCW - counter clockwise.
+Uses ShadowFB. Default: no rotation.
+.TP
+.BI "Option \*qVideoKey\*q \*q" integer \*q
+Set the video color key. Default: a little off full blue.
+.TP
+.BI "Option \*qByteSwap\*q \*q" boolean \*q
+Turn on byte swapping for capturing using SMI demo board. Default: off.
+.TP
+.BI "Option \*qInterlaced\*q \*q" boolean \*q
+Turn on interlaced video capturing. Default: off.
+.TP
+.BI "Option \*qUseBIOS\*q \*q" boolean \*q
+Use the BIOS to set the modes. This is used for custom panel timings.
+Default: on.
+.TP
+.BI "Option \*qZoomOnLCD\*q \*q" boolean \*q
+Allow changing resolution on LCD (Ctrl-Alt-Plus and Ctrl-Alt-Minus).
+Default: off.
+
+.PP
+The following video memory
+.B Options
+are supported:
+.TP
+.BI "Option \*qset_mclk\*q \*q" integer \*q
+sets the memory clock, where
+.I integer
+is in kHz, and
+.I integer
+<= 100000. Default: probe the memory clock value,
+and use it at server start.
+
+
+.PP
+The following acceleration and graphics engine
+.B Options
+are supported:
+.TP
+.B "Option \*qNoAccel\*q"
+Disable acceleration. Very useful for determining if the
+driver has problems with drawing and acceleration routines. This is the first
+option to try if your server runs but you see graphic corruption on the screen.
+Using it decreases performance, as it uses software emulation for drawing
+operations the video driver can accelerate with hardware.
+Default: acceleration is enabled.
+.TP
+.B "Option \*qfifo_aggressive\*q"
+.TP
+.B "Option \*qfifo_moderate\*q"
+.TP
+.B "Option \*qfifo_conservative\*q"
+alter the settings
+for the threshold at which the pixel FIFO takes over the internal
+memory bus to refill itself. The smaller this threshold, the better
+the acceleration performance of the card. You may try the fastest
+setting
+.RB ( "fifo_aggressive" )
+and move down if you encounter pixel corruption.
+The optimal setting will probably depend on dot-clock and on color
+depth. Note that specifying any of these options will also alter other
+memory settings which may increase performance, so trying
+.B "fifo_conservative"
+will in most cases be a slight benefit (this uses the chip defaults).
+If pixel corruption or transient streaking is observed during drawing
+operations then removing any fifo options is recommended. Default: none.
+
+.PP
+The following PCI bus
+.B Options
+are supported:
+.TP
+.BI "Option \*qpci_burst\*q \*q" boolean \*q
+will enable PCI burst mode. This should work on all but a
+few broken PCI chipsets, and will increase performance. Default: off.
+.TP
+.BI "Option \*qpci_retry\*q \*q" boolean \*q
+will allow the driver to rely on PCI Retry to program the
+ViRGE registers.
+.B "pci_burst"
+must be enabled for this to work.
+This will increase performance, especially for small fills/blits,
+because the driver does not have to poll the ViRGE before sending it
+commands to make sure it is ready. It should work on most
+recent PCI chipsets. Default: off.
+
+.PP
+The following additional
+.B Options
+are supported:
+.TP
+.BI "Option \*qShowCache\*q \*q" boolean \*q
+Enable or disable viewing offscreen cache memory. A
+development debug option. Default: off.
+
+.SH SEE ALSO
+XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__)
+
+.SH SUPPORT
+For assistance with this driver, or XFree86 in general, check the XFree86 web
+site at http://www.xfree86.org. A FAQ is available on the web site at
+http://www.xfree86.org/FAQ/. If you find a problem with XFree86 or have a
+question not answered in the FAQ please use our bug report form available on
+the web site or send mail to XFree86@XFree86.org. When reporting problems
+with the driver send as much detail as possible, including chipset type, a
+server output log, and operating system specifics.
+
+.SH AUTHORS
+Kevin Brosius,
+Matt Grossman,
+Harald Koenig,
+Sebastien Marineau,
+Mark Vojkovich,
+Frido Garritsen,
+Corvin Zahn.
diff --git a/src/regsmi.h b/src/regsmi.h
new file mode 100644
index 0000000..c134bed
--- /dev/null
+++ b/src/regsmi.h
@@ -0,0 +1,207 @@
+/* Header: //Mercury/Projects/archives/XFree86/4.0/regsmi.h-arc 1.11 14 Sep 2000 11:17:30 Frido $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. 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, sublicense, 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 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, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the names of the XFree86 Project and
+Silicon Motion shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from the XFree86 Project and SIlicon Motion.
+*/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/regsmi.h,v 1.2 2002/01/25 21:56:09 tsi Exp $ */
+
+#ifndef _REGSMI_H
+#define _REGSMI_H
+
+#define SMI_LYNX_SERIES(chip) ((chip & 0xF0F0) == 0x0010)
+#define SMI_LYNX3D_SERIES(chip) ((chip & 0xF0F0) == 0x0020)
+#define SMI_LYNXEM_SERIES(chip) ((chip & 0xFFF0) == 0x0710)
+#define SMI_LYNXM_SERIES(chip) ((chip & 0xFF00) == 0x0700)
+
+/* Chip tags */
+#define PCI_SMI_VENDOR_ID PCI_VENDOR_SMI
+#define SMI_UNKNOWN 0
+#define SMI_LYNX PCI_CHIP_SMI910
+#define SMI_LYNXE PCI_CHIP_SMI810
+#define SMI_LYNX3D PCI_CHIP_SMI820
+#define SMI_LYNXEM PCI_CHIP_SMI710
+#define SMI_LYNXEMplus PCI_CHIP_SMI712
+#define SMI_LYNX3DM PCI_CHIP_SMI720
+
+/* I/O Functions */
+static __inline__ CARD8
+VGAIN8_INDEX(SMIPtr pSmi, int indexPort, int dataPort, CARD8 index)
+{
+ if (pSmi->IOBase)
+ {
+ MMIO_OUT8(pSmi->IOBase, indexPort, index);
+ return(MMIO_IN8(pSmi->IOBase, dataPort));
+ }
+ else
+ {
+ outb(pSmi->PIOBase + indexPort, index);
+ return(inb(pSmi->PIOBase + dataPort));
+ }
+}
+
+static __inline__ void
+VGAOUT8_INDEX(SMIPtr pSmi, int indexPort, int dataPort, CARD8 index, CARD8 data)
+{
+ if (pSmi->IOBase)
+ {
+ MMIO_OUT8(pSmi->IOBase, indexPort, index);
+ MMIO_OUT8(pSmi->IOBase, dataPort, data);
+ }
+ else
+ {
+ outb(pSmi->PIOBase + indexPort, index);
+ outb(pSmi->PIOBase + dataPort, data);
+ }
+}
+
+static __inline__ CARD8
+VGAIN8(SMIPtr pSmi, int port)
+{
+ if (pSmi->IOBase)
+ {
+ return(MMIO_IN8(pSmi->IOBase, port));
+ }
+ else
+ {
+ return(inb(pSmi->PIOBase + port));
+ }
+}
+
+static __inline__ void
+VGAOUT8(SMIPtr pSmi, int port, CARD8 data)
+{
+ if (pSmi->IOBase)
+ {
+ MMIO_OUT8(pSmi->IOBase, port, data);
+ }
+ else
+ {
+ outb(pSmi->PIOBase + port, data);
+ }
+}
+
+#define OUT_SEQ(pSmi, index, data) \
+ VGAOUT8_INDEX((pSmi), VGA_SEQ_INDEX, VGA_SEQ_DATA, (index), (data))
+#define IN_SEQ(pSmi, index) \
+ VGAIN8_INDEX((pSmi), VGA_SEQ_INDEX, VGA_SEQ_DATA, (index))
+
+#define WRITE_DPR(pSmi, dpr, data) MMIO_OUT32(pSmi->DPRBase, dpr, data); DEBUG((VERBLEV, "DPR%02X = %08X\n", dpr, data))
+#define READ_DPR(pSmi, dpr) MMIO_IN32(pSmi->DPRBase, dpr)
+#define WRITE_VPR(pSmi, vpr, data) MMIO_OUT32(pSmi->VPRBase, vpr, data); DEBUG((VERBLEV, "VPR%02X = %08X\n", vpr, data))
+#define READ_VPR(pSmi, vpr) MMIO_IN32(pSmi->VPRBase, vpr)
+#define WRITE_CPR(pSmi, cpr, data) MMIO_OUT32(pSmi->CPRBase, cpr, data); DEBUG((VERBLEV, "CPR%02X = %08X\n", cpr, data))
+#define READ_CPR(pSmi, cpr) MMIO_IN32(pSmi->CPRBase, cpr)
+
+/* 2D Engine commands */
+#define SMI_TRANSPARENT_SRC 0x00000100
+#define SMI_TRANSPARENT_DEST 0x00000300
+
+#define SMI_OPAQUE_PXL 0x00000000
+#define SMI_TRANSPARENT_PXL 0x00000400
+
+#define SMI_MONO_PACK_8 0x00001000
+#define SMI_MONO_PACK_16 0x00002000
+#define SMI_MONO_PACK_32 0x00003000
+
+#define SMI_ROP2_SRC 0x00008000
+#define SMI_ROP2_PAT 0x0000C000
+#define SMI_ROP3 0x00000000
+
+#define SMI_BITBLT 0x00000000
+#define SMI_RECT_FILL 0x00010000
+#define SMI_TRAPEZOID_FILL 0x00030000
+#define SMI_SHORT_STROKE 0x00060000
+#define SMI_BRESENHAM_LINE 0x00070000
+#define SMI_HOSTBLT_WRITE 0x00080000
+#define SMI_HOSTBLT_READ 0x00090000
+#define SMI_ROTATE_BLT 0x000B0000
+
+#define SMI_SRC_COLOR 0x00000000
+#define SMI_SRC_MONOCHROME 0x00400000
+
+#define SMI_GRAPHICS_STRETCH 0x00800000
+
+#define SMI_ROTATE_CW 0x01000000
+#define SMI_ROTATE_CCW 0x02000000
+
+#define SMI_MAJOR_X 0x00000000
+#define SMI_MAJOR_Y 0x04000000
+
+#define SMI_LEFT_TO_RIGHT 0x00000000
+#define SMI_RIGHT_TO_LEFT 0x08000000
+
+#define SMI_COLOR_PATTERN 0x40000000
+#define SMI_MONO_PATTERN 0x00000000
+
+#define SMI_QUICK_START 0x10000000
+#define SMI_START_ENGINE 0x80000000
+
+#define MAXLOOP 0x100000 /* timeout value for engine waits */
+
+#define ENGINE_IDLE() \
+ ((VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x16) & 0x08) == 0)
+#define FIFO_EMPTY() \
+ ((VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x16) & 0x10) != 0)
+
+/* Wait until "v" queue entries are free */
+#define WaitQueue(v) \
+ do \
+ { \
+ if (pSmi->NoPCIRetry) \
+ { \
+ int loop = MAXLOOP; mem_barrier(); \
+ while (!FIFO_EMPTY()) \
+ if (loop-- == 0) break; \
+ if (loop <= 0) SMI_GEReset(pScrn, 1, __LINE__, __FILE__); \
+ } \
+ } while (0)
+
+/* Wait until GP is idle */
+#define WaitIdle() \
+ do \
+ { \
+ int loop = MAXLOOP; mem_barrier(); \
+ while (!ENGINE_IDLE()) \
+ if (loop-- == 0) break; \
+ if (loop <= 0) SMI_GEReset(pScrn, 1, __LINE__, __FILE__); \
+ } \
+ while (0)
+
+/* Wait until GP is idle and queue is empty */
+#define WaitIdleEmpty() \
+ do \
+ { \
+ WaitQueue(MAXFIFO); \
+ WaitIdle(); \
+ } \
+ while (0)
+
+#define RGB8_PSEUDO (-1)
+#define RGB16_565 0
+#define RGB16_555 1
+#define RGB32_888 2
+
+#endif /* _REGSMI_H */
diff --git a/src/smi.h b/src/smi.h
new file mode 100644
index 0000000..6fb2ee0
--- /dev/null
+++ b/src/smi.h
@@ -0,0 +1,362 @@
+/* Header: //Mercury/Projects/archives/XFree86/4.0/smi.h-arc 1.51 29 Nov 2000 17:45:16 Frido $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. 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, sublicense, 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 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, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the names of the XFree86 Project and
+Silicon Motion shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from the XFree86 Project and Silicon Motion.
+*/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi.h,v 1.12 2003/01/12 03:55:49 tsi Exp $ */
+
+#ifndef _SMI_H
+#define _SMI_H
+
+#define USE_FB
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "xf86Cursor.h"
+#include "vgaHW.h"
+
+#include "compiler.h"
+
+#include "mipointer.h"
+#include "micmap.h"
+
+#ifdef USE_FB
+#include "fb.h"
+#else
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb16.h"
+#include "cfb24.h"
+#endif
+
+#include "xaa.h"
+#include "xf86cmap.h"
+#include "xf86i2c.h"
+
+#include "xf86int10.h"
+#include "vbe.h"
+
+#ifdef XvExtension
+# include "xf86xv.h"
+# include "Xv.h"
+#endif
+
+/******************************************************************************/
+/* D E F I N I T I O N S */
+/******************************************************************************/
+
+#ifndef SMI_DEBUG
+# define SMI_DEBUG 0
+#endif
+
+#define SMI_USE_IMAGE_WRITES 0
+#define SMI_USE_VIDEO 1
+#define SMI_USE_CAPTURE 1
+
+/******************************************************************************/
+/* S T R U C T U R E S */
+/******************************************************************************/
+
+/* Driver data structure; this should contain all needed info for a mode */
+typedef struct
+{
+ Bool modeInit;
+ CARD16 mode;
+ CARD8 SR17, SR18, SR21, SR31, SR32, SR6A, SR6B, SR81, SRA0;
+ CARD8 CR33, CR33_2, CR3A;
+ CARD8 CR40[14], CR40_2[14];
+ CARD8 CR90[16], CR9F_2;
+ CARD8 CRA0[14];
+ CARD8 smiDACMask, smiDacRegs[256][3];
+ /* CZ 2.11.2001: for gamma correction */
+ CARD8 CCR66;
+ /* end CZ */
+ CARD8 smiFont[8192];
+ CARD32 DPR10, DPR1C, DPR20, DPR24, DPR28, DPR2C, DPR30, DPR3C, DPR40,
+ DPR44;
+ CARD32 VPR00, VPR0C, VPR10;
+ CARD32 CPR00;
+
+} SMIRegRec, *SMIRegPtr;
+
+/* Global PDEV structure. */
+typedef struct
+{
+ /* accel additions */
+ CARD32 AccelCmd; /* Value for DPR0C */
+ CARD32 Stride; /* Stride of frame buffer */
+ CARD32 ScissorsLeft; /* Left/top of current
+ scissors */
+ CARD32 ScissorsRight; /* Right/bottom of current
+ scissors */
+ Bool ClipTurnedOn; /* Clipping was turned on by
+ the previous command */
+ CARD8 SR18Value; /* PDR#521: original SR18
+ value */
+ CARD8 SR21Value; /* PDR#521: original SR21
+ value */
+ SMIRegRec SavedReg; /* console saved mode
+ registers */
+ SMIRegRec ModeReg; /* XServer video state mode
+ registers */
+ xf86CursorInfoPtr CursorInfoRec; /* HW Cursor info */
+
+ Bool ModeStructInit; /* Flag indicating ModeReg has
+ been duped from console
+ state */
+ int vgaCRIndex, vgaCRReg;
+ int width, height; /* Width and height of the
+ screen */
+ int Bpp; /* Bytes per pixel */
+
+ /* XAA */
+ int videoRAMBytes; /* In units as noted, set in
+ PreInit */
+ int videoRAMKBytes; /* In units as noted, set in
+ PreInit */
+ unsigned char * MapBase; /* Base of mapped memory */
+ int MapSize; /* Size of mapped memory */
+ CARD8 * DPRBase; /* Base of DPR registers */
+ CARD8 * VPRBase; /* Base of VPR registers */
+ CARD8 * CPRBase; /* Base of CPR registers */
+ CARD8 * DataPortBase; /* Base of data port */
+ int DataPortSize; /* Size of data port */
+ CARD8 * IOBase; /* Base of MMIO VGA ports */
+ IOADDRESS PIOBase; /* Base of I/O ports */
+ unsigned char * FBBase; /* Base of FB */
+ CARD32 FBOffset; /* Current visual FB starting
+ location */
+ CARD32 FBCursorOffset; /* Cursor storage location */
+ CARD32 FBReserved; /* Reserved memory in frame
+ buffer */
+
+ Bool PrimaryVidMapped; /* Flag indicating if
+ vgaHWMapMem was used
+ successfully for
+ this screen */
+ int dacSpeedBpp; /* Clock value */
+ int minClock; /* Mimimum clock */
+ int maxClock; /* Maximum clock */
+ int MCLK; /* Memory Clock */
+ int GEResetCnt; /* Limit the number of errors
+ printed using a counter */
+
+ Bool pci_burst; /* Enable PCI burst mode for
+ reads? */
+ Bool NoPCIRetry; /* Disable PCI retries */
+ Bool fifo_conservative; /* Adjust fifo for
+ acceleration? */
+ Bool fifo_moderate; /* Adjust fifo for
+ acceleration? */
+ Bool fifo_aggressive; /* Adjust fifo for
+ acceleration? */
+ Bool NoAccel; /* Disable Acceleration */
+ Bool hwcursor; /* hardware cursor enabled */
+ Bool ShowCache; /* Debugging option */
+ Bool useBIOS; /* Use BIOS for mode sets */
+ Bool zoomOnLCD; /* Zoom on LCD */
+
+ CloseScreenProcPtr CloseScreen; /* Pointer used to save wrapped
+ CloseScreen function */
+ XAAInfoRecPtr AccelInfoRec; /* XAA info Rec */
+ pciVideoPtr PciInfo; /* PCI info vars */
+ PCITAG PciTag;
+ int Chipset; /* Chip info, set using PCI
+ above */
+ int ChipRev;
+
+ /* DGA */
+ DGAModePtr DGAModes; /* Pointer to DGA modes */
+ int numDGAModes; /* Number of DGA modes */
+ Bool DGAactive; /* Flag if DGA is active */
+ int DGAViewportStatus;
+
+ /* DPMS */
+ int CurrentDPMS; /* Current DPMS state */
+ unsigned char DPMS_SR20; /* Saved DPMS SR20 register */
+ unsigned char DPMS_SR21; /* Saved DPMS SR21 register */
+ unsigned char DPMS_SR31; /* Saved DPMS SR31 register */
+ unsigned char DPMS_SR34; /* Saved DPMS SR34 register */
+
+ /* Panel information */
+ Bool lcd; /* LCD active, 1=DSTN, 2=TFT */
+ int lcdWidth; /* LCD width */
+ int lcdHeight; /* LCD height */
+
+ I2CBusPtr I2C; /* Pointer into I2C module */
+ xf86Int10InfoPtr pInt10; /* Pointer to INT10 module */
+
+ /* Shadow frame buffer (rotation) */
+ Bool shadowFB; /* Flag if shadow buffer is
+ used */
+ int rotate; /* Rotation flags */
+ int ShadowPitch; /* Pitch of shadow buffer */
+ int ShadowWidthBytes; /* Width of shadow
+ buffer in bytes */
+ int ShadowWidth; /* Width of shadow buffer in
+ pixels */
+ int ShadowHeight; /* Height of shadow buffer in
+ pixels */
+ CARD32 saveBufferSize; /* #670 - FB save buffer size */
+ void * pSaveBuffer; /* #670 - FB save buffer */
+ CARD32 savedFBOffset; /* #670 - Saved FBOffset value */
+ CARD32 savedFBReserved; /* #670 - Saved
+ FBReserved value */
+ CARD8 * paletteBuffer; /* #920 - Palette save buffer */
+
+ /* Polylines - #671 */
+ ValidateGCProcPtr ValidatePolylines; /* Org.
+ ValidatePolylines
+ function */
+ Bool polyLines; /* Our polylines patch is
+ active */
+
+ void (*PointerMoved)(int index, int x, int y);
+
+#ifdef XvExtension
+ int videoKey; /* Video chroma key */
+ Bool ByteSwap; /* Byte swap for ZV port */
+ Bool interlaced; /* True: Interlaced Video */
+ /* XvExtension */
+ XF86VideoAdaptorPtr ptrAdaptor; /* Pointer to VideoAdapter
+ structure */
+ void (*BlockHandler)(int i, pointer blockData, pointer pTimeout,
+ pointer pReadMask);
+ GCPtr videoGC;
+#endif
+ OptionInfoPtr Options;
+ CARD8 DACmask;
+} SMIRec, *SMIPtr;
+
+#define SMIPTR(p) ((SMIPtr)((p)->driverPrivate))
+
+/******************************************************************************/
+/* M A C R O S */
+/******************************************************************************/
+
+#if SMI_DEBUG
+# define VERBLEV 1
+# define ENTER_PROC(PROCNAME) xf86ErrorFVerb(VERBLEV, "ENTER\t" PROCNAME \
+ "(%d)\n", __LINE__); xf86Break1()
+# define DEBUG_PROC(PROCNAME) xf86ErrorFVerb(VERBLEV, "DEBUG\t" PROCNAME \
+ "(%d)\n", __LINE__); xf86Break2()
+# define LEAVE_PROC(PROCNAME) xf86ErrorFVerb(VERBLEV, "LEAVE\t" PROCNAME \
+ "(%d)\n", __LINE__); xf86Break1()
+# define DEBUG(arg) xf86ErrorFVerb arg
+#else
+# define VERBLEV 4
+# define ENTER_PROC(PROCNAME)
+# define DEBUG_PROC(PROCNAME)
+# define LEAVE_PROC(PROCNAME)
+# define DEBUG(arg)
+#endif
+
+/* Some Silicon Motion structs & registers */
+#include "regsmi.h"
+
+#if !defined (MetroLink) && !defined (VertDebug)
+#define VerticalRetraceWait() \
+do \
+{ \
+ if (VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x17) & 0x80) \
+ { \
+ while ((VGAIN8(pSmi, vgaIOBase + 0x0A) & 0x08) == 0x00); \
+ while ((VGAIN8(pSmi, vgaIOBase + 0x0A) & 0x08) == 0x08); \
+ while ((VGAIN8(pSmi, vgaIOBase + 0x0A) & 0x08) == 0x00); \
+ } \
+} while (0)
+#else
+#define SPIN_LIMIT 1000000
+#define VerticalRetraceWait() \
+do \
+{ \
+ if (VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x17) & 0x80) \
+ { \
+ volatile unsigned long _spin_me; \
+ for (_spin_me = SPIN_LIMIT; \
+ ((VGAIN8(pSmi, vgaIOBase + 0x0A) & 0x08) == 0x00) && \
+ _spin_me; \
+ _spin_me--); \
+ if (!_spin_me) \
+ ErrorF("smi: warning: VerticalRetraceWait timed out.\n"); \
+ for (_spin_me = SPIN_LIMIT; \
+ ((VGAIN8(pSmi, vgaIOBase + 0x0A) & 0x08) == 0x08) && \
+ _spin_me; \
+ _spin_me--); \
+ if (!_spin_me) \
+ ErrorF("smi: warning: VerticalRetraceWait timed out.\n"); \
+ for (_spin_me = SPIN_LIMIT; \
+ ((VGAIN8(pSmi, vgaIOBase + 0x0A) & 0x08) == 0x00) && \
+ _spin_me; \
+ _spin_me--); \
+ if (!_spin_me) \
+ ErrorF("smi: warning: VerticalRetraceWait timed out.\n"); \
+ } \
+} while (0)
+#endif
+
+/******************************************************************************/
+/* F U N C T I O N P R O T O T Y P E S */
+/******************************************************************************/
+
+/* smi_dac.c */
+void SMI_CommonCalcClock(int scrnIndex, long freq, int min_m, int min_n1,
+ int max_n1, int min_n2, int max_n2, long freq_min,
+ long freq_max, unsigned char * mdiv,
+ unsigned char * ndiv);
+
+/* smi_i2c */
+Bool SMI_I2CInit(ScrnInfoPtr pScrn);
+
+/* smi_accel.c */
+Bool SMI_AccelInit(ScreenPtr pScrn);
+void SMI_AccelSync(ScrnInfoPtr pScrn);
+void SMI_GEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file);
+void SMI_EngineReset(ScrnInfoPtr);
+
+/* smi_hwcurs.c */
+Bool SMI_HWCursorInit(ScreenPtr pScrn);
+
+/* smi_driver.c */
+void SMI_AdjustFrame(int scrnIndex, int x, int y, int flags);
+Bool SMI_SwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
+
+/* smi_dga.c */
+Bool SMI_DGAInit(ScreenPtr pScrn);
+
+/* smi_shadow.c */
+void SMI_PointerMoved(int index, int x, int y);
+void SMI_RefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+
+/* smi_video.c */
+void SMI_InitVideo(ScreenPtr pScreen);
+
+#endif /*_SMI_H*/
diff --git a/src/smi_accel.c b/src/smi_accel.c
new file mode 100644
index 0000000..1c53060
--- /dev/null
+++ b/src/smi_accel.c
@@ -0,0 +1,1108 @@
+/* Header: //Mercury/Projects/archives/XFree86/4.0/smi_accel.c-arc 1.16 03 Jan 2001 13:29:06 Frido $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. 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, sublicense, 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 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, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the names of the XFree86 Project and
+Silicon Motion shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from the XFree86 Project and silicon Motion.
+*/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_accel.c,v 1.7 2003/01/12 03:55:49 tsi Exp $ */
+
+#include "smi.h"
+
+#include "miline.h"
+#include "xaalocal.h"
+#include "xaarop.h"
+#include "servermd.h"
+
+
+static void SMI_SetupForScreenToScreenCopy(ScrnInfoPtr, int, int, int,
+ unsigned int, int);
+static void SMI_SubsequentScreenToScreenCopy(ScrnInfoPtr, int, int, int, int,
+ int, int);
+static void SMI_SetupForSolidFill(ScrnInfoPtr, int, int, unsigned);
+static void SMI_SubsequentSolidFillRect(ScrnInfoPtr, int, int, int, int);
+static void SMI_SubsequentSolidHorVertLine(ScrnInfoPtr, int, int, int, int);
+static void SMI_SetupForCPUToScreenColorExpandFill(ScrnInfoPtr, int, int, int,
+ unsigned int);
+static void SMI_SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr, int, int, int,
+ int, int);
+static void SMI_SetupForMono8x8PatternFill(ScrnInfoPtr, int, int, int, int, int,
+ unsigned int);
+static void SMI_SubsequentMono8x8PatternFillRect(ScrnInfoPtr, int, int, int,
+ int, int, int);
+static void SMI_SetupForColor8x8PatternFill(ScrnInfoPtr, int, int, int,
+ unsigned int, int);
+static void SMI_SubsequentColor8x8PatternFillRect(ScrnInfoPtr, int, int, int,
+ int, int, int);
+#if SMI_USE_IMAGE_WRITES
+static void SMI_SetupForImageWrite(ScrnInfoPtr, int, unsigned int, int, int,
+ int);
+static void SMI_SubsequentImageWriteRect(ScrnInfoPtr, int, int, int, int, int);
+#endif
+static void SMI_SetClippingRectangle(ScrnInfoPtr, int, int, int, int);
+static void SMI_DisableClipping(ScrnInfoPtr);
+/* #671 */
+static void SMI_ValidatePolylines(GCPtr, unsigned long, DrawablePtr);
+static void SMI_Polylines(DrawablePtr, GCPtr, int, int, DDXPointPtr);
+
+Bool
+SMI_AccelInit(ScreenPtr pScreen)
+{
+ XAAInfoRecPtr infoPtr;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ SMIPtr pSmi = SMIPTR(pScrn);
+ /*BoxRec AvailFBArea;*/
+ Bool ret;
+ /*int numLines, maxLines;*/
+
+ ENTER_PROC("SMI_AccelInit");
+
+ pSmi->AccelInfoRec = infoPtr = XAACreateInfoRec();
+ if (infoPtr == NULL)
+ {
+ LEAVE_PROC("SMI_AccelInit");
+ return FALSE;
+ }
+
+ infoPtr->Flags = PIXMAP_CACHE
+ | LINEAR_FRAMEBUFFER
+ | OFFSCREEN_PIXMAPS;
+
+ infoPtr->Sync = SMI_AccelSync;
+
+ /* Screen to screen copies */
+ infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK
+ | ONLY_TWO_BITBLT_DIRECTIONS;
+ infoPtr->SetupForScreenToScreenCopy = SMI_SetupForScreenToScreenCopy;
+ infoPtr->SubsequentScreenToScreenCopy = SMI_SubsequentScreenToScreenCopy;
+ if (pScrn->bitsPerPixel == 24)
+ {
+ infoPtr->ScreenToScreenCopyFlags |= NO_TRANSPARENCY;
+ }
+ if ((pSmi->Chipset == SMI_LYNX3D) && (pScrn->bitsPerPixel == 8))
+ {
+ infoPtr->ScreenToScreenCopyFlags |= GXCOPY_ONLY;
+ }
+
+ /* Solid Fills */
+ infoPtr->SolidFillFlags = NO_PLANEMASK;
+ infoPtr->SetupForSolidFill = SMI_SetupForSolidFill;
+ infoPtr->SubsequentSolidFillRect = SMI_SubsequentSolidFillRect;
+
+ /* Solid Lines */
+ infoPtr->SolidLineFlags = NO_PLANEMASK;
+ infoPtr->SetupForSolidLine = SMI_SetupForSolidFill;
+ infoPtr->SubsequentSolidHorVertLine = SMI_SubsequentSolidHorVertLine;
+
+ /* Color Expansion Fills */
+ infoPtr->CPUToScreenColorExpandFillFlags = ROP_NEEDS_SOURCE
+ | NO_PLANEMASK
+ | BIT_ORDER_IN_BYTE_MSBFIRST
+ | LEFT_EDGE_CLIPPING
+ | CPU_TRANSFER_PAD_DWORD
+ | SCANLINE_PAD_DWORD;
+ infoPtr->ColorExpandBase = pSmi->DataPortBase;
+ infoPtr->ColorExpandRange = pSmi->DataPortSize;
+ infoPtr->SetupForCPUToScreenColorExpandFill =
+ SMI_SetupForCPUToScreenColorExpandFill;
+ infoPtr->SubsequentCPUToScreenColorExpandFill =
+ SMI_SubsequentCPUToScreenColorExpandFill;
+
+ /* 8x8 Mono Pattern Fills */
+ infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK
+ | HARDWARE_PATTERN_PROGRAMMED_BITS
+ | HARDWARE_PATTERN_SCREEN_ORIGIN
+ | BIT_ORDER_IN_BYTE_MSBFIRST;
+ infoPtr->SetupForMono8x8PatternFill = SMI_SetupForMono8x8PatternFill;
+ infoPtr->SubsequentMono8x8PatternFillRect =
+ SMI_SubsequentMono8x8PatternFillRect;
+
+ /* 8x8 Color Pattern Fills */
+ if (!SMI_LYNX3D_SERIES(pSmi->Chipset) || (pScrn->bitsPerPixel != 24))
+ {
+ infoPtr->Color8x8PatternFillFlags = NO_PLANEMASK
+ | HARDWARE_PATTERN_SCREEN_ORIGIN;
+ infoPtr->SetupForColor8x8PatternFill =
+ SMI_SetupForColor8x8PatternFill;
+ infoPtr->SubsequentColor8x8PatternFillRect =
+ SMI_SubsequentColor8x8PatternFillRect;
+ }
+
+#if SMI_USE_IMAGE_WRITES
+ /* Image Writes */
+ infoPtr->ImageWriteFlags = ROP_NEEDS_SOURCE
+ | NO_PLANEMASK
+ | CPU_TRANSFER_PAD_DWORD
+ | SCANLINE_PAD_DWORD;
+ infoPtr->ImageWriteBase = pSmi->DataPortBase;
+ infoPtr->ImageWriteRange = pSmi->DataPortSize;
+ infoPtr->SetupForImageWrite = SMI_SetupForImageWrite;
+ infoPtr->SubsequentImageWriteRect = SMI_SubsequentImageWriteRect;
+#endif
+
+ /* Clipping */
+ infoPtr->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY
+ | HARDWARE_CLIP_MONO_8x8_FILL
+ | HARDWARE_CLIP_COLOR_8x8_FILL
+ | HARDWARE_CLIP_SOLID_FILL
+ | HARDWARE_CLIP_SOLID_LINE
+ | HARDWARE_CLIP_DASHED_LINE;
+ infoPtr->SetClippingRectangle = SMI_SetClippingRectangle;
+ infoPtr->DisableClipping = SMI_DisableClipping;
+
+ /* Pixmap Cache */
+ if (pScrn->bitsPerPixel == 24)
+ {
+ infoPtr->CachePixelGranularity = 16;
+ }
+ else
+ {
+ infoPtr->CachePixelGranularity = 128 / pScrn->bitsPerPixel;
+ }
+
+ /* Offscreen Pixmaps */
+ infoPtr->maxOffPixWidth = 4096;
+ infoPtr->maxOffPixHeight = 4096;
+ if (pScrn->bitsPerPixel == 24)
+ {
+ infoPtr->maxOffPixWidth = 4096 / 3;
+
+ if (pSmi->Chipset == SMI_LYNX)
+ {
+ infoPtr->maxOffPixHeight = 4096 / 3;
+ }
+ }
+
+ SMI_EngineReset(pScrn);
+
+
+ /* CZ 18.06.2001: moved to smi_driver.c before the NoAccel question
+ to have offscreen framebuffer in NoAccel mode */
+#if 0
+ maxLines = pSmi->FBReserved / (pSmi->width * pSmi->Bpp);
+ if (pSmi->rotate)
+ {
+ numLines = maxLines;
+ }
+ else
+ {
+#if defined(XvExtension) && SMI_USE_VIDEO
+ numLines = ((pSmi->FBReserved - pSmi->width * pSmi->Bpp * pSmi->height)
+ * 25 / 100 + pSmi->width * pSmi->Bpp - 1)
+ / (pSmi->width * pSmi->Bpp);
+ numLines += pSmi->height;
+#else
+ numLines = maxLines;
+#endif
+ }
+
+ AvailFBArea.x1 = 0;
+ AvailFBArea.y1 = 0;
+ AvailFBArea.x2 = pSmi->width;
+ AvailFBArea.y2 = numLines;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FrameBuffer Box: %d,%d - %d,%d\n",
+ AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2, AvailFBArea.y2);
+ xf86InitFBManager(pScreen, &AvailFBArea);
+#endif
+
+ ret = XAAInit(pScreen, infoPtr);
+ if (ret && pSmi->shadowFB) /* #671 */
+ {
+ pSmi->ValidatePolylines = infoPtr->ValidatePolylines;
+ infoPtr->ValidatePolylines = SMI_ValidatePolylines;
+ }
+
+ LEAVE_PROC("SMI_AccelInit");
+ return(ret);
+}
+
+void
+SMI_GEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ CARD8 tmp;
+
+ ENTER_PROC("SMI_GEReset");
+
+ if (from_timeout)
+ {
+ if (pSmi->GEResetCnt++ < 10 || xf86GetVerbosity() > 1)
+ {
+ xf86DrvMsg(pScrn->scrnIndex,X_INFO,"\tSMI_GEReset called from %s line %d\n", file, line);
+ }
+ }
+ else
+ {
+ WaitIdleEmpty();
+ }
+
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x15);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x15, tmp | 0x30);
+
+ WaitIdleEmpty();
+
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x15, tmp);
+ SMI_EngineReset(pScrn);
+
+ LEAVE_PROC("SMI_GEReset");
+}
+
+/* The sync function for the GE */
+void
+SMI_AccelSync(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_AccelSync");
+
+ WaitIdleEmpty(); /* #161 */
+
+ LEAVE_PROC("SMI_AccelSync");
+}
+
+void
+SMI_EngineReset(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ CARD32 DEDataFormat = 0;
+ int i;
+ int xyAddress[] = { 320, 400, 512, 640, 800, 1024, 1280, 1600, 2048 };
+
+ ENTER_PROC("SMI_EngineReset");
+
+ pSmi->Stride = (pSmi->width * pSmi->Bpp + 15) & ~15;
+
+ switch (pScrn->bitsPerPixel)
+ {
+ case 8:
+ DEDataFormat = 0x00000000;
+ break;
+
+ case 16:
+ pSmi->Stride >>= 1;
+ DEDataFormat = 0x00100000;
+ break;
+
+ case 24:
+ DEDataFormat = 0x00300000;
+ break;
+
+ case 32:
+ pSmi->Stride >>= 2;
+ DEDataFormat = 0x00200000;
+ break;
+ }
+ for (i = 0; i < sizeof(xyAddress) / sizeof(xyAddress[0]); i++)
+ {
+ if (pSmi->rotate)
+ {
+ if (xyAddress[i] == pSmi->height)
+ {
+ DEDataFormat |= i << 16;
+ break;
+ }
+ }
+ else
+ {
+ if (xyAddress[i] == pSmi->width)
+ {
+ DEDataFormat |= i << 16;
+ break;
+ }
+ }
+ }
+
+ WaitIdleEmpty();
+ WRITE_DPR(pSmi, 0x10, (pSmi->Stride << 16) | pSmi->Stride);
+ WRITE_DPR(pSmi, 0x1C, DEDataFormat);
+ WRITE_DPR(pSmi, 0x24, 0xFFFFFFFF);
+ WRITE_DPR(pSmi, 0x28, 0xFFFFFFFF);
+ WRITE_DPR(pSmi, 0x3C, (pSmi->Stride << 16) | pSmi->Stride);
+ WRITE_DPR(pSmi, 0x40, 0);
+ WRITE_DPR(pSmi, 0x44, 0);
+
+ SMI_DisableClipping(pScrn);
+
+ LEAVE_PROC("SMI_EngineReset");
+}
+
+/******************************************************************************/
+/* Screen to Screen Copies */
+/******************************************************************************/
+
+static void
+SMI_SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
+ unsigned int planemask, int trans)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SetupForScreenToScreenCopy");
+ DEBUG((VERBLEV, "xdir=%d ydir=%d rop=%02X trans=%08X\n", xdir, ydir,
+ rop, trans));
+
+ pSmi->AccelCmd = XAACopyROP[rop]
+ | SMI_BITBLT
+ | SMI_START_ENGINE;
+
+ if ((xdir == -1) || (ydir == -1))
+ {
+ pSmi->AccelCmd |= SMI_RIGHT_TO_LEFT;
+ }
+
+ if (trans != -1)
+ {
+ pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL;
+ WaitQueue(1);
+ WRITE_DPR(pSmi, 0x20, trans);
+ }
+
+ if (pSmi->ClipTurnedOn)
+ {
+ WaitQueue(1);
+ WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
+ pSmi->ClipTurnedOn = FALSE;
+ }
+
+ LEAVE_PROC("SMI_SetupForScreenToScreenCopy");
+}
+
+static void
+SMI_SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2,
+ int y2, int w, int h)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SubsequentScreenToScreenCopy");
+ DEBUG((VERBLEV, "x1=%d y1=%d x2=%d y2=%d w=%d h=%d\n", x1, y1, x2, y2, w,
+ h));
+
+ if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT)
+ {
+ x1 += w - 1;
+ y1 += h - 1;
+ x2 += w - 1;
+ y2 += h - 1;
+ }
+
+ if (pScrn->bitsPerPixel == 24)
+ {
+ x1 *= 3;
+ x2 *= 3;
+ w *= 3;
+
+ if (pSmi->Chipset == SMI_LYNX)
+ {
+ y1 *= 3;
+ y2 *= 3;
+ }
+
+ if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT)
+ {
+ x1 += 2;
+ x2 += 2;
+ }
+ }
+
+ WaitQueue(4);
+ WRITE_DPR(pSmi, 0x00, (x1 << 16) + (y1 & 0xFFFF));
+ WRITE_DPR(pSmi, 0x04, (x2 << 16) + (y2 & 0xFFFF));
+ WRITE_DPR(pSmi, 0x08, (w << 16) + (h & 0xFFFF));
+ WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
+
+ LEAVE_PROC("SMI_SubsequentScreenToScreenCopy");
+}
+
+/******************************************************************************/
+/* Solid Fills */
+/******************************************************************************/
+
+static void
+SMI_SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SetupForSolidFill");
+ DEBUG((VERBLEV, "color=%08X rop=%02X\n", color, rop));
+
+ pSmi->AccelCmd = XAAPatternROP[rop]
+ | SMI_BITBLT
+ | SMI_START_ENGINE;
+
+ if (pSmi->ClipTurnedOn)
+ {
+ WaitQueue(4);
+ WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
+ pSmi->ClipTurnedOn = FALSE;
+ }
+ else
+ {
+ WaitQueue(3);
+ }
+ WRITE_DPR(pSmi, 0x14, color);
+ WRITE_DPR(pSmi, 0x34, 0xFFFFFFFF);
+ WRITE_DPR(pSmi, 0x38, 0xFFFFFFFF);
+
+ LEAVE_PROC("SMI_SetupForSolidFill");
+}
+
+void
+SMI_SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SubsequentSolidFillRect");
+ DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h));
+
+ if (pScrn->bitsPerPixel == 24)
+ {
+ x *= 3;
+ w *= 3;
+
+ if (pSmi->Chipset == SMI_LYNX)
+ {
+ y *= 3;
+ }
+ }
+
+ WaitQueue(3);
+ WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
+ WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
+ WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
+
+ LEAVE_PROC("SMI_SubsequentSolidFillRect");
+}
+
+/******************************************************************************/
+/* Solid Lines */
+/******************************************************************************/
+
+static void
+SMI_SubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len,
+ int dir)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ int w, h;
+
+ ENTER_PROC("SMI_SubsequentSolidHorVertLine");
+ DEBUG((VERBLEV, "x=%d y=%d len=%d dir=%d\n", x, y, len, dir));
+
+ if (dir == DEGREES_0)
+ {
+ w = len;
+ h = 1;
+ }
+ else
+ {
+ w = 1;
+ h = len;
+ }
+
+ if (pScrn->bitsPerPixel == 24)
+ {
+ x *= 3;
+ w *= 3;
+
+ if (pSmi->Chipset == SMI_LYNX)
+ {
+ y *= 3;
+ }
+ }
+
+ WaitQueue(3);
+ WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
+ WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
+ WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
+
+ LEAVE_PROC("SMI_SubsequentSolidHorVertLine");
+}
+
+/******************************************************************************/
+/* Color Expansion Fills */
+/******************************************************************************/
+
+static void
+SMI_SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg,
+ int rop, unsigned int planemask)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SetupForCPUToScreenColorExpandFill");
+ DEBUG((VERBLEV, "fg=%08X bg=%08X rop=%02X\n", fg, bg, rop));
+
+ pSmi->AccelCmd = XAACopyROP[rop]
+ | SMI_HOSTBLT_WRITE
+ | SMI_SRC_MONOCHROME
+ | SMI_START_ENGINE;
+
+ if (bg == -1)
+ {
+ pSmi->AccelCmd |= SMI_TRANSPARENT_SRC;
+
+ WaitQueue(3);
+ WRITE_DPR(pSmi, 0x14, fg);
+ WRITE_DPR(pSmi, 0x18, ~fg);
+ WRITE_DPR(pSmi, 0x20, fg);
+ }
+ else
+ {
+ WaitQueue(2);
+ WRITE_DPR(pSmi, 0x14, fg);
+ WRITE_DPR(pSmi, 0x18, bg);
+ }
+
+ LEAVE_PROC("SMI_SetupForCPUToScreenColorExpandFill");
+}
+
+void
+SMI_SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y, int w,
+ int h, int skipleft)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SubsequentCPUToScreenColorExpandFill");
+ DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d skipleft=%d\n", x, y, w, h, skipleft));
+
+ if (pScrn->bitsPerPixel == 24)
+ {
+ x *= 3;
+ w *= 3;
+ skipleft *= 3;
+
+ if (pSmi->Chipset == SMI_LYNX)
+ {
+ y *= 3;
+ }
+ }
+
+ if (skipleft)
+ {
+ WaitQueue(5);
+ WRITE_DPR(pSmi, 0x2C, (pSmi->ScissorsLeft & 0xFFFF0000)
+ | (x + skipleft) | 0x2000);
+ pSmi->ClipTurnedOn = TRUE;
+ }
+ else
+ {
+ if (pSmi->ClipTurnedOn)
+ {
+ WaitQueue(5);
+ WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
+ pSmi->ClipTurnedOn = FALSE;
+ }
+ else
+ {
+ WaitQueue(4);
+ }
+ }
+ WRITE_DPR(pSmi, 0x00, 0);
+ WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
+ WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
+ WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
+
+ LEAVE_PROC("SMI_SubsequentCPUToScreenColorExpandFill");
+}
+
+/******************************************************************************/
+/* 8x8 Mono Pattern Fills */
+/******************************************************************************/
+
+static void
+SMI_SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, int fg,
+ int bg, int rop, unsigned int planemask)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SetupForMono8x8PatternFill");
+ DEBUG((VERBLEV, "patx=%08X paty=%08X fg=%08X bg=%08X rop=%02X\n", patx,
+ paty, fg, bg, rop));
+
+ pSmi->AccelCmd = XAAPatternROP[rop]
+ | SMI_BITBLT
+ | SMI_START_ENGINE;
+
+ if (pSmi->ClipTurnedOn)
+ {
+ WaitQueue(1);
+ WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
+ pSmi->ClipTurnedOn = FALSE;
+ }
+
+ if (bg == -1)
+ {
+ WaitQueue(5);
+ WRITE_DPR(pSmi, 0x14, fg);
+ WRITE_DPR(pSmi, 0x18, ~fg);
+ WRITE_DPR(pSmi, 0x20, fg);
+ WRITE_DPR(pSmi, 0x34, patx);
+ WRITE_DPR(pSmi, 0x38, paty);
+ }
+ else
+ {
+ WaitQueue(4);
+ WRITE_DPR(pSmi, 0x14, fg);
+ WRITE_DPR(pSmi, 0x18, bg);
+ WRITE_DPR(pSmi, 0x34, patx);
+ WRITE_DPR(pSmi, 0x38, paty);
+ }
+
+ LEAVE_PROC("SMI_SetupForMono8x8PatternFill");
+}
+
+static void
+SMI_SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty,
+ int x, int y, int w, int h)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SubsequentMono8x8PatternFillRect");
+ DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h));
+
+ if (pScrn->bitsPerPixel == 24)
+ {
+ x *= 3;
+ w *= 3;
+ if (pSmi->Chipset == SMI_LYNX)
+ {
+ y *= 3;
+ }
+ }
+
+ WaitQueue(3);
+ WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
+ WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
+ WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
+
+ LEAVE_PROC("SMI_SubsequentMono8x8PatternFillRect");
+}
+
+/******************************************************************************/
+/* 8x8 Color Pattern Fills */
+/******************************************************************************/
+
+static void
+SMI_SetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, int rop,
+ unsigned int planemask, int trans_color)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SetupForColor8x8PatternFill");
+ DEBUG((VERBLEV, "patx=%d paty=%d rop=%02X trans_color=%08X\n", patx, paty,
+ rop, trans_color));
+
+ pSmi->AccelCmd = XAAPatternROP[rop]
+ | SMI_BITBLT
+ | SMI_COLOR_PATTERN
+ | SMI_START_ENGINE;
+
+ if (pScrn->bitsPerPixel <= 16)
+ {
+ /* PDR#950 */
+ CARD8* pattern = pSmi->FBBase
+ + (patx + paty * pSmi->Stride) * pSmi->Bpp;
+
+ WaitIdleEmpty();
+ WRITE_DPR(pSmi, 0x0C, SMI_BITBLT | SMI_COLOR_PATTERN);
+ memcpy(pSmi->DataPortBase, pattern, 8 * pSmi->Bpp * 8);
+ }
+ else
+ {
+ if (pScrn->bitsPerPixel == 24)
+ {
+ patx *= 3;
+
+ if (pSmi->Chipset == SMI_LYNX)
+ {
+ paty *= 3;
+ }
+ }
+
+ WaitQueue(1);
+ WRITE_DPR(pSmi, 0x00, (patx << 16) | (paty & 0xFFFF));
+ }
+
+ if (trans_color == -1)
+ {
+ pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL;
+
+ WaitQueue(1);
+ WRITE_DPR(pSmi, 0x20, trans_color);
+ }
+
+ if (pSmi->ClipTurnedOn)
+ {
+ WaitQueue(1);
+ WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
+ pSmi->ClipTurnedOn = FALSE;
+ }
+
+ LEAVE_PROC("SMI_SetupForColor8x8PatternFill");
+}
+
+static void
+SMI_SubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty,
+ int x, int y, int w, int h)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SubsequentColor8x8PatternFillRect");
+ DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h));
+
+ if (pScrn->bitsPerPixel == 24)
+ {
+ x *= 3;
+ w *= 3;
+
+ if (pSmi->Chipset == SMI_LYNX)
+ {
+ y *= 3;
+ }
+ }
+
+ WaitQueue(3);
+ WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
+ WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF)); /* PDR#950 */
+ WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
+
+ LEAVE_PROC("SMI_SubsequentColor8x8PatternFillRect");
+}
+
+#if SMI_USE_IMAGE_WRITES
+/******************************************************************************/
+/* Image Writes */
+/******************************************************************************/
+
+static void
+SMI_SetupForImageWrite(ScrnInfoPtr pScrn, int rop, unsigned int planemask,
+ int trans_color, int bpp, int depth)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SetupForImageWrite");
+ DEBUG((VERBLEV, "rop=%02X trans_color=%08X bpp=%d depth=%d\n", rop,
+ trans_color, bpp, depth));
+
+ pSmi->AccelCmd = XAACopyROP[rop]
+ | SMI_HOSTBLT_WRITE
+ | SMI_START_ENGINE;
+
+ if (trans_color != -1)
+ {
+ pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL;
+
+ WaitQueue(1);
+ WRITE_DPR(pSmi, 0x20, trans_color);
+ }
+
+ LEAVE_PROC("SMI_SetupForImageWrite");
+}
+
+static void
+SMI_SubsequentImageWriteRect(ScrnInfoPtr pScrn, int x, int y, int w, int h,
+ int skipleft)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SubsequentImageWriteRect");
+ DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d skipleft=%d\n", x, y, w, h, skipleft));
+
+ if (pScrn->bitsPerPixel == 24)
+ {
+ x *= 3;
+ w *= 3;
+ skipleft *= 3;
+
+ if (pSmi->Chipset == SMI_LYNX)
+ {
+ y *= 3;
+ }
+ }
+
+ if (skipleft)
+ {
+ WaitQueue(5);
+ WRITE_DPR(pSmi, 0x2C, (pSmi->ScissorsLeft & 0xFFFF0000) |
+ (x + skipleft) | 0x2000);
+ pSmi->ClipTurnedOn = TRUE;
+ }
+ else
+ {
+ if (pSmi->ClipTurnedOn)
+ {
+ WaitQueue(5);
+ WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
+ pSmi->ClipTurnedOn = FALSE;
+ }
+ else
+ {
+ WaitQueue(4);
+ }
+ }
+ WRITE_DPR(pSmi, 0x00, 0);
+ WRITE_DPR(pSmi, 0x04, (x << 16) | (y * 0xFFFF));
+ WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
+ WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
+
+ LEAVE_PROC("SMI_SubsequentImageWriteRect");
+}
+#endif
+
+/******************************************************************************/
+/* Clipping */
+/******************************************************************************/
+
+static void
+SMI_SetClippingRectangle(ScrnInfoPtr pScrn, int left, int top, int right,
+ int bottom)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SetClippingRectangle");
+ DEBUG((VERBLEV, "left=%d top=%d right=%d bottom=%d\n", left, top, right,
+ bottom));
+
+ /* CZ 26.10.2001: this code prevents offscreen pixmaps being drawn ???
+ left = max(left, 0);
+ top = max(top, 0);
+ right = min(right, pSmi->width);
+ bottom = min(bottom, pSmi->height);
+ */
+
+ if (pScrn->bitsPerPixel == 24)
+ {
+ left *= 3;
+ right *= 3;
+
+ if (pSmi->Chipset == SMI_LYNX)
+ {
+ top *= 3;
+ bottom *= 3;
+ }
+ }
+
+ pSmi->ScissorsLeft = (top << 16) | (left & 0xFFFF) | 0x2000;
+ pSmi->ScissorsRight = (bottom << 16) | (right & 0xFFFF);
+
+ pSmi->ClipTurnedOn = FALSE;
+
+ WaitQueue(2);
+ WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
+ WRITE_DPR(pSmi, 0x30, pSmi->ScissorsRight);
+
+ LEAVE_PROC("SMI_SetClippingRectangle");
+}
+
+static void
+SMI_DisableClipping(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_DisableClipping");
+
+ pSmi->ScissorsLeft = 0;
+ if (pScrn->bitsPerPixel == 24)
+ {
+ if (pSmi->Chipset == SMI_LYNX)
+ {
+ pSmi->ScissorsRight = ((pSmi->height * 3) << 16)
+ | (pSmi->width * 3);
+ }
+ else
+ {
+ pSmi->ScissorsRight = (pSmi->height << 16) | (pSmi->width * 3);
+ }
+ }
+ else
+ {
+ pSmi->ScissorsRight = (pSmi->height << 16) | pSmi->width;
+ }
+
+ pSmi->ClipTurnedOn = FALSE;
+
+ WaitQueue(2);
+ WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
+ WRITE_DPR(pSmi, 0x30, pSmi->ScissorsRight);
+
+ LEAVE_PROC("SMI_DisableClipping");
+}
+
+/******************************************************************************/
+/* Polylines #671 */
+/******************************************************************************/
+
+/*
+
+In order to speed up the "logout" screen in rotated modes, we need to intercept
+the Polylines function. Normally, the polylines are drawn and the shadowFB is
+then sending a request of the bounding rectangle of those poylines. This should
+be okay, if it weren't for the fact that the Gnome logout screen is drawing
+polylines in rectangles and this asks for a rotation of the entire rectangle.
+This is very slow.
+
+To circumvent this slowness, we intercept the ValidatePolylines function and
+override the default "Fallback" Polylines with our own Polylines function. Our
+Polylines function first draws the polylines through the original Fallback
+function and then rotates the lines, line by line. We then set a flag and
+return control to the shadowFB which will try to rotate the bounding rectangle.
+However, the flag has been set and the RefreshArea function does nothing but
+clear the flag so the next Refresh that comes in shoiuld be handled correctly.
+
+All this code improves the speed quite a bit.
+
+*/
+
+#define IS_VISIBLE(pWin) \
+( \
+ pScrn->vtSema \
+ && (((WindowPtr) pWin)->visibility != VisibilityFullyObscured) \
+)
+
+#define TRIM_BOX(box, pGC) \
+{ \
+ BoxPtr extents = &pGC->pCompositeClip->extents; \
+ if (box.x1 < extents->x1) box.x1 = extents->x1; \
+ if (box.y1 < extents->y1) box.y1 = extents->y1; \
+ if (box.x2 > extents->x2) box.x2 = extents->x2; \
+ if (box.y2 > extents->y2) box.y2 = extents->y2; \
+}
+
+#define TRANSLATE_BOX(box, pDraw) \
+{ \
+ box.x1 += pDraw->x; \
+ box.y1 += pDraw->y; \
+ box.x2 += pDraw->x; \
+ box.y2 += pDraw->y; \
+}
+
+#define BOX_NOT_EMPTY(box) \
+ ((box.x2 > box.x1) && (box.y2 > box.y1))
+
+static void
+SMI_ValidatePolylines(GCPtr pGC, unsigned long changes, DrawablePtr pDraw)
+{
+ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
+ SMIPtr pSmi = SMIPTR(infoRec->pScrn);
+
+ ENTER_PROC("SMI_ValidatePolylines");
+
+ pSmi->ValidatePolylines(pGC, changes, pDraw);
+ if (pGC->ops->Polylines == XAAFallbackOps.Polylines)
+ {
+ /* Override the Polylines function with our own Polylines function. */
+ pGC->ops->Polylines = SMI_Polylines;
+ }
+
+ LEAVE_PROC("SMI_ValidatePolylines");
+}
+
+static void
+SMI_Polylines(DrawablePtr pDraw, GCPtr pGC, int mode, int npt,
+ DDXPointPtr pptInit)
+{
+ XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
+ ScrnInfoPtr pScrn = infoRec->pScrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_Polylines");
+
+ /* Call the original Polylines function. */
+ pGC->ops->Polylines = XAAFallbackOps.Polylines;
+ (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit);
+ pGC->ops->Polylines = SMI_Polylines;
+
+ if (IS_VISIBLE(pDraw) && npt)
+ {
+ /* Allocate a temporary buffer for all segments of the polyline. */
+ BoxPtr pBox = xnfcalloc(sizeof(BoxRec), npt);
+ int extra = pGC->lineWidth >> 1, box;
+
+ if (npt > 1)
+ {
+ /* Adjust the extra space required per polyline segment. */
+ if (pGC->joinStyle == JoinMiter)
+ {
+ extra = 6 * pGC->lineWidth;
+ }
+ else if (pGC->capStyle == CapProjecting)
+ {
+ extra = pGC->lineWidth;
+ }
+ }
+
+ for (box = 0; --npt;)
+ {
+ /* Setup the bounding box for one polyline segment. */
+ pBox[box].x1 = pptInit->x;
+ pBox[box].y1 = pptInit->y;
+ pptInit++;
+ pBox[box].x2 = pptInit->x;
+ pBox[box].y2 = pptInit->y;
+ if (mode == CoordModePrevious)
+ {
+ pBox[box].x2 += pBox[box].x1;
+ pBox[box].y2 += pBox[box].y1;
+ }
+
+ /* Sort coordinates. */
+ if (pBox[box].x1 > pBox[box].x2)
+ {
+ int tmp = pBox[box].x1;
+ pBox[box].x1 = pBox[box].x2;
+ pBox[box].x2 = tmp;
+ }
+ if (pBox[box].y1 > pBox[box].y2)
+ {
+ int tmp = pBox[box].y1;
+ pBox[box].y1 = pBox[box].y2;
+ pBox[box].y2 = tmp;
+ }
+
+ /* Add extra space required for each polyline segment. */
+ pBox[box].x1 -= extra;
+ pBox[box].y1 -= extra;
+ pBox[box].x2 += extra + 1;
+ pBox[box].y2 += extra + 1;
+
+ /* See if we need to draw this polyline segment. */
+ TRANSLATE_BOX(pBox[box], pDraw);
+ TRIM_BOX(pBox[box], pGC);
+ if (BOX_NOT_EMPTY(pBox[box]))
+ {
+ box++;
+ }
+ }
+
+ if (box)
+ {
+ /* Refresh all polyline segments now. */
+ SMI_RefreshArea(pScrn, box, pBox);
+ }
+
+ /* Free the temporary buffer. */
+ xfree(pBox);
+ }
+
+ pSmi->polyLines = TRUE;
+ LEAVE_PROC("SMI_Polylines");
+}
diff --git a/src/smi_dac.c b/src/smi_dac.c
new file mode 100644
index 0000000..627b892
--- /dev/null
+++ b/src/smi_dac.c
@@ -0,0 +1,99 @@
+/* Header: //Mercury/Projects/archives/XFree86/4.0/smi_dac.c-arc 1.8 27 Nov 2000 15:47:08 Frido $ */
+
+/*
+Copyright (C) 1994-1998 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. 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, sublicense, 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 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, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the names of the XFree86 Project and
+Silicon Motion shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from the XFree86 Project and Silicon Motion.
+*/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_dac.c,v 1.2 2001/11/30 12:11:59 eich Exp $ */
+
+#include "smi.h"
+
+#define BASE_FREQ 14.31818 /* MHz */
+
+void
+SMI_CommonCalcClock(int scrnIndex, long freq, int min_m, int min_n1,
+ int max_n1, int min_n2, int max_n2, long freq_min,
+ long freq_max, unsigned char *mdiv, unsigned char *ndiv)
+{
+ double div, diff, best_diff;
+ unsigned int m;
+ unsigned char n1, n2;
+ unsigned char best_n1 = 63, best_n2 = 3, best_m = 255;
+
+ double ffreq = freq / 1000.0 / BASE_FREQ;
+ double ffreq_min = freq_min / 1000.0 / BASE_FREQ;
+ double ffreq_max = freq_max / 1000.0 / BASE_FREQ;
+
+ if (ffreq < ffreq_min / (1 << max_n2))
+ {
+ xf86DrvMsg(scrnIndex,X_WARNING,"invalid frequency %1.3f MHz [freq >= %1.3f MHz]\n",
+ ffreq * BASE_FREQ, ffreq_min * BASE_FREQ / (1 << max_n2));
+ ffreq = ffreq_min / (1 << max_n2);
+ }
+ if (ffreq > ffreq_max / (1 << min_n2))
+ {
+ xf86DrvMsg(scrnIndex,X_WARNING,"invalid frequency %1.3f MHz [freq <= %1.3f MHz]\n",
+ ffreq * BASE_FREQ, ffreq_max * BASE_FREQ / (1 << min_n2));
+ ffreq = ffreq_max / (1 << min_n2);
+ }
+
+ /* work out suitable timings */
+ best_diff = ffreq;
+
+ for (n2 = min_n2; n2 <= max_n2; n2++)
+ {
+ for (n1 = min_n1; n1 <= max_n1; n1++)
+ {
+ m = (int)(ffreq * n1 * (1 << n2) + 0.5);
+ if ( (m < min_m) || (m > 255) )
+ {
+ continue;
+ }
+ div = (double)(m) / (double)(n1);
+ if ( (div >= ffreq_min) && (div <= ffreq_max) )
+ {
+ diff = ffreq - div / (1 << n2);
+ if (diff < 0.0)
+ {
+ diff = -diff;
+ }
+ if (diff < best_diff)
+ {
+ best_diff = diff;
+ best_m = m;
+ best_n1 = n1;
+ best_n2 = n2;
+ }
+ }
+ }
+ }
+
+ DEBUG((VERBLEV, "Clock parameters for %1.6f MHz: m=%d, n1=%d, n2=%d\n",
+ ((double)(best_m) / (double)(best_n1) / (1 << best_n2)) * BASE_FREQ,
+ best_m, best_n1, best_n2));
+
+ *ndiv = best_n1 | (best_n2 << 6);
+ *mdiv = best_m;
+}
diff --git a/src/smi_dga.c b/src/smi_dga.c
new file mode 100644
index 0000000..9f090b9
--- /dev/null
+++ b/src/smi_dga.c
@@ -0,0 +1,301 @@
+/* Header: //Mercury/Projects/archives/XFree86/4.0/smi_dga.c-arc 1.5 27 Nov 2000 15:47:18 Frido $ */
+
+/*
+Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. 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, sublicense, 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 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, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the names of the XFree86 Project and
+Silicon Motion shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from the XFree86 Project and Silicon Motion.
+*/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_dga.c,v 1.2 2001/02/15 18:20:33 dawes Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+#include "xaa.h"
+#include "xaalocal.h"
+
+#include "smi.h"
+#include "dgaproc.h"
+
+static Bool SMI_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, int *,
+ int *, int *);
+static Bool SMI_SetMode(ScrnInfoPtr, DGAModePtr);
+static int SMI_GetViewport(ScrnInfoPtr);
+static void SMI_SetViewport(ScrnInfoPtr, int, int, int);
+static void SMI_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
+static void SMI_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
+static void SMI_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
+ unsigned long);
+
+static
+DGAFunctionRec SMI_DGAFuncs =
+{
+ SMI_OpenFramebuffer,
+ NULL,
+ SMI_SetMode,
+ SMI_SetViewport,
+ SMI_GetViewport,
+ SMI_AccelSync,
+ SMI_FillRect,
+ SMI_BlitRect,
+ SMI_BlitTransRect
+};
+
+Bool
+SMI_DGAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ SMIPtr pSmi = SMIPTR(pScrn);
+ DGAModePtr modes = NULL, newmodes = NULL, currentMode;
+ DisplayModePtr pMode, firstMode;
+ int Bpp = pScrn->bitsPerPixel >> 3;
+ int num = 0;
+ Bool ret;
+
+ ENTER_PROC("SMI_DGAInit");
+
+ pMode = firstMode = pScrn->modes;
+
+ while (pMode)
+ {
+ newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec));
+ if (newmodes == NULL)
+ {
+ xfree(modes);
+ LEAVE_PROC("SMI_DGAInit");
+ return(FALSE);
+ }
+
+ modes = newmodes;
+
+ currentMode = modes + num;
+ num++;
+
+ currentMode->mode = pMode;
+ currentMode->flags = DGA_PIXMAP_AVAILABLE;
+ if (!pSmi->NoAccel)
+ {
+ currentMode->flags |= DGA_FILL_RECT
+ | DGA_BLIT_RECT
+ | 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 = pScrn->depth;
+ currentMode->bitsPerPixel = pScrn->bitsPerPixel;
+ currentMode->red_mask = pScrn->mask.red;
+ currentMode->green_mask = pScrn->mask.green;
+ currentMode->blue_mask = pScrn->mask.blue;
+ currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
+ currentMode->viewportWidth = pMode->HDisplay;
+ currentMode->viewportHeight = pMode->VDisplay;
+ currentMode->xViewportStep = (Bpp == 3) ? 8 : (8 / Bpp);
+ currentMode->yViewportStep = 1;
+ currentMode->viewportFlags = DGA_FLIP_RETRACE;
+ currentMode->offset = 0;
+ currentMode->address = pSmi->FBBase;
+
+ xf86ErrorFVerb(VERBLEV, "\tSMI_DGAInit %dx%d @ %d bpp\n",
+ currentMode->viewportWidth, currentMode->viewportHeight,
+ currentMode->bitsPerPixel);
+
+ currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 15)
+ & ~15L;
+ currentMode->imageWidth = pScrn->displayWidth;
+ currentMode->imageHeight = pSmi->FBReserved
+ / currentMode->bytesPerScanline;
+ currentMode->pixmapWidth = currentMode->imageWidth;
+ currentMode->pixmapHeight = currentMode->imageHeight;
+ currentMode->maxViewportX = currentMode->imageWidth
+ - currentMode->viewportWidth;
+ currentMode->maxViewportY = currentMode->imageHeight
+ - currentMode->viewportHeight;
+
+ pMode = pMode->next;
+ if (pMode == firstMode)
+ {
+ break;
+ }
+ }
+
+ pSmi->numDGAModes = num;
+ pSmi->DGAModes = modes;
+
+ ret = DGAInit(pScreen, &SMI_DGAFuncs, modes, num);
+ LEAVE_PROC("SMI_DGAInit");
+ return(ret);
+}
+
+static Bool
+SMI_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
+{
+ static int OldDisplayWidth[MAXSCREENS];
+ int index = pScrn->pScreen->myNum;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SetMode");
+
+ if (pMode == NULL)
+ { /* restore the original mode */
+
+ /* put the ScreenParameters back */
+ pScrn->displayWidth = OldDisplayWidth[index];
+
+ SMI_SwitchMode(index, pScrn->currentMode, 0);
+ pSmi->DGAactive = FALSE;
+ }
+ else
+ {
+ if (!pSmi->DGAactive)
+ { /* save the old parameters */
+ OldDisplayWidth[index] = pScrn->displayWidth;
+
+ pSmi->DGAactive = TRUE;
+ }
+
+ pScrn->displayWidth = pMode->bytesPerScanline
+ / (pMode->bitsPerPixel >> 3);
+
+ SMI_SwitchMode(index, pMode->mode, 0);
+ }
+
+ LEAVE_PROC("SMI_SetMode");
+ return(TRUE);
+}
+
+
+static int
+SMI_GetViewport(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_GetViewport");
+
+ LEAVE_PROC("SMI_GetViewport");
+
+ return(pSmi->DGAViewportStatus);
+}
+
+static void
+SMI_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SetViewport");
+
+ SMI_AdjustFrame(pScrn->pScreen->myNum, x, y, flags);
+ pSmi->DGAViewportStatus = 0;
+
+ LEAVE_PROC("SMI_SetViewport");
+}
+
+static void
+SMI_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_FillRect");
+
+ if (pSmi->AccelInfoRec)
+ {
+ (*pSmi->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
+ (*pSmi->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
+ SET_SYNC_FLAG(pSmi->AccelInfoRec);
+ }
+
+ LEAVE_PROC("SMI_FillRect");
+}
+
+static void
+SMI_BlitRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, int dstx,
+ int dsty)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_BlitRect");
+
+ if (pSmi->AccelInfoRec)
+ {
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ (*pSmi->AccelInfoRec->SetupForScreenToScreenCopy)(pScrn, xdir, ydir,
+ GXcopy, ~0, -1);
+ (*pSmi->AccelInfoRec->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy,
+ dstx, dsty, w, h);
+ SET_SYNC_FLAG(pSmi->AccelInfoRec);
+ }
+
+ LEAVE_PROC("SMI_BlitRect");
+}
+
+static void
+SMI_BlitTransRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, int dstx,
+ int dsty, unsigned long color)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_BlitTraneRect");
+
+ if (pSmi->AccelInfoRec)
+ {
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ (*pSmi->AccelInfoRec->SetupForScreenToScreenCopy)(pScrn, xdir, ydir,
+ GXcopy, ~0, color);
+ (*pSmi->AccelInfoRec->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy,
+ dstx, dsty, w, h);
+ SET_SYNC_FLAG(pSmi->AccelInfoRec);
+ }
+
+ LEAVE_PROC("SMI_BlitTraneRect");
+}
+
+static Bool
+SMI_OpenFramebuffer(ScrnInfoPtr pScrn, char **name, unsigned char **mem,
+ int *size, int *offset, int *flags)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_OpenFrameBuffer");
+
+ *name = NULL; /* no special device */
+ *mem = (unsigned char*)pSmi->FBBase;
+ *size = pSmi->videoRAMBytes;
+ *offset = 0;
+ *flags = DGA_NEED_ROOT;
+
+ LEAVE_PROC("SMI_OpenFrameBuffer");
+ return(TRUE);
+}
diff --git a/src/smi_driver.c b/src/smi_driver.c
new file mode 100644
index 0000000..ffd946e
--- /dev/null
+++ b/src/smi_driver.c
@@ -0,0 +1,3294 @@
+/* Header: //Mercury/Projects/archives/XFree86/4.0/smi_driver.c-arc 1.42 03 Jan 2001 13:52:16 Frido $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. 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, sublicense, 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 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, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the names of The XFree86 Project and
+Silicon Motion shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from The XFree86 Project or Silicon Motion.
+*/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_driver.c,v 1.28.2.1 2003/05/09 02:22:00 dawes Exp $ */
+
+#include "xf86Resources.h"
+#include "xf86RAC.h"
+#include "xf86DDC.h"
+#include "xf86int10.h"
+#include "vbe.h"
+#include "shadowfb.h"
+
+#include "smi.h"
+
+#include "globals.h"
+#define DPMS_SERVER
+#include "extensions/dpms.h"
+
+/*
+ * Internals
+ */
+static void SMI_EnableMmio(ScrnInfoPtr pScrn);
+static void SMI_DisableMmio(ScrnInfoPtr pScrn);
+
+/*
+ * Forward definitions for the functions that make up the driver.
+ */
+
+static const OptionInfoRec * SMI_AvailableOptions(int chipid, int busid);
+static void SMI_Identify(int flags);
+static Bool SMI_Probe(DriverPtr drv, int flags);
+static Bool SMI_PreInit(ScrnInfoPtr pScrn, int flags);
+static Bool SMI_EnterVT(int scrnIndex, int flags);
+static void SMI_LeaveVT(int scrnIndex, int flags);
+static void SMI_Save (ScrnInfoPtr pScrn);
+static void SMI_WriteMode (ScrnInfoPtr pScrn, vgaRegPtr, SMIRegPtr);
+static Bool SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
+ char **argv);
+static int SMI_InternalScreenInit(int scrnIndex, ScreenPtr pScreen);
+static void SMI_PrintRegs(ScrnInfoPtr);
+static ModeStatus SMI_ValidMode(int scrnIndex, DisplayModePtr mode,
+ Bool verbose, int flags);
+static void SMI_DisableVideo(ScrnInfoPtr pScrn);
+static void SMI_EnableVideo(ScrnInfoPtr pScrn);
+static Bool SMI_MapMem(ScrnInfoPtr pScrn);
+static void SMI_UnmapMem(ScrnInfoPtr pScrn);
+static Bool SMI_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
+static Bool SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen);
+static Bool SMI_SaveScreen(ScreenPtr pScreen, int mode);
+static void SMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies,
+ LOCO *colors, VisualPtr pVisual);
+static void SMI_DisplayPowerManagementSet(ScrnInfoPtr pScrn,
+ int PowerManagementMode, int flags);
+static Bool SMI_ddc1(int scrnIndex);
+static unsigned int SMI_ddc1Read(ScrnInfoPtr pScrn);
+static void SMI_FreeScreen(int ScrnIndex, int flags);
+static void SMI_ProbeDDC(ScrnInfoPtr pScrn, int index);
+
+
+#define SILICONMOTION_NAME "Silicon Motion"
+#define SILICONMOTION_DRIVER_NAME "siliconmotion"
+#define SILICONMOTION_VERSION_NAME "1.3.1"
+#define SILICONMOTION_VERSION_MAJOR 1
+#define SILICONMOTION_VERSION_MINOR 3
+#define SILICONMOTION_PATCHLEVEL 1
+#define SILICONMOTION_DRIVER_VERSION ((SILICONMOTION_VERSION_MAJOR << 24) | \
+ (SILICONMOTION_VERSION_MINOR << 16) | \
+ (SILICONMOTION_PATCHLEVEL))
+
+/*
+ * This contains the functions needed by the server after loading the
+ * driver module. It must be supplied, and gets added the driver list by
+ * the Module Setup funtion 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 SILICONMOTION =
+{
+ SILICONMOTION_DRIVER_VERSION,
+ SILICONMOTION_DRIVER_NAME,
+ SMI_Identify,
+ SMI_Probe,
+ SMI_AvailableOptions,
+ NULL,
+ 0
+};
+
+/* Supported chipsets */
+static SymTabRec SMIChipsets[] =
+{
+ { PCI_CHIP_SMI910, "Lynx" },
+ { PCI_CHIP_SMI810, "LynxE" },
+ { PCI_CHIP_SMI820, "Lynx3D" },
+ { PCI_CHIP_SMI710, "LynxEM" },
+ { PCI_CHIP_SMI712, "LynxEM+" },
+ { PCI_CHIP_SMI720, "Lynx3DM" },
+ { -1, NULL }
+};
+
+static PciChipsets SMIPciChipsets[] =
+{
+ /* numChipset, PciID, Resource */
+ { PCI_CHIP_SMI910, PCI_CHIP_SMI910, RES_SHARED_VGA },
+ { PCI_CHIP_SMI810, PCI_CHIP_SMI810, RES_SHARED_VGA },
+ { PCI_CHIP_SMI820, PCI_CHIP_SMI820, RES_SHARED_VGA },
+ { PCI_CHIP_SMI710, PCI_CHIP_SMI710, RES_SHARED_VGA },
+ { PCI_CHIP_SMI712, PCI_CHIP_SMI712, RES_SHARED_VGA },
+ { PCI_CHIP_SMI720, PCI_CHIP_SMI720, RES_SHARED_VGA },
+ { -1, -1, RES_UNDEFINED }
+};
+
+typedef enum
+{
+ OPTION_PCI_BURST,
+ OPTION_FIFO_CONSERV,
+ OPTION_FIFO_MODERATE,
+ OPTION_FIFO_AGGRESSIVE,
+ OPTION_PCI_RETRY,
+ OPTION_NOACCEL,
+ OPTION_MCLK,
+ OPTION_SHOWCACHE,
+ OPTION_SWCURSOR,
+ OPTION_HWCURSOR,
+ OPTION_SHADOW_FB,
+ OPTION_ROTATE,
+#ifdef XvExtension
+ OPTION_VIDEOKEY,
+ OPTION_BYTESWAP,
+ /* CZ 26.10.2001: interlaced video */
+ OPTION_INTERLACED,
+ /* end CZ */
+#endif
+ OPTION_USEBIOS,
+ OPTION_ZOOMONLCD,
+ NUMBER_OF_OPTIONS
+
+} SMIOpts;
+
+static const OptionInfoRec SMIOptions[] =
+{
+ { OPTION_PCI_BURST, "pci_burst", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_FIFO_CONSERV, "fifo_conservative", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_FIFO_MODERATE, "fifo_moderate", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_FIFO_AGGRESSIVE, "fifo_aggressive", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_PCI_RETRY, "pci_retry", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_MCLK, "set_mclk", OPTV_FREQ, {0}, FALSE },
+ { OPTION_SHOWCACHE, "show_cache", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_HWCURSOR, "HWCursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE },
+#ifdef XvExtension
+ { OPTION_VIDEOKEY, "VideoKey", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_BYTESWAP, "ByteSwap", OPTV_BOOLEAN, {0}, FALSE },
+ /* CZ 26.10.2001: interlaced video */
+ { OPTION_INTERLACED, "Interlaced", OPTV_BOOLEAN, {0}, FALSE },
+ /* end CZ */
+#endif
+ { OPTION_USEBIOS, "UseBIOS", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_ZOOMONLCD, "ZoomOnLCD", OPTV_BOOLEAN, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+/*
+ * Lists of symbols that may/may not be required by this driver.
+ * This allows the loader to know which ones to issue warnings for.
+ *
+ * Note that vgahwSymbols and xaaSymbols are referenced outside the
+ * XFree86LOADER define in later code, so are defined outside of that
+ * define here also.
+ */
+
+static const char *vgahwSymbols[] =
+{
+ "vgaHWCopyReg",
+ "vgaHWGetHWRec",
+ "vgaHWGetIOBase",
+ "vgaHWGetIndex",
+ "vgaHWInit",
+ "vgaHWLock",
+ "vgaHWMapMem",
+ "vgaHWProtect",
+ "vgaHWRestore",
+ "vgaHWSave",
+ "vgaHWSaveScreen",
+ "vgaHWSetMmioFuncs",
+ "vgaHWSetStdFuncs",
+ "vgaHWUnmapMem",
+ "vgaHWddc1SetSpeed",
+ NULL
+};
+
+static const char *xaaSymbols[] =
+{
+ "XAACopyROP",
+ "XAACreateInfoRec",
+ "XAADestroyInfoRec",
+ "XAAFallbackOps",
+ "XAAFillSolidRects",
+ "XAAInit",
+ "XAAPatternROP",
+ "XAAScreenIndex",
+ NULL
+};
+
+static const char *ramdacSymbols[] =
+{
+ "xf86CreateCursorInfoRec",
+ "xf86DestroyCursorInfoRec",
+ "xf86InitCursor",
+ NULL
+};
+
+static const char *ddcSymbols[] =
+{
+ "xf86PrintEDID",
+ "xf86DoEDID_DDC1",
+ "xf86DoEDID_DDC2",
+ "xf86SetDDCproperties",
+ NULL
+};
+
+static const char *i2cSymbols[] =
+{
+ "xf86CreateI2CBusRec",
+ "xf86CreateI2CDevRec",
+ "xf86DestroyI2CBusRec",
+ "xf86DestroyI2CDevRec",
+ "xf86I2CBusInit",
+ "xf86I2CDevInit",
+ "xf86I2CReadBytes",
+ "xf86I2CWriteByte",
+ NULL
+};
+
+static const char *shadowSymbols[] =
+{
+ "ShadowFBInit",
+ NULL
+};
+
+static const char *int10Symbols[] =
+{
+ "xf86ExecX86int10",
+ "xf86FreeInt10",
+ "xf86InitInt10",
+ NULL
+};
+
+static const char *vbeSymbols[] =
+{
+ "VBEInit",
+ "vbeDoEDID",
+ "vbeFree",
+ NULL
+};
+
+static const char *fbSymbols[] =
+{
+#ifdef USE_FB
+ "fbPictureInit",
+ "fbScreenInit",
+#else
+ "cfbScreenInit",
+ "cfb16ScreenInit",
+ "cfb24ScreenInit",
+ "cfb32ScreenInit",
+ "cfb16BresS",
+ "cfb24BresS",
+#endif
+ NULL
+};
+
+#ifdef XFree86LOADER
+
+static MODULESETUPPROTO(siliconmotionSetup);
+
+static XF86ModuleVersionInfo SMIVersRec =
+{
+ "siliconmotion",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ SILICONMOTION_VERSION_MAJOR,
+ SILICONMOTION_VERSION_MINOR,
+ SILICONMOTION_PATCHLEVEL,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0, 0, 0, 0}
+};
+
+/*
+ * This is the module init data for XFree86 modules.
+ *
+ * Its name has to be the driver name followed by ModuleData.
+ */
+XF86ModuleData siliconmotionModuleData =
+{
+ &SMIVersRec,
+ siliconmotionSetup,
+ NULL
+};
+
+static pointer
+siliconmotionSetup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = FALSE;
+
+ if (!setupDone)
+ {
+ setupDone = TRUE;
+ xf86AddDriver(&SILICONMOTION, module, 0);
+
+ /*
+ * Modules that this driver always requires can be loaded here
+ * by calling LoadSubModule().
+ */
+
+ /*
+ * Tell the loader about symbols from other modules that this module
+ * might refer to.
+ */
+ LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols, ramdacSymbols,
+ ddcSymbols, i2cSymbols, int10Symbols, vbeSymbols,
+ shadowSymbols, NULL);
+
+ /*
+ * The return value must be non-NULL on success even though there
+ * is no TearDownProc.
+ */
+ return (pointer) 1;
+ }
+ else
+ {
+ if (errmaj)
+ {
+ *errmaj = LDR_ONCEONLY;
+ }
+ return(NULL);
+ }
+}
+
+#endif /* XFree86LOADER */
+
+static Bool
+SMI_GetRec(ScrnInfoPtr pScrn)
+{
+ ENTER_PROC("SMI_GetRec");
+
+ /*
+ * Allocate an 'Chip'Rec, 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)
+ {
+ pScrn->driverPrivate = xnfcalloc(sizeof(SMIRec), 1);
+ }
+
+ LEAVE_PROC("SMI_GetRec");
+ return(TRUE);
+}
+
+static void
+SMI_FreeRec(ScrnInfoPtr pScrn)
+{
+ ENTER_PROC("SMI_FreeRec");
+
+ if (pScrn->driverPrivate != NULL)
+ {
+ xfree(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+ }
+
+ LEAVE_PROC("SMI_FreeRec");
+}
+
+static const OptionInfoRec *
+SMI_AvailableOptions(int chipid, int busid)
+{
+ ENTER_PROC("SMI_AvailableOptions");
+ LEAVE_PROC("SMI_AvailableOptions");
+ return(SMIOptions);
+}
+
+static void
+SMI_Identify(int flags)
+{
+ ENTER_PROC("SMI_Identify");
+
+ xf86PrintChipsets(SILICONMOTION_NAME, "driver (version "
+ SILICONMOTION_VERSION_NAME ") for Silicon Motion Lynx chipsets",
+ SMIChipsets);
+
+ LEAVE_PROC("SMI_Identify");
+}
+
+static Bool
+SMI_Probe(DriverPtr drv, int flags)
+{
+ int i;
+ GDevPtr *devSections;
+ int *usedChips;
+ int numDevSections;
+ int numUsed;
+ Bool foundScreen = FALSE;
+
+ ENTER_PROC("SMI_Probe");
+
+ numDevSections = xf86MatchDevice(SILICONMOTION_DRIVER_NAME, &devSections);
+ if (numDevSections <= 0)
+ {
+ /* There's no matching device section in the config file, so quit now.
+ */
+ LEAVE_PROC("SMI_Probe");
+ return(FALSE);
+ }
+
+ if (xf86GetPciVideoInfo() == NULL)
+ {
+ LEAVE_PROC("SMI_Probe");
+ return(FALSE);
+ }
+
+ numUsed = xf86MatchPciInstances(SILICONMOTION_NAME, PCI_SMI_VENDOR_ID,
+ SMIChipsets, SMIPciChipsets, devSections,
+ numDevSections, drv, &usedChips);
+
+ /* Free it since we don't need that list after this */
+ xfree(devSections);
+ if (numUsed <= 0)
+ {
+ LEAVE_PROC("SMI_Probe");
+ return(FALSE);
+ }
+
+ if (flags & PROBE_DETECT)
+ {
+ foundScreen = TRUE;
+ }
+ else
+ {
+ for (i = 0; i < numUsed; i++)
+ {
+ /* Allocate a ScrnInfoRec and claim the slot */
+ ScrnInfoPtr pScrn = xf86AllocateScreen(drv, 0);
+
+ /* Fill in what we can of the ScrnInfoRec */
+ pScrn->driverVersion = SILICONMOTION_DRIVER_VERSION;
+ pScrn->driverName = SILICONMOTION_DRIVER_NAME;
+ pScrn->name = SILICONMOTION_NAME;
+ pScrn->Probe = SMI_Probe;
+ pScrn->PreInit = SMI_PreInit;
+ pScrn->ScreenInit = SMI_ScreenInit;
+ pScrn->SwitchMode = SMI_SwitchMode;
+ pScrn->AdjustFrame = SMI_AdjustFrame;
+ pScrn->EnterVT = SMI_EnterVT;
+ pScrn->LeaveVT = SMI_LeaveVT;
+ pScrn->FreeScreen = SMI_FreeScreen;
+ pScrn->ValidMode = SMI_ValidMode;
+ foundScreen = TRUE;
+
+ xf86ConfigActivePciEntity(pScrn, usedChips[i], SMIPciChipsets, NULL,
+ NULL, NULL, NULL, NULL);
+ }
+ }
+ xfree(usedChips);
+
+ LEAVE_PROC("SMI_Probe");
+ return(foundScreen);
+}
+
+static Bool
+SMI_PreInit(ScrnInfoPtr pScrn, int flags)
+{
+ EntityInfoPtr pEnt;
+ SMIPtr pSmi;
+ MessageType from;
+ int i;
+ double real;
+ ClockRangePtr clockRanges;
+#ifndef USE_FB
+ char *mod = NULL;
+ const char *reqSym = NULL;
+#endif
+ char *s;
+ unsigned char config, m, n, shift;
+ int mclk;
+ vgaHWPtr hwp;
+ int vgaCRIndex, vgaCRReg, vgaIOBase;
+ vbeInfoPtr pVbe = NULL;
+
+ ENTER_PROC("SMI_PreInit");
+
+ if (flags & PROBE_DETECT)
+ {
+ SMI_ProbeDDC(pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index);
+ LEAVE_PROC("SMI_PreInit");
+ return(TRUE);
+ }
+
+ /* Ignoring the Type list for now. It might be needed when multiple cards
+ * are supported.
+ */
+ if (pScrn->numEntities > 1)
+ {
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+
+ /* The vgahw module should be loaded here when needed */
+ if (!xf86LoadSubModule(pScrn, "vgahw"))
+ {
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+
+ xf86LoaderReqSymLists(vgahwSymbols, NULL);
+
+ /*
+ * Allocate a vgaHWRec
+ */
+ if (!vgaHWGetHWRec(pScrn))
+ {
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+
+ /* Allocate the SMIRec driverPrivate */
+ if (!SMI_GetRec(pScrn))
+ {
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+ pSmi = SMIPTR(pScrn);
+
+ /* Set pScrn->monitor */
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+ /*
+ * The first thing we should figure out is the depth, bpp, etc. Our
+ * default depth is 8, so pass it to the helper function. We support
+ * only 24bpp layouts, so indicate that.
+ */
+ if (!xf86SetDepthBpp(pScrn, 8, 8, 8, Support24bppFb))
+ {
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+
+ /* Check that the returned depth is one we support */
+ switch (pScrn->depth)
+ {
+ case 8:
+ case 16:
+ case 24:
+ /* OK */
+ break;
+
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by this driver\n",
+ pScrn->depth);
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+ xf86PrintDepthBpp(pScrn);
+
+ /*
+ * 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))
+ {
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+ }
+
+ if (!xf86SetDefaultVisual(pScrn, -1))
+ {
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+
+ /* We don't currently 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);
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+
+ /* We use a programmable clock */
+ pScrn->progClock = TRUE;
+
+ /* Collect all of the relevant option flags (fill in pScrn->options) */
+ xf86CollectOptions(pScrn, NULL);
+
+ /* Set the bits per RGB for 8bpp mode */
+ if (pScrn->depth == 8)
+ {
+ pScrn->rgbBits = 6;
+ }
+
+ /* Process the options */
+ if (!(pSmi->Options = xalloc(sizeof(SMIOptions))))
+ return FALSE;
+ memcpy(pSmi->Options, SMIOptions, sizeof(SMIOptions));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pSmi->Options);
+
+ if (xf86ReturnOptValBool(pSmi->Options, OPTION_PCI_BURST, FALSE))
+ {
+ pSmi->pci_burst = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: pci_burst - PCI burst "
+ "read enabled\n");
+ }
+ else
+ {
+ pSmi->pci_burst = FALSE;
+ }
+
+ pSmi->NoPCIRetry = TRUE;
+ if (xf86ReturnOptValBool(pSmi->Options, OPTION_PCI_RETRY, FALSE))
+ {
+ if (xf86ReturnOptValBool(pSmi->Options, OPTION_PCI_BURST, FALSE))
+ {
+ pSmi->NoPCIRetry = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: pci_retry\n");
+ }
+ else
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"pci_retry\" option "
+ "requires \"pci_burst\".\n");
+ }
+ }
+
+ if (xf86IsOptionSet(pSmi->Options, OPTION_FIFO_CONSERV))
+ {
+ pSmi->fifo_conservative = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fifo_conservative "
+ "set\n");
+ }
+ else
+ {
+ pSmi->fifo_conservative = FALSE;
+ }
+
+ if (xf86IsOptionSet(pSmi->Options, OPTION_FIFO_MODERATE))
+ {
+ pSmi->fifo_moderate = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fifo_moderate set\n");
+ }
+ else
+ {
+ pSmi->fifo_moderate = FALSE;
+ }
+
+ if (xf86IsOptionSet(pSmi->Options, OPTION_FIFO_AGGRESSIVE))
+ {
+ pSmi->fifo_aggressive = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: fifo_aggressive set\n");
+ }
+ else
+ {
+ pSmi->fifo_aggressive = FALSE;
+ }
+
+ if (xf86ReturnOptValBool(pSmi->Options, OPTION_NOACCEL, FALSE))
+ {
+ pSmi->NoAccel = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - Acceleration "
+ "disabled\n");
+ }
+ else
+ {
+ pSmi->NoAccel = FALSE;
+ }
+
+ if (xf86ReturnOptValBool(pSmi->Options, OPTION_SHOWCACHE, FALSE))
+ {
+ pSmi->ShowCache = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: show_cache set\n");
+ }
+ else
+ {
+ pSmi->ShowCache = FALSE;
+ }
+
+ if (xf86GetOptValFreq(pSmi->Options, OPTION_MCLK, OPTUNITS_MHZ, &real))
+ {
+ pSmi->MCLK = (int)(real * 1000.0);
+ if (pSmi->MCLK <= 120000)
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: set_mclk set to "
+ "%1.3f MHz\n", pSmi->MCLK / 1000.0);
+ }
+ else
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Memory Clock value of "
+ "%1.3f MHz is larger than limit of 120 MHz\n",
+ pSmi->MCLK / 1000.0);
+ pSmi->MCLK = 0;
+ }
+ }
+ else
+ {
+ pSmi->MCLK = 0;
+ }
+
+ from = X_DEFAULT;
+ pSmi->hwcursor = TRUE;
+ if (xf86GetOptValBool(pSmi->Options, OPTION_HWCURSOR, &pSmi->hwcursor))
+ {
+ from = X_CONFIG;
+ }
+ if (xf86ReturnOptValBool(pSmi->Options, OPTION_SWCURSOR, FALSE))
+ {
+ pSmi->hwcursor = FALSE;
+ from = X_CONFIG;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Using %s Cursor\n",
+ pSmi->hwcursor ? "Hardware" : "Software");
+
+ if (xf86GetOptValBool(pSmi->Options, OPTION_SHADOW_FB, &pSmi->shadowFB))
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowFB %s.\n",
+ pSmi->shadowFB ? "enabled" : "disabled");
+ }
+
+#if 1 /* PDR#932 */
+ if ((pScrn->depth == 8) || (pScrn->depth == 16))
+#endif /* PDR#932 */
+ if ((s = xf86GetOptValString(pSmi->Options, OPTION_ROTATE)))
+ {
+ if(!xf86NameCmp(s, "CW"))
+ {
+ pSmi->shadowFB = TRUE;
+ pSmi->rotate = SMI_ROTATE_CCW;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen "
+ "clockwise\n");
+ }
+ else if (!xf86NameCmp(s, "CCW"))
+ {
+ pSmi->shadowFB = TRUE;
+ pSmi->rotate = SMI_ROTATE_CW;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen counter "
+ "clockwise\n");
+ }
+ else
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid "
+ "value for Option \"Rotate\"\n", s);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid options are \"CW\" or "
+ "\"CCW\"\n");
+ }
+ }
+
+#ifdef XvExtension
+ if (xf86GetOptValInteger(pSmi->Options, OPTION_VIDEOKEY, &pSmi->videoKey))
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Video key set to "
+ "0x%08X\n", pSmi->videoKey);
+ }
+ else
+ {
+ pSmi->videoKey = (1 << pScrn->offset.red) | (1 << pScrn->offset.green)
+ | (((pScrn->mask.blue >> pScrn->offset.blue) - 1)
+ << pScrn->offset.blue);
+ }
+
+ if (xf86ReturnOptValBool(pSmi->Options, OPTION_BYTESWAP, FALSE))
+ {
+ pSmi->ByteSwap = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: ByteSwap enabled.\n");
+ }
+ else
+ {
+ pSmi->ByteSwap = FALSE;
+ }
+
+ /* CZ 26.10.2001: interlaced video */
+ if (xf86ReturnOptValBool(pSmi->Options, OPTION_INTERLACED, FALSE))
+ {
+ pSmi->interlaced = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Interlaced enabled.\n");
+ }
+ else
+ {
+ pSmi->interlaced = FALSE;
+ }
+ /* end CZ */
+#endif
+
+ if (xf86GetOptValBool(pSmi->Options, OPTION_USEBIOS, &pSmi->useBIOS))
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: UseBIOS %s.\n",
+ pSmi->useBIOS ? "enabled" : "disabled");
+ }
+ else
+ {
+ /* Default to UseBIOS enabled. */
+ pSmi->useBIOS = TRUE;
+ }
+
+ if (xf86GetOptValBool(pSmi->Options, OPTION_ZOOMONLCD, &pSmi->zoomOnLCD))
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: ZoomOnLCD %s.\n",
+ pSmi->zoomOnLCD ? "enabled" : "disabled");
+ }
+ else
+ {
+ /* Default to ZoomOnLCD enabled. */
+ pSmi->zoomOnLCD = TRUE;
+ }
+
+ /* Find the PCI slot for this screen */
+ pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+ if ((pEnt->location.type != BUS_PCI) || (pEnt->resources))
+ {
+ xfree(pEnt);
+ SMI_FreeRec(pScrn);
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+
+ if (xf86LoadSubModule(pScrn,"int10")) {
+ xf86LoaderReqSymLists(int10Symbols,NULL);
+ pSmi->pInt10 = xf86InitInt10(pEnt->index);
+ }
+
+ if (pSmi->pInt10 && xf86LoadSubModule(pScrn, "vbe"))
+ {
+ xf86LoaderReqSymLists(vbeSymbols, NULL);
+ pVbe = VBEInit(pSmi->pInt10, pEnt->index);
+ }
+
+ pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
+ xf86RegisterResources(pEnt->index, NULL, ResExclusive);
+/* xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr); */
+/* xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr); */
+
+ /*
+ * Set the Chipset and ChipRev, allowing config file entries to
+ * override.
+ */
+ if (pEnt->device->chipset && *pEnt->device->chipset)
+ {
+ pScrn->chipset = pEnt->device->chipset;
+ pSmi->Chipset = xf86StringToToken(SMIChipsets, pScrn->chipset);
+ from = X_CONFIG;
+ }
+ else if (pEnt->device->chipID >= 0)
+ {
+ pSmi->Chipset = pEnt->device->chipID;
+ pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
+ from = X_CONFIG;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
+ pSmi->Chipset);
+ }
+ else
+ {
+ from = X_PROBED;
+ pSmi->Chipset = pSmi->PciInfo->chipType;
+ pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
+ }
+
+ if (pEnt->device->chipRev >= 0)
+ {
+ pSmi->ChipRev = pEnt->device->chipRev;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
+ pSmi->ChipRev);
+ }
+ else
+ {
+ pSmi->ChipRev = pSmi->PciInfo->chipRev;
+ }
+ xfree(pEnt);
+
+ /*
+ * This shouldn't happen because such problems should be caught in
+ * SMI_Probe(), but check it just in case.
+ */
+ if (pScrn->chipset == NULL)
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04X is not "
+ "recognised\n", pSmi->Chipset);
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+ if (pSmi->Chipset < 0)
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Chipset \"%s\" is not "
+ "recognised\n", pScrn->chipset);
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
+
+ pSmi->PciTag = pciTag(pSmi->PciInfo->bus, pSmi->PciInfo->device,
+ pSmi->PciInfo->func);
+
+ SMI_MapMem(pScrn);
+ SMI_DisableVideo(pScrn);
+
+ hwp = VGAHWPTR(pScrn);
+ vgaIOBase = hwp->IOBase;
+ vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET;
+ vgaCRReg = vgaIOBase + VGA_CRTC_DATA_OFFSET;
+ pSmi->PIOBase = hwp->PIOOffset;
+
+ xf86ErrorFVerb(VERBLEV, "\tSMI_PreInit vgaCRIndex=%x, vgaIOBase=%x, "
+ "MMIOBase=%x\n", vgaCRIndex, vgaIOBase, hwp->MMIOBase);
+
+ /* Next go on to detect amount of installed ram */
+ config = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x71);
+
+ if (xf86LoadSubModule(pScrn, "i2c"))
+ {
+ xf86LoaderReqSymLists(i2cSymbols, NULL);
+ SMI_I2CInit(pScrn);
+ }
+ if (xf86LoadSubModule(pScrn, "ddc"))
+ {
+ xf86MonPtr pMon = NULL;
+
+ xf86LoaderReqSymLists(ddcSymbols, NULL);
+#if 1 /* PDR#579 */
+ if (pVbe)
+ {
+ pMon = vbeDoEDID(pVbe, NULL);
+ if (pMon != NULL)
+ {
+ if ( (pMon->rawData[0] == 0x00)
+ && (pMon->rawData[1] == 0xFF)
+ && (pMon->rawData[2] == 0xFF)
+ && (pMon->rawData[3] == 0xFF)
+ && (pMon->rawData[4] == 0xFF)
+ && (pMon->rawData[5] == 0xFF)
+ && (pMon->rawData[6] == 0xFF)
+ && (pMon->rawData[7] == 0x00)
+ )
+ {
+ pMon = xf86PrintEDID(pMon);
+ if (pMon != NULL)
+ {
+ xf86SetDDCproperties(pScrn, pMon);
+ }
+ }
+ }
+ }
+#else
+ if ( (pVbe)
+ && ((pMon = xf86PrintEDID(vbeDoEDID(pVbe, NULL))) != NULL)
+ )
+ {
+ xf86SetDDCproperties(pScrn, pMon);
+ }
+#endif
+ else if (!SMI_ddc1(pScrn->scrnIndex))
+ {
+ if (pSmi->I2C)
+ {
+ xf86SetDDCproperties(pScrn,
+ xf86PrintEDID(xf86DoEDID_DDC2(pScrn->scrnIndex,
+ pSmi->I2C)));
+ }
+ }
+ }
+
+ vbeFree(pVbe);
+ xf86FreeInt10(pSmi->pInt10);
+ pSmi->pInt10 = NULL;
+
+ /*
+ * If the driver can do gamma correction, it should call xf86SetGamma()
+ * here. (from MGA, no ViRGE gamma support yet, but needed for
+ * xf86HandleColormaps support.)
+ */
+ {
+ Gamma zeros = { 0.0, 0.0, 0.0 };
+
+ if (!xf86SetGamma(pScrn, zeros))
+ {
+ LEAVE_PROC("SMI_PreInit");
+ SMI_EnableVideo(pScrn);
+ SMI_UnmapMem(pScrn);
+ return(FALSE);
+ }
+ }
+
+ /* And compute the amount of video memory and offscreen memory */
+ pSmi->videoRAMKBytes = 0;
+
+ if (!pScrn->videoRam)
+ {
+ switch (pSmi->Chipset)
+ {
+ default:
+ {
+ int mem_table[4] = { 1, 2, 4, 0 };
+ pSmi->videoRAMKBytes = mem_table[(config >> 6)] * 1024;
+ break;
+ }
+
+ case SMI_LYNX3D:
+ {
+ int mem_table[4] = { 0, 2, 4, 6 };
+ pSmi->videoRAMKBytes = mem_table[(config >> 6)] * 1024 + 512;
+ break;
+ }
+
+ case SMI_LYNX3DM:
+ {
+ int mem_table[4] = { 16, 2, 4, 8 };
+ pSmi->videoRAMKBytes = mem_table[(config >> 6)] * 1024;
+ break;
+ }
+ }
+ pSmi->videoRAMBytes = pSmi->videoRAMKBytes * 1024;
+ pScrn->videoRam = pSmi->videoRAMKBytes;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "videoram: %dkB\n",
+ pSmi->videoRAMKBytes);
+ }
+ else
+ {
+ pSmi->videoRAMKBytes = pScrn->videoRam;
+ pSmi->videoRAMBytes = pScrn->videoRam * 1024;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "videoram: %dk\n",
+ pSmi->videoRAMKBytes);
+ }
+
+ /* Lynx built-in ramdac speeds */
+ pScrn->numClocks = 4;
+
+ if ((pScrn->clock[3] <= 0) && (pScrn->clock[2] > 0))
+ {
+ pScrn->clock[3] = pScrn->clock[2];
+ }
+
+ if (pSmi->Chipset == SMI_LYNX3DM)
+ {
+ if (pScrn->clock[0] <= 0) pScrn->clock[0] = 200000;
+ if (pScrn->clock[1] <= 0) pScrn->clock[1] = 200000;
+ if (pScrn->clock[2] <= 0) pScrn->clock[2] = 200000;
+ if (pScrn->clock[3] <= 0) pScrn->clock[3] = 200000;
+ }
+ else
+ {
+ if (pScrn->clock[0] <= 0) pScrn->clock[0] = 135000;
+ if (pScrn->clock[1] <= 0) pScrn->clock[1] = 135000;
+ if (pScrn->clock[2] <= 0) pScrn->clock[2] = 135000;
+ if (pScrn->clock[3] <= 0) pScrn->clock[3] = 135000;
+ }
+
+ /* Now set RAMDAC limits */
+ switch (pSmi->Chipset)
+ {
+ default:
+ pSmi->minClock = 20000;
+ pSmi->maxClock = 135000;
+ break;
+ }
+ xf86ErrorFVerb(VERBLEV, "\tSMI_PreInit minClock=%d, maxClock=%d\n",
+ pSmi->minClock, pSmi->maxClock);
+
+ /* Detect current MCLK and print it for user */
+ m = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A);
+ n = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B);
+ switch (n >> 6)
+ {
+ default:
+ shift = 1;
+ break;
+
+ case 1:
+ shift = 4;
+ break;
+
+ case 2:
+ shift = 2;
+ break;
+ }
+ n &= 0x3F;
+ mclk = ((1431818 * m) / n / shift + 50) / 100;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected current MCLK value of "
+ "%1.3f MHz\n", mclk / 1000.0);
+
+ SMI_EnableVideo(pScrn);
+ SMI_UnmapMem(pScrn);
+
+ pScrn->virtualX = pScrn->display->virtualX;
+
+ /*
+ * 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 = pSmi->minClock;
+ clockRanges->maxClock = pSmi->maxClock;
+ clockRanges->clockIndex = -1;
+ clockRanges->interlaceAllowed = FALSE;
+ clockRanges->doubleScanAllowed = FALSE;
+
+ i = xf86ValidateModes(
+ pScrn, /* Screen pointer */
+ pScrn->monitor->Modes, /* Available monitor modes */
+ pScrn->display->modes, /* req mode names for screen */
+ clockRanges, /* list of clock ranges allowed */
+ NULL, /* use min/max below */
+ 128, /* min line pitch (width) */
+ 4096, /* maximum line pitch (width) */
+ 128, /* bits of granularity for line pitch */
+ /* (width) above */
+ 128, /* min virtual height */
+ 4096, /* max virtual height */
+ pScrn->display->virtualX, /* force virtual x */
+ pScrn->display->virtualY, /* force virtual Y */
+ pSmi->videoRAMBytes, /* size of aperture used to access */
+ /* video memory */
+ LOOKUP_BEST_REFRESH); /* how to pick modes */
+
+ if (i == -1)
+ {
+ SMI_FreeRec(pScrn);
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+
+ /* Prune the modes marked as invalid */
+ xf86PruneDriverModes(pScrn);
+
+ if ((i == 0) || (pScrn->modes == NULL))
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+ SMI_FreeRec(pScrn);
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+ xf86SetCrtcForModes(pScrn, 0);
+
+ /* Set the current mode to the first in the list */
+ pScrn->currentMode = pScrn->modes;
+
+ /* Print the list of modes being used */
+ xf86PrintModes(pScrn);
+
+ /* Set display resolution */
+ xf86SetDpi(pScrn, 0, 0);
+
+#ifdef USE_FB
+ if ((xf86LoadSubModule(pScrn, "fb") == NULL))
+ {
+ SMI_FreeRec(pScrn);
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+
+ xf86LoaderReqSymLists(fbSymbols, NULL);
+#else
+ /* Load bpp-specific modules */
+ switch (pScrn->bitsPerPixel)
+ {
+ case 8:
+ mod = "cfb";
+ reqSym = "cfbScreenInit";
+ break;
+
+ case 16:
+ mod = "cfb16";
+ reqSym = "cfb16ScreenInit";
+ break;
+
+ case 24:
+ mod = "cfb24";
+ reqSym = "cfb24ScreenInit";
+ break;
+ }
+
+ if (mod && (xf86LoadSubModule(pScrn, mod) == NULL))
+ {
+ SMI_FreeRec(pScrn);
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+
+ xf86LoaderReqSymbols(reqSym, NULL);
+#endif
+ /* Load XAA if needed */
+ if (!pSmi->NoAccel || pSmi->hwcursor)
+ {
+ if (!xf86LoadSubModule(pScrn, "xaa"))
+ {
+ SMI_FreeRec(pScrn);
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+ xf86LoaderReqSymLists(xaaSymbols, NULL);
+ }
+
+ /* Load ramdac if needed */
+ if (pSmi->hwcursor)
+ {
+ if (!xf86LoadSubModule(pScrn, "ramdac"))
+ {
+ SMI_FreeRec(pScrn);
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+ xf86LoaderReqSymLists(ramdacSymbols, NULL);
+ }
+
+ if (pSmi->shadowFB)
+ {
+ if (!xf86LoadSubModule(pScrn, "shadowfb"))
+ {
+ SMI_FreeRec(pScrn);
+ LEAVE_PROC("SMI_PreInit");
+ return(FALSE);
+ }
+ xf86LoaderReqSymLists(shadowSymbols, NULL);
+ }
+
+ LEAVE_PROC("SMI_PreInit");
+ return(TRUE);
+}
+
+/*
+ * This is called when VT switching back to the X server. Its job is to
+ * reinitialise the video mode. We may wish to unmap video/MMIO memory too.
+ */
+
+static Bool
+SMI_EnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ SMIPtr pSmi = SMIPTR(pScrn);
+ Bool ret;
+
+ ENTER_PROC("SMI_EnterVT");
+
+ /* Enable MMIO and map memory */
+ SMI_MapMem(pScrn);
+ SMI_Save(pScrn);
+
+ /* #670 */
+ if (pSmi->shadowFB)
+ {
+ pSmi->FBOffset = pSmi->savedFBOffset;
+ pSmi->FBReserved = pSmi->savedFBReserved;
+ }
+
+ ret = SMI_ModeInit(pScrn, pScrn->currentMode);
+
+ /* #670 */
+ if (ret && pSmi->shadowFB)
+ {
+ BoxRec box;
+
+ /* #920 */
+ if (pSmi->paletteBuffer)
+ {
+ int i;
+
+ VGAOUT8(pSmi, VGA_DAC_WRITE_ADDR, 0);
+ for(i = 0; i < 256 * 3; i++)
+ {
+ VGAOUT8(pSmi, VGA_DAC_DATA, pSmi->paletteBuffer[i]);
+ }
+ xfree(pSmi->paletteBuffer);
+ pSmi->paletteBuffer = NULL;
+ }
+
+ if (pSmi->pSaveBuffer)
+ {
+ memcpy(pSmi->FBBase, pSmi->pSaveBuffer, pSmi->saveBufferSize);
+ xfree(pSmi->pSaveBuffer);
+ pSmi->pSaveBuffer = NULL;
+ }
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScrn->virtualY;
+ box.y2 = pScrn->virtualX;
+ SMI_RefreshArea(pScrn, 1, &box);
+ }
+
+ /* Reset the grapics engine */
+ if (!pSmi->NoAccel)
+ SMI_EngineReset(pScrn);
+
+ LEAVE_PROC("SMI_EnterVT");
+ return(ret);
+}
+
+/*
+ * This is called when VT switching away from the X server. Its job is to
+ * restore the previous (text) mode. We may wish to remap video/MMIO memory
+ * too.
+ */
+
+static void
+SMI_LeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ SMIPtr pSmi = SMIPTR(pScrn);
+ vgaRegPtr vgaSavePtr = &hwp->SavedReg;
+ SMIRegPtr SMISavePtr = &pSmi->SavedReg;
+
+ ENTER_PROC("SMI_LeaveVT");
+
+ /* #670 */
+ if (pSmi->shadowFB)
+ {
+ pSmi->pSaveBuffer = xnfalloc(pSmi->saveBufferSize);
+ if (pSmi->pSaveBuffer)
+ {
+ memcpy(pSmi->pSaveBuffer, pSmi->FBBase, pSmi->saveBufferSize);
+ }
+
+ pSmi->savedFBOffset = pSmi->FBOffset;
+ pSmi->savedFBReserved = pSmi->FBReserved;
+
+ /* #920 */
+ if (pSmi->Bpp == 1)
+ {
+ pSmi->paletteBuffer = xnfalloc(256 * 3);
+ if (pSmi->paletteBuffer)
+ {
+ int i;
+
+ VGAOUT8(pSmi, VGA_DAC_READ_ADDR, 0);
+ for (i = 0; i < 256 * 3; i++)
+ {
+ pSmi->paletteBuffer[i] = VGAIN8(pSmi, VGA_DAC_DATA);
+ }
+ }
+ }
+ }
+
+ memset(pSmi->FBBase, 0, 256 * 1024); /* #689 */
+ SMI_WriteMode(pScrn, vgaSavePtr, SMISavePtr);
+ SMI_UnmapMem(pScrn);
+
+ LEAVE_PROC("SMI_LeaveVT");
+}
+
+/*
+ * This function performs the inverse of the restore function: It saves all the
+ * standard and extended registers that we are going to modify to set up a video
+ * mode.
+ */
+
+static void
+SMI_Save(ScrnInfoPtr pScrn)
+{
+ int i;
+ CARD32 offset;
+
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ vgaRegPtr vgaSavePtr = &hwp->SavedReg;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ SMIRegPtr save = &pSmi->SavedReg;
+
+ int vgaIOBase = hwp->IOBase;
+ int vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET;
+ int vgaCRData = vgaIOBase + VGA_CRTC_DATA_OFFSET;
+
+ ENTER_PROC("SMI_Save");
+
+ /* Save the standard VGA registers */
+ vgaHWSave(pScrn, vgaSavePtr, VGA_SR_ALL);
+ save->smiDACMask = VGAIN8(pSmi, VGA_DAC_MASK);
+ VGAOUT8(pSmi, VGA_DAC_READ_ADDR, 0);
+ for (i = 0; i < 256; i++)
+ {
+ save->smiDacRegs[i][0] = VGAIN8(pSmi, VGA_DAC_DATA);
+ save->smiDacRegs[i][1] = VGAIN8(pSmi, VGA_DAC_DATA);
+ save->smiDacRegs[i][2] = VGAIN8(pSmi, VGA_DAC_DATA);
+ }
+ for (i = 0, offset = 2; i < 8192; i++, offset += 8)
+ {
+ save->smiFont[i] = *(pSmi->FBBase + offset);
+ }
+
+ /* Now we save all the extended registers we need. */
+ save->SR17 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17);
+ save->SR18 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18);
+ save->SR21 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
+ save->SR31 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31);
+ save->SR32 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32);
+ save->SR6A = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A);
+ save->SR6B = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B);
+ save->SR81 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81);
+ save->SRA0 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0xA0);
+
+ if (SMI_LYNXM_SERIES(pSmi->Chipset))
+ {
+ /* Save primary registers */
+ save->CR90[14] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E);
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E,
+ save->CR90[14] & ~0x20);
+
+ for (i = 0; i < 16; i++)
+ {
+ save->CR90[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x90 + i);
+ }
+ save->CR33 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33);
+ save->CR3A = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A);
+ for (i = 0; i < 14; i++)
+ {
+ save->CR40[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i);
+ }
+
+ /* Save secondary registers */
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14] | 0x20);
+ save->CR33_2 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33);
+ for (i = 0; i < 14; i++)
+ {
+ save->CR40_2[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData,
+ 0x40 + i);
+ }
+ save->CR9F_2 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9F);
+
+ /* Save common registers */
+ for (i = 0; i < 14; i++)
+ {
+ save->CRA0[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0xA0 + i);
+ }
+
+ /* PDR#1069 */
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14]);
+ }
+ else
+ {
+ save->CR33 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33);
+ save->CR3A = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A);
+ for (i = 0; i < 14; i++)
+ {
+ save->CR40[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i);
+ }
+ }
+
+ /* CZ 2.11.2001: for gamma correction (TODO: other chipsets?) */
+ if (pSmi->Chipset == SMI_LYNX3DM) {
+ save->CCR66 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66);
+ }
+ /* end CZ */
+
+ save->DPR10 = READ_DPR(pSmi, 0x10);
+ save->DPR1C = READ_DPR(pSmi, 0x1C);
+ save->DPR20 = READ_DPR(pSmi, 0x20);
+ save->DPR24 = READ_DPR(pSmi, 0x24);
+ save->DPR28 = READ_DPR(pSmi, 0x28);
+ save->DPR2C = READ_DPR(pSmi, 0x2C);
+ save->DPR30 = READ_DPR(pSmi, 0x30);
+ save->DPR3C = READ_DPR(pSmi, 0x3C);
+ save->DPR40 = READ_DPR(pSmi, 0x40);
+ save->DPR44 = READ_DPR(pSmi, 0x44);
+
+ save->VPR00 = READ_VPR(pSmi, 0x00);
+ save->VPR0C = READ_VPR(pSmi, 0x0C);
+ save->VPR10 = READ_VPR(pSmi, 0x10);
+
+ save->CPR00 = READ_CPR(pSmi, 0x00);
+
+ if (!pSmi->ModeStructInit)
+ {
+ /* XXX Should check the return value of vgaHWCopyReg() */
+ vgaHWCopyReg(&hwp->ModeReg, vgaSavePtr);
+ memcpy(&pSmi->ModeReg, save, sizeof(SMIRegRec));
+ pSmi->ModeStructInit = TRUE;
+ }
+
+ if (pSmi->useBIOS && (pSmi->pInt10 != NULL))
+ {
+ pSmi->pInt10->num = 0x10;
+ pSmi->pInt10->ax = 0x0F00;
+ xf86ExecX86int10(pSmi->pInt10);
+ save->mode = pSmi->pInt10->ax & 0x007F;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Current mode 0x%02X.\n",
+ save->mode);
+ }
+
+ if (xf86GetVerbosity() > 1)
+ {
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "Saved current video mode. Register dump:\n");
+ SMI_PrintRegs(pScrn);
+ }
+
+ LEAVE_PROC("SMI_Save");
+}
+
+/*
+ * This function is used to restore a video mode. It writes out all of the
+ * standard VGA and extended registers needed to setup a video mode.
+ */
+
+static void
+SMI_WriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, SMIRegPtr restore)
+{
+ int i;
+ CARD8 tmp;
+ CARD32 offset;
+
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ SMIPtr pSmi = SMIPTR(pScrn);
+ int vgaIOBase = hwp->IOBase;
+ int vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET;
+ int vgaCRData = vgaIOBase + VGA_CRTC_DATA_OFFSET;
+
+ ENTER_PROC("SMI_WriteMode");
+
+ vgaHWProtect(pScrn, TRUE);
+
+ /* Wait for engine to become idle */
+ WaitIdle();
+
+ if (pSmi->useBIOS && (pSmi->pInt10 != NULL)
+ && (restore->mode != 0))
+ {
+ pSmi->pInt10->num = 0x10;
+ pSmi->pInt10->ax = restore->mode | 0x80;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode 0x%02X\n",
+ restore->mode);
+ xf86ExecX86int10(pSmi->pInt10);
+
+ /* Enable linear mode. */
+ outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
+ tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
+ outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x01);
+
+ /* Enable DPR/VPR registers. */
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, tmp & ~0x03);
+ }
+ else
+ {
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17, restore->SR17);
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18) & ~0x1F;
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18, tmp |
+ (restore->SR18 & 0x1F));
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, tmp & ~0x03);
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31) & ~0xC0;
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, tmp |
+ (restore->SR31 & 0xC0));
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32) & ~0x07;
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32, tmp |
+ (restore->SR32 & 0x07));
+ if (restore->SR6B != 0xFF)
+ {
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A,
+ restore->SR6A);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B,
+ restore->SR6B);
+ }
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, restore->SR81);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0xA0, restore->SRA0);
+
+ /* Restore the standard VGA registers */
+ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL);
+ if (restore->smiDACMask)
+ {
+ VGAOUT8(pSmi, VGA_DAC_MASK, restore->smiDACMask);
+ }
+ else
+ {
+ VGAOUT8(pSmi, VGA_DAC_MASK, 0xFF);
+ }
+ VGAOUT8(pSmi, VGA_DAC_WRITE_ADDR, 0);
+ for (i = 0; i < 256; i++)
+ {
+ VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][0]);
+ VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][1]);
+ VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][2]);
+ }
+ for (i = 0, offset = 2; i < 8192; i++, offset += 8)
+ {
+ *(pSmi->FBBase + offset) = restore->smiFont[i];
+ }
+
+ if (SMI_LYNXM_SERIES(pSmi->Chipset))
+ {
+ /* Restore secondary registers */
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E,
+ restore->CR90[14] | 0x20);
+
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33_2);
+ for (i = 0; i < 14; i++)
+ {
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i,
+ restore->CR40_2[i]);
+ }
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9F, restore->CR9F_2);
+
+ /* Restore primary registers */
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E,
+ restore->CR90[14] & ~0x20);
+
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33);
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A, restore->CR3A);
+ for (i = 0; i < 14; i++)
+ {
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i,
+ restore->CR40[i]);
+ }
+ for (i = 0; i < 16; i++)
+ {
+ if (i != 14)
+ {
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x90 + i,
+ restore->CR90[i]);
+ }
+ }
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, restore->CR90[14]);
+
+ /* Restore common registers */
+ for (i = 0; i < 14; i++)
+ {
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0xA0 + i,
+ restore->CRA0[i]);
+ }
+ }
+
+ /* Restore the standard VGA registers */
+ if (xf86IsPrimaryPci(pSmi->PciInfo)) {
+ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_CMAP
+ | VGA_SR_FONTS);
+ }
+
+ if (restore->modeInit)
+ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL);
+
+ if (!SMI_LYNXM_SERIES(pSmi->Chipset))
+ {
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33);
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A, restore->CR3A);
+ for (i = 0; i < 14; i++)
+ {
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i,
+ restore->CR40[i]);
+ }
+ }
+ }
+
+ /* CZ 2.11.2001: for gamma correction (TODO: other chipsets?) */
+ if (pSmi->Chipset == SMI_LYNX3DM) {
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66, restore->CCR66);
+ }
+ /* end CZ */
+
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, 0x00);
+
+ WRITE_DPR(pSmi, 0x10, restore->DPR10);
+ WRITE_DPR(pSmi, 0x1C, restore->DPR1C);
+ WRITE_DPR(pSmi, 0x20, restore->DPR20);
+ WRITE_DPR(pSmi, 0x24, restore->DPR24);
+ WRITE_DPR(pSmi, 0x28, restore->DPR28);
+ WRITE_DPR(pSmi, 0x2C, restore->DPR2C);
+ WRITE_DPR(pSmi, 0x30, restore->DPR30);
+ WRITE_DPR(pSmi, 0x3C, restore->DPR3C);
+ WRITE_DPR(pSmi, 0x40, restore->DPR40);
+ WRITE_DPR(pSmi, 0x44, restore->DPR44);
+
+ WRITE_VPR(pSmi, 0x00, restore->VPR00);
+ WRITE_VPR(pSmi, 0x0C, restore->VPR0C);
+ WRITE_VPR(pSmi, 0x10, restore->VPR10);
+
+ WRITE_CPR(pSmi, 0x00, restore->CPR00);
+
+ if (xf86GetVerbosity() > 1)
+ {
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "Done restoring mode. Register dump:\n");
+ SMI_PrintRegs(pScrn);
+ }
+
+ vgaHWProtect(pScrn, FALSE);
+
+ LEAVE_PROC("SMI_WriteMode");
+}
+
+static Bool
+SMI_MapMem(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ vgaHWPtr hwp;
+ CARD32 memBase;
+
+ ENTER_PROC("SMI_MapMem");
+
+ /* Map the Lynx register space */
+ switch (pSmi->Chipset)
+ {
+ default:
+ memBase = pSmi->PciInfo->memBase[0] + 0x400000;
+ pSmi->MapSize = 0x10000;
+ break;
+
+ case SMI_LYNX3D:
+ memBase = pSmi->PciInfo->memBase[0] + 0x680000;
+ pSmi->MapSize = 0x180000;
+ break;
+
+ case SMI_LYNXEM:
+ case SMI_LYNXEMplus:
+ memBase = pSmi->PciInfo->memBase[0] + 0x400000;
+ pSmi->MapSize = 0x400000;
+ break;
+
+ case SMI_LYNX3DM:
+ memBase = pSmi->PciInfo->memBase[0];
+ pSmi->MapSize = 0x200000;
+ break;
+ }
+ pSmi->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag,
+ memBase, pSmi->MapSize);
+
+ if (pSmi->MapBase == NULL)
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not map "
+ "MMIO registers.\n");
+ LEAVE_PROC("SMI_MapMem");
+ return(FALSE);
+ }
+
+ switch (pSmi->Chipset)
+ {
+ default:
+ pSmi->DPRBase = pSmi->MapBase + 0x8000;
+ pSmi->VPRBase = pSmi->MapBase + 0xC000;
+ pSmi->CPRBase = pSmi->MapBase + 0xE000;
+ pSmi->IOBase = NULL;
+ pSmi->DataPortBase = pSmi->MapBase;
+ pSmi->DataPortSize = 0x8000;
+ break;
+
+ case SMI_LYNX3D:
+ pSmi->DPRBase = pSmi->MapBase + 0x000000;
+ pSmi->VPRBase = pSmi->MapBase + 0x000800;
+ pSmi->CPRBase = pSmi->MapBase + 0x001000;
+ pSmi->IOBase = pSmi->MapBase + 0x040000;
+ pSmi->DataPortBase = pSmi->MapBase + 0x080000;
+ pSmi->DataPortSize = 0x100000;
+ break;
+
+ case SMI_LYNXEM:
+ case SMI_LYNXEMplus:
+ pSmi->DPRBase = pSmi->MapBase + 0x008000;
+ pSmi->VPRBase = pSmi->MapBase + 0x00C000;
+ pSmi->CPRBase = pSmi->MapBase + 0x00E000;
+ pSmi->IOBase = pSmi->MapBase + 0x300000;
+ pSmi->DataPortBase = pSmi->MapBase /*+ 0x100000*/;
+ pSmi->DataPortSize = 0x8000 /*0x200000*/;
+ break;
+
+ case SMI_LYNX3DM:
+ pSmi->DPRBase = pSmi->MapBase + 0x000000;
+ pSmi->VPRBase = pSmi->MapBase + 0x000800;
+ pSmi->CPRBase = pSmi->MapBase + 0x001000;
+ pSmi->IOBase = pSmi->MapBase + 0x0C0000;
+ pSmi->DataPortBase = pSmi->MapBase + 0x100000;
+ pSmi->DataPortSize = 0x100000;
+ break;
+ }
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "Physical MMIO at 0x%08X\n", memBase);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "Logical MMIO at 0x%08X - 0x%08X\n", pSmi->MapBase,
+ pSmi->MapBase + pSmi->MapSize - 1);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "DPR=0x%08X, VPR=0x%08X, IOBase=0x%08X\n", pSmi->DPRBase,
+ pSmi->VPRBase, pSmi->IOBase);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "DataPort=0x%08X - 0x%08X\n", pSmi->DataPortBase,
+ pSmi->DataPortBase + pSmi->DataPortSize - 1);
+
+ /* Map the frame buffer */
+ if (pSmi->Chipset == SMI_LYNX3DM)
+ {
+ pScrn->memPhysBase = pSmi->PciInfo->memBase[0] + 0x200000;
+ }
+ else
+ {
+ pScrn->memPhysBase = pSmi->PciInfo->memBase[0];
+ }
+ if (pSmi->videoRAMBytes)
+ {
+ pSmi->FBBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
+ pSmi->PciTag, pScrn->memPhysBase, pSmi->videoRAMBytes);
+
+ if (pSmi->FBBase == NULL)
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not "
+ "map framebuffer.\n");
+ LEAVE_PROC("SMI_MapMem");
+ return(FALSE);
+ }
+ }
+ pSmi->FBOffset = pScrn->fbOffset = 0;
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "Physical frame buffer at 0x%08X\n", pScrn->memPhysBase);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "Logical frame buffer at 0x%08X - 0x%08X\n", pSmi->FBBase,
+ pSmi->FBBase + pSmi->videoRAMBytes - 1);
+
+ SMI_EnableMmio(pScrn);
+
+ /* Set up offset to hwcursor memory area. It's a 1K chunk at the end of
+ * the frame buffer. Also set up the reserved memory space.
+ */
+ pSmi->FBCursorOffset = pSmi->videoRAMBytes - 1024;
+ if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x01)/* #1074 */
+ {
+ CARD32 fifoOffset = 0;
+ fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x46)
+ << 3;
+ fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x47)
+ << 11;
+ fifoOffset |= (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x49)
+ & 0x1C) << 17;
+ pSmi->FBReserved = fifoOffset; /* PDR#1074 */
+ }
+ else
+ {
+ pSmi->FBReserved = pSmi->videoRAMBytes - 2048;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Cursor Offset: %08X Reserved: %08X\n",
+ pSmi->FBCursorOffset, pSmi->FBReserved);
+
+ pSmi->lcd = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31) & 0x01;
+ if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x01)
+ {
+ pSmi->lcd <<= 1;
+ }
+ switch (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x0C)
+ {
+ case 0x00:
+ pSmi->lcdWidth = 640;
+ pSmi->lcdHeight = 480;
+ break;
+
+ case 0x04:
+ pSmi->lcdWidth = 800;
+ pSmi->lcdHeight = 600;
+ break;
+
+ case 0x08:
+ if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x74) & 0x02)
+ {
+ pSmi->lcdWidth = 1024;
+ pSmi->lcdHeight = 600;
+ }
+ else
+ {
+ pSmi->lcdWidth = 1024;
+ pSmi->lcdHeight = 768;
+ }
+ break;
+
+ case 0x0C:
+ pSmi->lcdWidth = 1280;
+ pSmi->lcdHeight = 1024;
+ break;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Panel Size = %dx%d\n",
+ (pSmi->lcd == 0) ? "OFF" : (pSmi->lcd == 1) ? "TFT" : "DSTN",
+ pSmi->lcdWidth, pSmi->lcdHeight);
+
+ /* Assign hwp->MemBase & IOBase here */
+ hwp = VGAHWPTR(pScrn);
+ if (pSmi->IOBase != NULL)
+ {
+ vgaHWSetMmioFuncs(hwp, pSmi->MapBase, pSmi->IOBase - pSmi->MapBase);
+ }
+ vgaHWGetIOBase(hwp);
+
+ /* Map the VGA memory when the primary video */
+ if (xf86IsPrimaryPci(pSmi->PciInfo))
+ {
+ hwp->MapSize = 0x10000;
+ if (!vgaHWMapMem(pScrn))
+ {
+ LEAVE_PROC("SMI_MapMem");
+ return(FALSE);
+ }
+ pSmi->PrimaryVidMapped = TRUE;
+ }
+
+ LEAVE_PROC("SMI_MapMem");
+ return(TRUE);
+}
+
+/* UnMapMem - contains half of pre-4.0 EnterLeave function. The EnterLeave
+ * function which en/disable access to IO ports and ext. regs
+ */
+
+static void
+SMI_UnmapMem(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_UnmapMem");
+
+ /* Unmap VGA mem if mapped. */
+ if (pSmi->PrimaryVidMapped)
+ {
+ vgaHWUnmapMem(pScrn);
+ pSmi->PrimaryVidMapped = FALSE;
+ }
+
+ SMI_DisableMmio(pScrn);
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pSmi->MapBase, pSmi->MapSize);
+ if (pSmi->FBBase != NULL)
+ {
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pSmi->FBBase,
+ pSmi->videoRAMBytes);
+ }
+
+ LEAVE_PROC("SMI_UnmapMem");
+}
+
+/* This gets called at the start of each server generation. */
+
+static Bool
+SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ SMIPtr pSmi = SMIPTR(pScrn);
+ EntityInfoPtr pEnt;
+
+ ENTER_PROC("SMI_ScreenInit");
+
+ /* Map MMIO regs and framebuffer */
+ if (!SMI_MapMem(pScrn))
+ {
+ LEAVE_PROC("SMI_ScreenInit");
+ return(FALSE);
+ }
+
+ pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+
+ if (!pSmi->pInt10) {
+ pSmi->pInt10 = xf86InitInt10(pEnt->index);
+ }
+
+ /* Save the chip/graphics state */
+ SMI_Save(pScrn);
+
+ /* Zero the frame buffer, #258 */
+ memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
+
+ /* Initialize the first mode */
+ if (!SMI_ModeInit(pScrn, pScrn->currentMode))
+ {
+ LEAVE_PROC("SMI_ScreenInit");
+ return(FALSE);
+ }
+
+ /*
+ * The next step is to setup the screen's visuals, and initialise the
+ * framebuffer code. In cases where the framebuffer's default choises 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 the 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. To deal with this, call
+ * miSetVisualTypes with the appropriate visual mask.
+ */
+#ifndef USE_FB
+ if (pScrn->bitsPerPixel > 8)
+ {
+ if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits,
+ pScrn->defaultVisual))
+ {
+ LEAVE_PROC("SMI_ScreenInit");
+ return(FALSE);
+ }
+ }
+ else
+#endif
+ {
+ if (!miSetVisualTypes(pScrn->depth,
+ miGetDefaultVisualMask(pScrn->depth), pScrn->rgbBits,
+ pScrn->defaultVisual))
+ {
+ LEAVE_PROC("SMI_ScreenInit");
+ return(FALSE);
+ }
+ }
+#ifdef USE_FB
+ if (!miSetPixmapDepths ()) return FALSE;
+#endif
+
+ if (!SMI_InternalScreenInit(scrnIndex, pScreen))
+ {
+ LEAVE_PROC("SMI_ScreenInit");
+ return(FALSE);
+ }
+
+ xf86SetBlackWhitePixels(pScreen);
+
+ if (pScrn->bitsPerPixel > 8)
+ {
+ VisualPtr visual;
+ /* 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;
+ }
+ }
+ }
+
+#ifdef USE_FB
+ /* must be after RGB ordering fixed */
+ fbPictureInit(pScreen, 0, 0);
+#endif
+
+ /* CZ 18.06.2001: moved here from smi_accel.c to have offscreen
+ framebuffer in NoAccel mode */
+ {
+ int numLines, maxLines;
+ BoxRec AvailFBArea;
+
+ maxLines = pSmi->FBReserved / (pSmi->width * pSmi->Bpp);
+ if (pSmi->rotate) {
+ numLines = maxLines;
+ } else {
+ /* CZ 3.11.2001: What does the following code? see also smi_video.c aaa line 1226 */
+/*#if defined(XvExtension) && SMI_USE_VIDEO */
+#if 0
+ numLines = ((pSmi->FBReserved - pSmi->width * pSmi->Bpp
+ * pSmi->height) * 25 / 100 + pSmi->width
+ * pSmi->Bpp - 1) / (pSmi->width * pSmi->Bpp);
+ numLines += pSmi->height;
+#else
+ numLines = maxLines;
+#endif
+ }
+
+ AvailFBArea.x1 = 0;
+ AvailFBArea.y1 = 0;
+ AvailFBArea.x2 = pSmi->width;
+ AvailFBArea.y2 = numLines;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "FrameBuffer Box: %d,%d - %d,%d\n",
+ AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2,
+ AvailFBArea.y2);
+ xf86InitFBManager(pScreen, &AvailFBArea);
+ }
+ /* end CZ */
+
+
+ /* Initialize acceleration layer */
+ if (!pSmi->NoAccel) {
+ if (!SMI_AccelInit(pScreen)) {
+ LEAVE_PROC("SMI_ScreenInit");
+ return(FALSE);
+ }
+ }
+
+ miInitializeBackingStore(pScreen);
+
+ /* hardware cursor needs to wrap this layer */
+ SMI_DGAInit(pScreen);
+
+ /* Initialise cursor functions */
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ /* Initialize HW cursor layer. Must follow software cursor
+ * initialization.
+ */
+ if (pSmi->hwcursor)
+ {
+ if (!SMI_HWCursorInit(pScreen))
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Hardware cursor "
+ "initialization failed\n");
+ }
+ }
+
+ if (pSmi->shadowFB)
+ {
+ RefreshAreaFuncPtr refreshArea = SMI_RefreshArea;
+
+ if (pSmi->rotate)
+ {
+ if (pSmi->PointerMoved == NULL)
+ {
+ pSmi->PointerMoved = pScrn->PointerMoved;
+ pScrn->PointerMoved = SMI_PointerMoved;
+ }
+ }
+
+ ShadowFBInit(pScreen, refreshArea);
+ }
+
+ /* Initialise default colormap */
+ if (!miCreateDefColormap(pScreen))
+ {
+ LEAVE_PROC("SMI_ScreenInit");
+ return(FALSE);
+ }
+
+ /* Initialize colormap layer. Must follow initialization of the default
+ * colormap. And SetGamma call, else it will load palette with solid white.
+ */
+ /* CZ 2.11.2001: CMAP_PALETTED_TRUECOLOR for gamma correction */
+ if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, SMI_LoadPalette, NULL,
+ CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR))
+ {
+ LEAVE_PROC("SMI_ScreenInit");
+ return(FALSE);
+ }
+
+ pScreen->SaveScreen = SMI_SaveScreen;
+ pSmi->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = SMI_CloseScreen;
+
+ if (!xf86DPMSInit(pScreen, SMI_DisplayPowerManagementSet, 0))
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n");
+ }
+
+ SMI_InitVideo(pScreen);
+
+ /* Report any unused options (only for the first generation) */
+ if (serverGeneration == 1)
+ {
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+ }
+
+ LEAVE_PROC("SMI_ScreenInit");
+ return(TRUE);
+}
+
+/* Common init routines needed in EnterVT and ScreenInit */
+
+static int
+SMI_InternalScreenInit(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ SMIPtr pSmi = SMIPTR(pScrn);
+ int width, height, displayWidth;
+ int bytesPerPixel = pScrn->bitsPerPixel / 8;
+ int xDpi, yDpi;
+ int ret;
+
+ ENTER_PROC("SMI_InternalScreenInit");
+
+ if (pSmi->rotate)
+ {
+ width = pScrn->virtualY;
+ height = pScrn->virtualX;
+ xDpi = pScrn->yDpi;
+ yDpi = pScrn->xDpi;
+ displayWidth = ((width * bytesPerPixel + 15) & ~15) / bytesPerPixel;
+ }
+ else
+ {
+ width = pScrn->virtualX;
+ height = pScrn->virtualY;
+ xDpi = pScrn->xDpi;
+ yDpi = pScrn->yDpi;
+ displayWidth = pScrn->displayWidth;
+ }
+
+ if (pSmi->shadowFB)
+ {
+ pSmi->ShadowWidth = width;
+ pSmi->ShadowHeight = height;
+ pSmi->ShadowWidthBytes = (width * bytesPerPixel + 15) & ~15;
+ if (bytesPerPixel == 3)
+ {
+ pSmi->ShadowPitch = ((height * 3) << 16)
+ | pSmi->ShadowWidthBytes;
+ }
+ else
+ {
+ pSmi->ShadowPitch = (height << 16)
+ | (pSmi->ShadowWidthBytes / bytesPerPixel);
+ }
+
+ pSmi->saveBufferSize = pSmi->ShadowWidthBytes * pSmi->ShadowHeight;
+ pSmi->FBReserved -= pSmi->saveBufferSize;
+ pSmi->FBReserved &= ~0x15;
+ WRITE_VPR(pSmi, 0x0C, (pSmi->FBOffset = pSmi->FBReserved) >> 3);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Shadow: width=%d height=%d "
+ "offset=0x%08X pitch=0x%08X\n", pSmi->ShadowWidth,
+ pSmi->ShadowHeight, pSmi->FBOffset, pSmi->ShadowPitch);
+ }
+ else
+ {
+ pSmi->FBOffset = 0;
+ }
+
+ /*
+ * Call the framebuffer layer's ScreenInit function, and fill in other
+ * pScreen fields.
+ */
+
+ DEBUG((VERBLEV, "\tInitializing FB @ 0x%08X for %dx%d (%d)\n",
+ pSmi->FBBase, width, height, displayWidth));
+ switch (pScrn->bitsPerPixel)
+ {
+#ifdef USE_FB
+ case 8:
+ case 16:
+ case 24:
+ ret = fbScreenInit(pScreen, pSmi->FBBase, width, height, xDpi,
+ yDpi, displayWidth,pScrn->bitsPerPixel);
+ break;
+#else
+ case 8:
+ ret = cfbScreenInit(pScreen, pSmi->FBBase, width, height, xDpi,
+ yDpi, displayWidth);
+ break;
+
+ case 16:
+ ret = cfb16ScreenInit(pScreen, pSmi->FBBase, width, height, xDpi,
+ yDpi, displayWidth);
+ break;
+
+ case 24:
+ ret = cfb24ScreenInit(pScreen, pSmi->FBBase, width, height, xDpi,
+ yDpi, displayWidth);
+ break;
+#endif
+ default:
+ xf86DrvMsg(scrnIndex, X_ERROR, "Internal error: invalid bpp (%d) "
+ "in SMI_InternalScreenInit\n", pScrn->bitsPerPixel);
+ LEAVE_PROC("SMI_InternalScreenInit");
+ return(FALSE);
+ }
+
+ LEAVE_PROC("SMI_InternalScreenInit");
+ return(ret);
+}
+
+/* Checks if a mode is suitable for the selected configuration. */
+static ModeStatus
+SMI_ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ SMIPtr pSmi = SMIPTR(pScrn);
+ float refresh;
+
+ ENTER_PROC("SMI_ValidMode");
+ refresh = (mode->VRefresh > 0) ? mode->VRefresh
+ : mode->Clock * 1000.0 / mode->VTotal / mode->HTotal;
+ xf86DrvMsg(scrnIndex, X_INFO, "Mode: %dx%d %d-bpp, %fHz\n", mode->HDisplay,
+ mode->VDisplay, pScrn->bitsPerPixel, refresh);
+
+ if (pSmi->shadowFB)
+ {
+ int mem;
+
+ if (pScrn->bitsPerPixel == 24)
+ {
+ LEAVE_PROC("SMI_ValidMode");
+ return(MODE_BAD);
+ }
+
+ mem = (pScrn->virtualX * pScrn->bitsPerPixel / 8 + 15) & ~15;
+ mem *= pScrn->virtualY * 2;
+
+ if (mem > pSmi->FBReserved) /* PDR#1074 */
+ {
+ LEAVE_PROC("SMI_ValidMode");
+ return(MODE_MEM);
+ }
+ }
+
+ if (!pSmi->useBIOS || pSmi->lcd)
+ {
+#if 1 /* PDR#983 */
+ if (pSmi->zoomOnLCD)
+ {
+ if ( (mode->HDisplay > pSmi->lcdWidth)
+ || (mode->VDisplay > pSmi->lcdHeight)
+ )
+ {
+ LEAVE_PROC("SMI_ValidMode");
+ return(MODE_PANEL);
+ }
+ }
+ else
+#endif
+ {
+ if ( (mode->HDisplay != pSmi->lcdWidth)
+ || (mode->VDisplay != pSmi->lcdHeight)
+ )
+ {
+ LEAVE_PROC("SMI_ValidMode");
+ return(MODE_PANEL);
+ }
+ }
+
+ }
+
+#if 1 /* PDR#944 */
+ if (pSmi->rotate)
+ {
+ if ( (mode->HDisplay != pSmi->lcdWidth)
+ || (mode->VDisplay != pSmi->lcdHeight)
+ )
+ {
+ LEAVE_PROC("SMI_ValidMode");
+ return(MODE_PANEL);
+ }
+ }
+#endif
+
+ LEAVE_PROC("SMI_ValidMode");
+ return(MODE_OK);
+}
+
+static Bool
+SMI_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ SMIPtr pSmi = SMIPTR(pScrn);
+ unsigned char tmp;
+ int panelIndex, modeIndex, i;
+ int xyAddress[] = { 320, 400, 512, 640, 800, 1024, 1280, 1600, 2048 };
+ CARD32 DEDataFormat = 0;
+
+ /* Store values to current mode register structs */
+ SMIRegPtr new = &pSmi->ModeReg;
+ vgaRegPtr vganew = &hwp->ModeReg;
+
+ ENTER_PROC("SMI_ModeInit");
+
+ if(!vgaHWInit(pScrn, mode))
+ {
+ LEAVE_PROC("SMI_ModeInit");
+ return(FALSE);
+ }
+
+ new->modeInit = TRUE;
+
+ if (pSmi->rotate)
+ {
+ pSmi->width = pScrn->virtualY;
+ pSmi->height = pScrn->virtualX;
+ }
+ else
+ {
+ pSmi->width = pScrn->virtualX;
+ pSmi->height = pScrn->virtualY;
+ }
+ pSmi->Bpp = pScrn->bitsPerPixel / 8;
+
+ outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x17);
+ tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
+ if (pSmi->pci_burst)
+ {
+ new->SR17 = tmp | 0x20;
+ }
+ else
+ {
+ new->SR17 = tmp & ~0x20;
+ }
+
+ outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
+ new->SR18 = inb(pSmi->PIOBase + VGA_SEQ_DATA) | 0x11;
+
+ outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
+ new->SR21 = inb(pSmi->PIOBase + VGA_SEQ_DATA) & ~0x03;
+
+ outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x31);
+ new->SR31 = inb(pSmi->PIOBase + VGA_SEQ_DATA) & ~0xC0;
+
+ outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x32);
+ new->SR32 = inb(pSmi->PIOBase + VGA_SEQ_DATA) & ~0x07;
+ if (SMI_LYNXM_SERIES(pSmi->Chipset))
+ {
+ new->SR32 |= 0x04;
+ }
+
+ new->SRA0 = new->CR33 = new->CR3A = 0x00;
+
+ if (pSmi->lcdWidth == 640)
+ {
+ panelIndex = 0;
+ }
+ else if (pSmi->lcdWidth == 800)
+ {
+ panelIndex = 1;
+ }
+ else
+ {
+ panelIndex = 2;
+ }
+
+ if (mode->HDisplay == 640)
+ {
+ modeIndex = 0;
+ }
+ else if (mode->HDisplay == 800)
+ {
+ modeIndex = 1;
+ }
+ else
+ {
+ modeIndex = 2;
+ }
+
+ if (SMI_LYNXM_SERIES(pSmi->Chipset))
+ {
+ static unsigned char PanelTable[3][14] =
+ {
+ { 0x5F, 0x4F, 0x00, 0x52, 0x1E, 0x0B, 0xDF, 0x00, 0xE9, 0x0B, 0x2E,
+ 0x00, 0x4F, 0xDF },
+ { 0x7F, 0x63, 0x00, 0x69, 0x19, 0x72, 0x57, 0x00, 0x58, 0x0C, 0xA2,
+ 0x20, 0x4F, 0xDF },
+ { 0xA3, 0x7F, 0x00, 0x83, 0x14, 0x24, 0xFF, 0x00, 0x02, 0x08, 0xA7,
+ 0xE0, 0x4F, 0xDF },
+ };
+
+ for (i = 0; i < 14; i++)
+ {
+ new->CR40[i] = PanelTable[panelIndex][i];
+ }
+ new->CR90[14] = 0x03;
+ new->CR90[15] = 0x00;
+ if (mode->VDisplay < pSmi->lcdHeight)
+ {
+ new->CRA0[6] = (pSmi->lcdHeight - mode->VDisplay) / 8;
+ }
+ else
+ {
+ new->CRA0[6] = 0;
+ }
+
+ if (mode->HDisplay < pSmi->lcdWidth)
+ {
+ new->CRA0[7] = (pSmi->lcdWidth - mode->HDisplay) / 16;
+ }
+ else
+ {
+ new->CRA0[7] = 0;
+ }
+ }
+ else
+ {
+ static unsigned char PanelTable[3][3][14] =
+ {
+ { /* 640x480 panel */
+ { 0x5F, 0x4F, 0x00, 0x53, 0x00, 0x0B, 0xDF, 0x00, 0xEA, 0x0C,
+ 0x2E, 0x00, 0x4F, 0xDF },
+ { 0x5F, 0x4F, 0x00, 0x53, 0x00, 0x0B, 0xDF, 0x00, 0xEA, 0x0C,
+ 0x2E, 0x00, 0x4F, 0xDF },
+ { 0x5F, 0x4F, 0x00, 0x53, 0x00, 0x0B, 0xDF, 0x00, 0xEA, 0x0C,
+ 0x2E, 0x00, 0x4F, 0xDF },
+ },
+ { /* 800x600 panel */
+ { 0x7F, 0x59, 0x19, 0x5E, 0x8E, 0x72, 0x1C, 0x37, 0x1D, 0x00,
+ 0xA2, 0x20, 0x4F, 0xDF },
+ { 0x7F, 0x63, 0x00, 0x68, 0x18, 0x72, 0x58, 0x00, 0x59, 0x0C,
+ 0xE0, 0x20, 0x63, 0x57 },
+ { 0x7F, 0x63, 0x00, 0x68, 0x18, 0x72, 0x58, 0x00, 0x59, 0x0C,
+ 0xE0, 0x20, 0x63, 0x57 },
+ },
+ { /* 1024x768 panel */
+ { 0xA3, 0x67, 0x0F, 0x6D, 0x1D, 0x24, 0x70, 0x95, 0x72, 0x07,
+ 0xA3, 0x20, 0x4F, 0xDF },
+ { 0xA3, 0x71, 0x19, 0x77, 0x07, 0x24, 0xAC, 0xD1, 0xAE, 0x03,
+ 0xE1, 0x20, 0x63, 0x57 },
+ { 0xA3, 0x7F, 0x00, 0x85, 0x15, 0x24, 0xFF, 0x00, 0x01, 0x07,
+ 0xE5, 0x20, 0x7F, 0xFF },
+ },
+ };
+
+ for (i = 0; i < 14; i++)
+ {
+ new->CR40[i] = PanelTable[panelIndex][modeIndex][i];
+ }
+ }
+
+ /* CZ 2.11.2001: for gamma correction (TODO: other chipsets?) */
+ new->CCR66 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66);
+ if (pSmi->Chipset == SMI_LYNX3DM) {
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ new->CCR66 = (new->CCR66 & 0xF3) | 0x00; /* 6 bits-RAM */
+ break;
+ case 16:
+ new->CCR66 = (new->CCR66 & 0xF3) | 0x00; /* 6 bits-RAM */
+ /* no Gamma correction in 16 Bit mode (s. Release.txt 1.3.1) */
+ break;
+ case 24:
+ case 32:
+ new->CCR66 = (new->CCR66 & 0xF3) | 0x04; /* Gamma correct ON */
+ break;
+ default:
+ LEAVE_PROC("SMI_ModeInit");
+ return(FALSE);
+ }
+ }
+
+ outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x30);
+ if (inb(pSmi->PIOBase + VGA_SEQ_DATA) & 0x01)
+ {
+ new->SR21 = 0x00;
+ }
+
+ if (pSmi->MCLK > 0)
+ {
+ SMI_CommonCalcClock(pScrn->scrnIndex,pSmi->MCLK,
+ 1, 1, 31, 0, 2, pSmi->minClock,
+ pSmi->maxClock, &new->SR6A, &new->SR6B);
+ }
+ else
+ {
+ new->SR6B = 0xFF;
+ }
+
+ if ((mode->HDisplay == 640) && SMI_LYNXM_SERIES(pSmi->Chipset))
+ {
+ vganew->MiscOutReg &= ~0x0C;
+ }
+ else
+ {
+ vganew->MiscOutReg |= 0x0C;
+ }
+ vganew->MiscOutReg |= 0xE0;
+ if (mode->HDisplay == 800)
+ {
+ vganew->MiscOutReg &= ~0xC0;
+ }
+ if ((mode->HDisplay == 1024) && SMI_LYNXM_SERIES(pSmi->Chipset))
+ {
+ vganew->MiscOutReg &= ~0xC0;
+ }
+
+ /* Set DPR registers */
+ pSmi->Stride = (pSmi->width * pSmi->Bpp + 15) & ~15;
+ switch (pScrn->bitsPerPixel)
+ {
+ case 8:
+ DEDataFormat = 0x00000000;
+ break;
+
+ case 16:
+ pSmi->Stride >>= 1;
+ DEDataFormat = 0x00100000;
+ break;
+
+ case 24:
+ DEDataFormat = 0x00300000;
+ break;
+
+ case 32:
+ pSmi->Stride >>= 2;
+ DEDataFormat = 0x00200000;
+ break;
+ }
+ for (i = 0; i < sizeof(xyAddress) / sizeof(xyAddress[0]); i++)
+ {
+ if (pSmi->rotate)
+ {
+ if (xyAddress[i] == pSmi->height)
+ {
+ DEDataFormat |= i << 16;
+ break;
+ }
+ }
+ else
+ {
+ if (xyAddress[i] == pSmi->width)
+ {
+ DEDataFormat |= i << 16;
+ break;
+ }
+ }
+ }
+ new->DPR10 = (pSmi->Stride << 16) | pSmi->Stride;
+ new->DPR1C = DEDataFormat;
+ new->DPR20 = 0;
+ new->DPR24 = 0xFFFFFFFF;
+ new->DPR28 = 0xFFFFFFFF;
+ new->DPR2C = 0;
+ new->DPR30 = 0;
+ new->DPR3C = (pSmi->Stride << 16) | pSmi->Stride;
+ new->DPR40 = 0;
+ new->DPR44 = 0;
+
+ /* Set VPR registers */
+ switch (pScrn->bitsPerPixel)
+ {
+ case 8:
+ new->VPR00 = 0x00000000;
+ break;
+
+ case 16:
+ new->VPR00 = 0x00020000;
+ break;
+
+ case 24:
+ new->VPR00 = 0x00040000;
+ break;
+
+ case 32:
+ new->VPR00 = 0x00030000;
+ break;
+ }
+ new->VPR0C = pSmi->FBOffset >> 3;
+ if (pSmi->rotate)
+ {
+ new->VPR10 = ((((min(pSmi->lcdWidth, pSmi->height) * pSmi->Bpp) >> 3)
+ + 2) << 16) | ((pSmi->height * pSmi->Bpp) >> 3);
+ }
+ else
+ {
+ new->VPR10 = ((((min(pSmi->lcdWidth, pSmi->width) * pSmi->Bpp) >> 3)
+ + 2) << 16) | ((pSmi->width * pSmi->Bpp) >> 3);
+ }
+
+ /* Set CPR registers */
+ new->CPR00 = 0x00000000;
+
+ pScrn->vtSema = TRUE;
+
+ /* Find the INT 10 mode number */
+ {
+ static struct
+ {
+ int x, y, bpp;
+ CARD16 mode;
+
+ } modeTable[] =
+ {
+ { 640, 480, 8, 0x50 },
+ { 640, 480, 16, 0x52 },
+ { 640, 480, 24, 0x53 },
+ { 640, 480, 32, 0x54 },
+ { 800, 600, 8, 0x55 },
+ { 800, 600, 16, 0x57 },
+ { 800, 600, 24, 0x58 },
+ { 800, 600, 32, 0x59 },
+ { 1024, 768, 8, 0x60 },
+ { 1024, 768, 16, 0x62 },
+ { 1024, 768, 24, 0x63 },
+ { 1024, 768, 32, 0x64 },
+ { 1280, 1024, 8, 0x65 },
+ { 1280, 1024, 16, 0x67 },
+ { 1280, 1024, 24, 0x68 },
+ { 1280, 1024, 32, 0x69 },
+ };
+
+ new->mode = 0;
+ for (i = 0; i < sizeof(modeTable) / sizeof(modeTable[0]); i++)
+ {
+ if ( (modeTable[i].x == mode->HDisplay)
+ && (modeTable[i].y == mode->VDisplay)
+ && (modeTable[i].bpp == pScrn->bitsPerPixel)
+ )
+ {
+ new->mode = modeTable[i].mode;
+ break;
+ }
+ }
+ }
+
+ /* Zero the font memory */
+ memset(new->smiFont, 0, sizeof(new->smiFont));
+
+ /* Write the mode registers to hardware */
+ SMI_WriteMode(pScrn, vganew, new);
+
+ /* Adjust the viewport */
+ SMI_AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ LEAVE_PROC("SMI_ModeInit");
+ return(TRUE);
+}
+
+/*
+ * This is called at the end of each server generation. It restores the
+ * original (text) mode. It should also unmap the video memory, and free any
+ * per-generation data allocated by the driver. It should finish by unwrapping
+ * and calling the saved CloseScreen function.
+ */
+
+static Bool
+SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ SMIPtr pSmi = SMIPTR(pScrn);
+ vgaRegPtr vgaSavePtr = &hwp->SavedReg;
+ SMIRegPtr SMISavePtr = &pSmi->SavedReg;
+ Bool ret;
+
+ ENTER_PROC("SMI_CloseScreen");
+
+ if (pScrn->vtSema)
+ {
+ SMI_WriteMode(pScrn, vgaSavePtr, SMISavePtr);
+ vgaHWLock(hwp);
+ SMI_UnmapMem(pScrn);
+ }
+
+ if (pSmi->AccelInfoRec != NULL)
+ {
+ XAADestroyInfoRec(pSmi->AccelInfoRec);
+ }
+ if (pSmi->CursorInfoRec != NULL)
+ {
+ xf86DestroyCursorInfoRec(pSmi->CursorInfoRec);
+ }
+ if (pSmi->DGAModes != NULL)
+ {
+ xfree(pSmi->DGAModes);
+ }
+ if (pSmi->pInt10 != NULL)
+ {
+ xf86FreeInt10(pSmi->pInt10);
+ pSmi->pInt10 = NULL;
+ }
+#ifdef XvExtension
+ if (pSmi->ptrAdaptor != NULL)
+ {
+ xfree(pSmi->ptrAdaptor);
+ }
+ if (pSmi->BlockHandler != NULL)
+ {
+ pScreen->BlockHandler = pSmi->BlockHandler;
+ }
+#endif
+ if (pSmi->I2C != NULL)
+ {
+ xf86DestroyI2CBusRec(pSmi->I2C, FALSE, TRUE);
+ xfree(pSmi->I2C);
+ pSmi->I2C = NULL;
+ }
+ /* #670 */
+ if (pSmi->pSaveBuffer)
+ {
+ xfree(pSmi->pSaveBuffer);
+ }
+ /* #920 */
+ if (pSmi->paletteBuffer)
+ {
+ xfree(pSmi->paletteBuffer);
+ }
+
+ pScrn->vtSema = FALSE;
+ pScreen->CloseScreen = pSmi->CloseScreen;
+ ret = (*pScreen->CloseScreen)(scrnIndex, pScreen);
+
+ LEAVE_PROC("SMI_CloseScreen");
+ return(ret);
+}
+
+static void
+SMI_FreeScreen(int scrnIndex, int flags)
+{
+ SMI_FreeRec(xf86Screens[scrnIndex]);
+}
+
+static Bool
+SMI_SaveScreen(ScreenPtr pScreen, int mode)
+{
+ Bool ret;
+
+ ENTER_PROC("SMI_SaveScreen");
+
+ ret = vgaHWSaveScreen(pScreen, mode);
+
+ LEAVE_PROC("SMI_SaveScreen");
+ return(ret);
+}
+
+void
+SMI_AdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ SMIPtr pSmi = SMIPTR(pScrn);
+ CARD32 Base;
+
+ ENTER_PROC("SMI_AdjustFrame");
+
+ if (pSmi->ShowCache && y)
+ {
+ y += pScrn->virtualY - 1;
+ }
+
+ Base = pSmi->FBOffset + (x + y * pScrn->virtualX) * pSmi->Bpp;
+ if (SMI_LYNX3D_SERIES(pSmi->Chipset))
+ {
+ Base = (Base + 15) & ~15;
+#if 1 /* PDR#1058 */
+ while ((Base % pSmi->Bpp) > 0)
+ {
+ Base -= 16;
+ }
+#endif
+ }
+ else
+ {
+ Base = (Base + 7) & ~7;
+#if 1 /* PDR#1058 */
+ while ((Base % pSmi->Bpp) > 0)
+ {
+ Base -= 8;
+ }
+#endif
+ }
+
+ WRITE_VPR(pSmi, 0x0C, Base >> 3);
+
+ LEAVE_PROC("SMI_AdjustFrame");
+}
+
+Bool
+SMI_SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ Bool ret;
+
+ ENTER_PROC("SMI_SwitchMode");
+
+ ret = SMI_ModeInit(xf86Screens[scrnIndex], mode);
+
+ LEAVE_PROC("SMI_SwitchMode");
+ return(ret);
+}
+
+void
+SMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, LOCO *colors,
+ VisualPtr pVisual)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ int i;
+
+ ENTER_PROC("SMI_LoadPalette");
+
+ for(i = 0; i < numColors; i++)
+ {
+ DEBUG((VERBLEV, "pal[%d] = %d %d %d\n", indicies[i],
+ colors[indicies[i]].red, colors[indicies[i]].green, colors[indicies[i]].blue));
+ VGAOUT8(pSmi, VGA_DAC_WRITE_ADDR, indicies[i]);
+ VGAOUT8(pSmi, VGA_DAC_DATA, colors[indicies[i]].red);
+ VGAOUT8(pSmi, VGA_DAC_DATA, colors[indicies[i]].green);
+ VGAOUT8(pSmi, VGA_DAC_DATA, colors[indicies[i]].blue);
+ }
+
+ LEAVE_PROC("SMI_LoadPalette");
+}
+
+static void
+SMI_DisableVideo(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ CARD8 tmp;
+
+ if (!(tmp = VGAIN8(pSmi, VGA_DAC_MASK)))
+ return;
+ pSmi->DACmask = tmp;
+ VGAOUT8(pSmi, VGA_DAC_MASK, 0);
+}
+
+static void
+SMI_EnableVideo(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ VGAOUT8(pSmi, VGA_DAC_MASK, pSmi->DACmask);
+}
+
+
+void
+SMI_EnableMmio(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ SMIPtr pSmi = SMIPTR(pScrn);
+ CARD8 tmp;
+
+ ENTER_PROC("SMI_EnableMmio");
+
+ /*
+ * Enable chipset (seen on uninitialized secondary cards) might not be
+ * needed once we use the VGA softbooter
+ */
+ vgaHWSetStdFuncs(hwp);
+
+ /* Enable linear mode */
+ outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
+ tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
+ pSmi->SR18Value = tmp; /* PDR#521 */
+ outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x11);
+
+ /* Enable 2D/3D Engine and Video Processor */
+ outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
+ tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
+ pSmi->SR21Value = tmp; /* PDR#521 */
+ outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp & ~0x03);
+
+ LEAVE_PROC("SMI_EnableMmio");
+}
+
+void
+SMI_DisableMmio(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_DisableMmio");
+
+ vgaHWSetStdFuncs(hwp);
+
+ /* Disable 2D/3D Engine and Video Processor */
+ outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
+ outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR21Value); /* PDR#521 */
+
+ /* Disable linear mode */
+ outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
+ outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR18Value); /* PDR#521 */
+
+ LEAVE_PROC("SMI_DisableMmio");
+}
+
+/* This function is used to debug, it prints out the contents of Lynx regs */
+static void
+SMI_PrintRegs(ScrnInfoPtr pScrn)
+{
+ unsigned char i, tmp;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ SMIPtr pSmi = SMIPTR(pScrn);
+ int vgaCRIndex = hwp->IOBase + VGA_CRTC_INDEX_OFFSET;
+ int vgaCRReg = hwp->IOBase + VGA_CRTC_DATA_OFFSET;
+ int vgaStatus = hwp->IOBase + VGA_IN_STAT_1_OFFSET;
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "START register dump ------------------\n");
+
+ xf86ErrorFVerb(VERBLEV, "MISCELLANEOUS OUTPUT\n %02X\n",
+ VGAIN8(pSmi, VGA_MISC_OUT_R));
+
+ xf86ErrorFVerb(VERBLEV, "\nSEQUENCER\n"
+ " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF");
+ for (i = 0x00; i <= 0xAF; i++)
+ {
+ if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
+ if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
+ xf86ErrorFVerb(VERBLEV, "%02X ",
+ VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, i));
+ }
+
+ xf86ErrorFVerb(VERBLEV, "\n\nCRT CONTROLLER\n"
+ " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF");
+ for (i = 0x00; i <= 0xAD; i++)
+ {
+ if (i == 0x20) i = 0x30;
+ if (i == 0x50) i = 0x90;
+ if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
+ if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
+ xf86ErrorFVerb(VERBLEV, "%02X ",
+ VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRReg, i));
+ }
+
+ xf86ErrorFVerb(VERBLEV, "\n\nGRAPHICS CONTROLLER\n"
+ " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF");
+ for (i = 0x00; i <= 0x08; i++)
+ {
+ if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
+ if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
+ xf86ErrorFVerb(VERBLEV, "%02X ",
+ VGAIN8_INDEX(pSmi, VGA_GRAPH_INDEX, VGA_GRAPH_DATA, i));
+ }
+
+ xf86ErrorFVerb(VERBLEV, "\n\nATTRIBUTE 0CONTROLLER\n"
+ " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF");
+ for (i = 0x00; i <= 0x14; i++)
+ {
+ tmp = VGAIN8(pSmi, vgaStatus);
+ if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
+ if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
+ xf86ErrorFVerb(VERBLEV, "%02X ",
+ VGAIN8_INDEX(pSmi, VGA_ATTR_INDEX, VGA_ATTR_DATA_R, i));
+ }
+ tmp = VGAIN8(pSmi, vgaStatus);
+ VGAOUT8(pSmi, VGA_ATTR_INDEX, 0x20);
+
+ xf86ErrorFVerb(VERBLEV, "\n\nDPR x0 x4 x8 xC");
+ for (i = 0x00; i <= 0x44; i += 4)
+ {
+ if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
+ xf86ErrorFVerb(VERBLEV, " %08X", READ_DPR(pSmi, i));
+ }
+
+ xf86ErrorFVerb(VERBLEV, "\n\nVPR x0 x4 x8 xC");
+ for (i = 0x00; i <= 0x60; i += 4)
+ {
+ if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
+ xf86ErrorFVerb(VERBLEV, " %08X", READ_VPR(pSmi, i));
+ }
+
+ xf86ErrorFVerb(VERBLEV, "\n\nCPR x0 x4 x8 xC");
+ for (i = 0x00; i <= 0x18; i += 4)
+ {
+ if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
+ xf86ErrorFVerb(VERBLEV, " %08X", READ_CPR(pSmi, i));
+ }
+
+ xf86ErrorFVerb(VERBLEV, "\n\n");
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "END register dump --------------------\n");
+}
+
+/*
+ * SMI_DisplayPowerManagementSet -- Sets VESA Display Power Management
+ * Signaling (DPMS) Mode.
+ */
+static void
+SMI_DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
+ int flags)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ SMIPtr pSmi = SMIPTR(pScrn);
+ CARD8 SR01, SR20, SR21, SR22, SR23, SR24, SR31, SR34;
+
+ ENTER_PROC("SMI_DisplayPowerManagementSet");
+
+ /* If we already are in the requested DPMS mode, just return */
+ if (pSmi->CurrentDPMS == PowerManagementMode)
+ {
+ LEAVE_PROC("SMI_DisplayPowerManagementSet");
+ return;
+ }
+
+#if 1 /* PDR#735 */
+ if (pSmi->pInt10 != NULL)
+ {
+ pSmi->pInt10->ax = 0x4F10;
+ switch (PowerManagementMode)
+ {
+ case DPMSModeOn:
+ pSmi->pInt10->bx = 0x0001;
+ break;
+
+ case DPMSModeStandby:
+ pSmi->pInt10->bx = 0x0101;
+ break;
+
+ case DPMSModeSuspend:
+ pSmi->pInt10->bx = 0x0201;
+ break;
+
+ case DPMSModeOff:
+ pSmi->pInt10->bx = 0x0401;
+ break;
+ }
+ pSmi->pInt10->cx = 0x0000;
+ pSmi->pInt10->num = 0x10;
+ xf86ExecX86int10(pSmi->pInt10);
+ if (pSmi->pInt10->ax == 0x004F)
+ {
+ pSmi->CurrentDPMS = PowerManagementMode;
+#if 1 /* PDR#835 */
+ if (PowerManagementMode == DPMSModeOn)
+ {
+ SR01 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01,
+ SR01 & ~0x20);
+ }
+#endif
+ LEAVE_PROC("SMI_DisplayPowerManagementSet");
+ return;
+ }
+ }
+#endif
+
+ /* Save the current SR registers */
+ if (pSmi->CurrentDPMS == DPMSModeOn)
+ {
+ pSmi->DPMS_SR20 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20);
+ pSmi->DPMS_SR21 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
+ pSmi->DPMS_SR31 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31);
+ pSmi->DPMS_SR34 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x34);
+ }
+
+ /* Read the required SR registers for the DPMS handler */
+ SR01 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01);
+ SR20 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20);
+ SR21 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
+ SR22 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22);
+ SR23 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x23);
+ SR24 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x24);
+ SR31 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31);
+ SR34 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x34);
+
+ switch (PowerManagementMode)
+ {
+ case DPMSModeOn:
+ /* Screen On: HSync: On, VSync : On */
+ SR01 &= ~0x20;
+ SR20 = pSmi->DPMS_SR20;
+ SR21 = pSmi->DPMS_SR21;
+ SR22 &= ~0x30;
+ SR23 &= ~0xC0;
+ SR24 |= 0x01;
+ SR31 = pSmi->DPMS_SR31;
+ SR34 = pSmi->DPMS_SR34;
+ break;
+
+ case DPMSModeStandby:
+ /* Screen: Off; HSync: Off, VSync: On */
+ SR01 |= 0x20;
+ SR20 = (SR20 & ~0xB0) | 0x10;
+ SR21 |= 0x88;
+ SR22 = (SR22 & ~0x30) | 0x10;
+ SR23 = (SR23 & ~0x07) | 0xD8;
+ SR24 &= ~0x01;
+ SR31 = (SR31 & ~0x07) | 0x00;
+ SR34 |= 0x80;
+ break;
+
+ case DPMSModeSuspend:
+ /* Screen: Off; HSync: On, VSync: Off */
+ SR01 |= 0x20;
+ SR20 = (SR20 & ~0xB0) | 0x10;
+ SR21 |= 0x88;
+ SR22 = (SR22 & ~0x30) | 0x20;
+ SR23 = (SR23 & ~0x07) | 0xD8;
+ SR24 &= ~0x01;
+ SR31 = (SR31 & ~0x07) | 0x00;
+ SR34 |= 0x80;
+ break;
+
+ case DPMSModeOff:
+ /* Screen: Off; HSync: Off, VSync: Off */
+ SR01 |= 0x20;
+ SR20 = (SR20 & ~0xB0) | 0x10;
+ SR21 |= 0x88;
+ SR22 = (SR22 & ~0x30) | 0x30;
+ SR23 = (SR23 & ~0x07) | 0xD8;
+ SR24 &= ~0x01;
+ SR31 = (SR31 & ~0x07) | 0x00;
+ SR34 |= 0x80;
+ break;
+
+ default:
+ xf86ErrorFVerb(VERBLEV, "Invalid PowerManagementMode %d passed to "
+ "SMI_DisplayPowerManagementSet\n", PowerManagementMode);
+ LEAVE_PROC("SMI_DisplayPowerManagementSet");
+ return;
+ }
+
+ /* Wait for vertical retrace */
+ while (hwp->readST01(hwp) & 0x8) ;
+ while (!(hwp->readST01(hwp) & 0x8)) ;
+
+ /* Write the registers */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01, SR01);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x34, SR34);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, SR31);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20, SR20);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22, SR22);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x23, SR23);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, SR21);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x24, SR24);
+
+ /* Save the current power state */
+ pSmi->CurrentDPMS = PowerManagementMode;
+
+ LEAVE_PROC("SMI_DisplayPowerManagementSet");
+}
+
+static void
+SMI_ProbeDDC(ScrnInfoPtr pScrn, int index)
+{
+ vbeInfoPtr pVbe;
+ if (xf86LoadSubModule(pScrn, "vbe"))
+ {
+ pVbe = VBEInit(NULL, index);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+ vbeFree(pVbe);
+ }
+}
+
+static unsigned int
+SMI_ddc1Read(ScrnInfoPtr pScrn)
+{
+ register vgaHWPtr hwp = VGAHWPTR(pScrn);
+ SMIPtr pSmi = SMIPTR(pScrn);
+ unsigned int ret;
+
+ ENTER_PROC("SMI_ddc1Read");
+
+ while (hwp->readST01(hwp) & 0x8) ;
+ while (!(hwp->readST01(hwp) & 0x8)) ;
+
+ ret = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72) & 0x08;
+
+ LEAVE_PROC("SMI_ddc1Read");
+ return(ret);
+}
+
+static Bool
+SMI_ddc1(int scrnIndex)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ SMIPtr pSmi = SMIPTR(pScrn);
+ Bool success = FALSE;
+ xf86MonPtr pMon;
+ unsigned char tmp;
+
+ ENTER_PROC("SMI_ddc1");
+
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72, tmp | 0x20);
+
+ pMon = xf86PrintEDID(xf86DoEDID_DDC1(scrnIndex, vgaHWddc1SetSpeed,
+ SMI_ddc1Read));
+ if (pMon != NULL)
+ {
+ success = TRUE;
+ }
+ xf86SetDDCproperties(pScrn, pMon);
+
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72, tmp);
+
+ LEAVE_PROC("SMI_ddc1");
+ return(success);
+}
diff --git a/src/smi_hwcurs.c b/src/smi_hwcurs.c
new file mode 100644
index 0000000..b2f8d69
--- /dev/null
+++ b/src/smi_hwcurs.c
@@ -0,0 +1,375 @@
+/* Header: //Mercury/Projects/archives/XFree86/4.0/smi_hwcurs.c-arc 1.12 27 Nov 2000 15:47:48 Frido $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. 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, sublicense, 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 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, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the names of the XFree86 Project and
+Silicon Motion shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from the XFree86 Project and Silicon Motion.
+*/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_hwcurs.c,v 1.2 2001/03/03 22:26:13 tsi Exp $ */
+
+#include "cursorstr.h"
+#include "smi.h"
+
+#define MAX_CURSOR 32
+
+static unsigned char *
+SMI_RealizeCursor(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
+{
+ SMIPtr pSmi = SMIPTR(infoPtr->pScrn);
+ CursorBitsPtr bits = pCurs->bits;
+ unsigned char * ram;
+ unsigned char * psource = bits->source;
+ unsigned char * pmask = bits->mask;
+ int x, y, srcwidth, i;
+
+ ENTER_PROC("SMI_RealizeCursor");
+
+ /* Allocate memory */
+ ram = (unsigned char *) xcalloc(1, 1024);
+ if (ram == NULL)
+ {
+ LEAVE_PROC("SMI_RealizeCursor");
+ return(NULL);
+ }
+
+ /* Calculate cursor information */
+ srcwidth = ((bits->width + 31) / 8) & ~3;
+ i = 0;
+
+ switch (pSmi->rotate)
+ {
+ default:
+ /* Copy cursor image */
+ for (y = 0; y < min(MAX_CURSOR, bits->height); y++)
+ {
+ for (x = 0; x < min(MAX_CURSOR / 8, srcwidth); x++)
+ {
+ unsigned char mask = byte_reversed[*pmask++];
+ unsigned char source = byte_reversed[*psource++] & mask;
+
+ ram[i++] = ~mask;
+ ram[i++] = source;
+ if (i & 4) i += 4;
+ }
+
+ pmask += srcwidth - x;
+ psource += srcwidth - x;
+
+ /* Fill remaining part of line with no shape */
+ for (; x < MAX_CURSOR / 8; x++)
+ {
+ ram[i++] = 0xFF;
+ ram[i++] = 0x00;
+ if (i & 4) i += 4;
+ }
+ }
+
+ /* Fill remaining part of memory with no shape */
+ for (; y < MAX_CURSOR; y++)
+ {
+ for (x = 0; x < MAX_CURSOR / 8; x++)
+ {
+ ram[i++] = 0xFF;
+ ram[i++] = 0x00;
+ if (i & 4) i += 4;
+ }
+ }
+ break;
+
+ case SMI_ROTATE_CW:
+ /* Initialize cursor memory */
+ for (i = 0; i < 1024;)
+ {
+ ram[i++] = 0xFF;
+ ram[i++] = 0x00;
+ if (i & 4) i += 4;
+ }
+
+ /* Rotate cursor image */
+ for (y = 0; y < min(MAX_CURSOR, bits->height); y++)
+ {
+ unsigned char bitmask = 0x01 << (y & 7);
+ int index = ((MAX_CURSOR - y - 1) / 8) * 2;
+ if (index & 4) index += 4;
+
+ for (x = 0; x < min(MAX_CURSOR / 8, srcwidth); x++)
+ {
+ unsigned char mask = *pmask++;
+ unsigned char source = *psource++ & mask;
+
+ i = index + (x * 8) * 16;
+ if (mask || (source & mask))
+ {
+ unsigned char bit;
+ for (bit = 0x01; bit; bit <<= 1)
+ {
+ if (mask & bit)
+ {
+ ram[i + 0] &= ~bitmask;
+ }
+
+ if (source & bit)
+ {
+ ram[i + 1] |= bitmask;
+ }
+
+ i += 16;
+ }
+ }
+ }
+
+ pmask += srcwidth - x;
+ psource += srcwidth - x;
+ }
+ break;
+
+ case SMI_ROTATE_CCW:
+ /* Initialize cursor memory */
+ for (i = 0; i < 1024;)
+ {
+ ram[i++] = 0xFF;
+ ram[i++] = 0x00;
+ if (i & 4) i += 4;
+ }
+
+ /* Rotate cursor image */
+ for (y = 0; y < min(MAX_CURSOR, bits->height); y++)
+ {
+ unsigned char bitmask = 0x80 >> (y & 7);
+ int index = (y >> 3) * 2;
+ if (index & 4) index += 4;
+
+ for (x = 0; x < min(MAX_CURSOR / 8, srcwidth); x++)
+ {
+ unsigned char mask = *pmask++;
+ unsigned char source = *psource++ & mask;
+
+ i = index + (MAX_CURSOR - x * 8 - 1) * 16;
+ if (mask || (source & mask))
+ {
+ unsigned char bit;
+ for (bit = 0x01; bit; bit <<= 1)
+ {
+ if (mask & bit)
+ {
+ ram[i + 0] &= ~bitmask;
+ }
+
+ if (source & bit)
+ {
+ ram[i + 1] |= bitmask;
+ }
+
+ i -= 16;
+ }
+ }
+ }
+
+ pmask += srcwidth - x;
+ psource += srcwidth - x;
+ }
+ break;
+ }
+
+ LEAVE_PROC("SMI_RealizeCursor");
+ return(ram);
+}
+
+static void
+SMI_LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ CARD8 tmp;
+
+ ENTER_PROC("SMI_LoadCursorImage");
+
+ /* Load storage location. */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x80,
+ pSmi->FBCursorOffset / 2048);
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81) & 0x80;
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81,
+ tmp | ((pSmi->FBCursorOffset / 2048) >> 8));
+
+ /* Copy cursor image to framebuffer storage */
+ memcpy(pSmi->FBBase + pSmi->FBCursorOffset, src, 1024);
+
+ LEAVE_PROC("SMI_LoadCursorImage");
+}
+
+static void
+SMI_ShowCursor(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ char tmp;
+
+ ENTER_PROC("SMI_ShowCursor");
+
+ /* Show cursor */
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, tmp | 0x80);
+
+ LEAVE_PROC("SMI_ShowCursor");
+}
+
+static void
+SMI_HideCursor(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ char tmp;
+
+ ENTER_PROC("SMI_HideCursor");
+
+ /* Hide cursor */
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, tmp & ~0x80);
+
+ LEAVE_PROC("SMI_HideCursor");
+}
+
+static void
+SMI_SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ int xoff, yoff;
+
+ ENTER_PROC("SMI_SetCursorPosition");
+
+ /* Calculate coordinates for rotation */
+ switch (pSmi->rotate)
+ {
+ default:
+ xoff = x;
+ yoff = y;
+ break;
+
+ case SMI_ROTATE_CW:
+ xoff = pSmi->ShadowHeight - y - MAX_CURSOR;
+ yoff = x;
+ break;
+
+ case SMI_ROTATE_CCW:
+ xoff = y;
+ yoff = pSmi->ShadowWidth - x - MAX_CURSOR;
+ break;
+ }
+
+ /* Program coordinates */
+ if (xoff >= 0)
+ {
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x88, xoff & 0xFF);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x89,
+ (xoff >> 8) & 0x07);
+ }
+ else
+ {
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x88,
+ (-xoff) & (MAX_CURSOR - 1));
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x89, 0x08);
+ }
+
+ if (yoff >= 0)
+ {
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x8A, yoff & 0xFF);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x8B,
+ (yoff >> 8) & 0x07);
+ }
+ else
+ {
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x8A,
+ (-yoff) & (MAX_CURSOR - 1));
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x8B, 0x08);
+ }
+
+ LEAVE_PROC("SMI_SetCursorPosition");
+}
+
+static void
+SMI_SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ unsigned char packedFG, packedBG;
+
+ ENTER_PROC("SMI_SetCursorColors");
+
+ /* Pack the true color into 8 bit */
+ packedFG = (fg & 0xE00000) >> 16
+ | (fg & 0x00E000) >> 11
+ | (fg & 0x0000C0) >> 6
+ ;
+ packedBG = (bg & 0xE00000) >> 16
+ | (bg & 0x00E000) >> 11
+ | (bg & 0x0000C0) >> 6
+ ;
+
+ /* Program the colors */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x8C, packedFG);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x8D, packedBG);
+
+ LEAVE_PROC("SMI_SetCursorColors");
+}
+
+Bool
+SMI_HWCursorInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ SMIPtr pSmi = SMIPTR(pScrn);
+ xf86CursorInfoPtr infoPtr;
+ Bool ret;
+
+ ENTER_PROC("SMI_HWCursorInit");
+
+ /* Create cursor infor record */
+ infoPtr = xf86CreateCursorInfoRec();
+ if (infoPtr == NULL)
+ {
+ LEAVE_PROC("SMI_HWCursorInit");
+ return(FALSE);
+ }
+
+ pSmi->CursorInfoRec = infoPtr;
+
+ /* Fill in the information */
+ infoPtr->MaxWidth = MAX_CURSOR;
+ infoPtr->MaxHeight = MAX_CURSOR;
+ infoPtr->Flags = HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8
+ | HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK
+ | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK
+ | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
+ | HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
+ | HARDWARE_CURSOR_INVERT_MASK;
+
+ infoPtr->SetCursorColors = SMI_SetCursorColors;
+ infoPtr->SetCursorPosition = SMI_SetCursorPosition;
+ infoPtr->LoadCursorImage = SMI_LoadCursorImage;
+ infoPtr->HideCursor = SMI_HideCursor;
+ infoPtr->ShowCursor = SMI_ShowCursor;
+ infoPtr->RealizeCursor = SMI_RealizeCursor;
+ infoPtr->UseHWCursor = NULL;
+
+ /* Proceed with cursor initialization */
+ ret = xf86InitCursor(pScreen, infoPtr);
+
+ LEAVE_PROC("SMI_HWCursorInit");
+ return(ret);
+}
diff --git a/src/smi_i2c.c b/src/smi_i2c.c
new file mode 100644
index 0000000..3a73ced
--- /dev/null
+++ b/src/smi_i2c.c
@@ -0,0 +1,115 @@
+/* Header: //Mercury/Projects/archives/XFree86/4.0/smi_i2c.c-arc 1.10 27 Nov 2000 15:47:58 Frido $ */
+
+/*
+Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. 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, sublicense, 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 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, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the names of the XFree86 Project and
+Silicon Motion shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from the XFree86 Project and Silicon Motion.
+*/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_i2c.c,v 1.2 2001/12/20 21:35:39 eich Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+#include "vgaHW.h"
+
+#include "smi.h"
+
+#undef VERBLEV
+#undef ENTER_PROC
+#undef DEBUG_PROC
+#undef LEAVE_PROC
+#undef DEBUG
+#define VERBLEV 2
+#define ENTER_PROC(PROCNAME)
+#define DEBUG_PROC(PROCNAME)
+#define LEAVE_PROC(PROCNAME)
+#define DEBUG(arg)
+
+static void
+SMI_I2CPutBits(I2CBusPtr b, int clock, int data)
+{
+ SMIPtr pSmi = SMIPTR(xf86Screens[b->scrnIndex]);
+ unsigned int reg = 0x30;
+
+ ENTER_PROC("SMI_I2CPutBits");
+
+ if (clock) reg |= 0x01;
+ if (data) reg |= 0x02;
+
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72, reg);
+
+ LEAVE_PROC("SMI_I2CPutBits");
+}
+
+static void
+SMI_I2CGetBits(I2CBusPtr b, int *clock, int *data)
+{
+ SMIPtr pSmi = SMIPTR(xf86Screens[b->scrnIndex]);
+ unsigned int reg = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72);
+
+ ENTER_PROC("SMI_I2CGetBits");
+
+ *clock = reg & 0x04;
+ *data = reg & 0x08;
+
+ LEAVE_PROC("SMI_I2CGetBits");
+}
+
+Bool
+SMI_I2CInit(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_I2CInit");
+
+ if (pSmi->I2C == NULL)
+ {
+ I2CBusPtr I2CPtr = xf86CreateI2CBusRec();
+ if (I2CPtr == NULL)
+ {
+ LEAVE_PROC("SMI_I2CInit");
+ return(FALSE);
+ }
+
+ I2CPtr->BusName = "I2C bus";
+ I2CPtr->scrnIndex = pScrn->scrnIndex;
+ I2CPtr->I2CPutBits = SMI_I2CPutBits;
+ I2CPtr->I2CGetBits = SMI_I2CGetBits;
+
+ if (!xf86I2CBusInit(I2CPtr))
+ {
+ xf86DestroyI2CBusRec(I2CPtr, TRUE, TRUE);
+ LEAVE_PROC("SMI_I2CInit");
+ return(FALSE);
+ }
+
+ pSmi->I2C = I2CPtr;
+ }
+
+ LEAVE_PROC("SMI_I2CInit");
+ return(TRUE);
+}
diff --git a/src/smi_shadow.c b/src/smi_shadow.c
new file mode 100644
index 0000000..5ef9ba5
--- /dev/null
+++ b/src/smi_shadow.c
@@ -0,0 +1,226 @@
+/* Header: //Mercury/Projects/archives/XFree86/4.0/smi_shadow.c-arc 1.10 30 Nov 2000 11:40:38 Frido $ */
+
+/*
+Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. 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, sublicense, 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 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, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the names of the XFree86 Project and
+Silicon Motion shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from the XFree86 Project and Silicon Motion.
+*/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_shadow.c,v 1.2 2000/12/05 21:18:37 dawes Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86_ansic.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "shadowfb.h"
+#include "servermd.h"
+
+#include "smi.h"
+
+/******************************************************************************\
+|* SMI_RefreshArea
+|*=============================================================================
+|*
+|* PARAMETERS: pScrn Pointer to ScrnInfo structure.
+|* num Number of boxes to refresh.
+|* pbox Pointer to an array of boxes to refresh.
+|*
+|* DESCRIPTION: Refresh a portion of the shadow buffer to the visual screen
+|* buffer. This is mainly used for rotation purposes.
+|* y
+|* RETURNS: Nothing.
+|*
+\******************************************************************************/
+void SMI_RefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ int width, height, srcX, srcY, destX, destY;
+
+ ENTER_PROC("SMI_RefreshArea");
+
+ /* #671 */
+ if (pSmi->polyLines)
+ {
+ pSmi->polyLines = FALSE;
+ return;
+ }
+
+ if (pSmi->rotate)
+ {
+ /* IF we need to do rotation, setup the hardware here. */
+ WaitIdleEmpty();
+ WRITE_DPR(pSmi, 0x10, pSmi->ShadowPitch);
+ WRITE_DPR(pSmi, 0x3C, pSmi->ShadowPitch);
+ WRITE_DPR(pSmi, 0x44, pSmi->FBOffset >> 3);
+ }
+
+ /* #672 */
+ if (pSmi->ClipTurnedOn)
+ {
+ WaitQueue(1);
+ WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
+ pSmi->ClipTurnedOn = FALSE;
+ }
+
+ while (num--)
+ {
+ /* Get coordinates of the box to refresh. */
+ srcX = pbox->x1;
+ srcY = pbox->y1;
+ width = pbox->x2 - srcX;
+ height = pbox->y2 - srcY;
+
+ DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", srcX, srcY, width, height));
+
+ if ((width > 0) && (height > 0))
+ {
+ switch (pSmi->rotate)
+ {
+ case SMI_ROTATE_CW:
+ /* 90 degrees CW rotation. Calculate destination
+ coordinates:
+
+ *---+
+ | | +-----*
+ | | | | destX = shadowHeight - srcY - 1
+ | | --> | | destY = srcX
+ | | | |
+ | | +-----+
+ +---+
+ */
+ destX = pSmi->ShadowHeight - srcY - 1;
+ destY = srcX;
+
+ WaitQueue(4);
+ WRITE_DPR(pSmi, 0x00, (srcX << 16) + srcY);
+ WRITE_DPR(pSmi, 0x04, (destX << 16) + destY);
+ WRITE_DPR(pSmi, 0x08, (width << 16) + height);
+ WRITE_DPR(pSmi, 0x0C, 0xCC | SMI_ROTATE_BLT |
+ SMI_ROTATE_CW | SMI_START_ENGINE);
+ break;
+
+ case SMI_ROTATE_CCW:
+ /* 90 degrees CCW rotatation. Calculate destination
+ coordinates:
+
+ *---+
+ | | +-----+
+ | | | | destX = srcY
+ | | --> | | destY = shadowWidth - srcX - 1
+ | | | |
+ | | *-----+
+ +---+
+ */
+ destX = srcY;
+ destY = pSmi->ShadowWidth - srcX - 1;
+
+ WaitQueue(4);
+ WRITE_DPR(pSmi, 0x00, (srcX << 16) + srcY);
+ WRITE_DPR(pSmi, 0x04, (destX << 16) + destY);
+ WRITE_DPR(pSmi, 0x08, (width << 16) + height);
+ WRITE_DPR(pSmi, 0x0C, 0xCC | SMI_ROTATE_BLT |
+ SMI_ROTATE_CCW | SMI_START_ENGINE);
+ break;
+
+ default:
+ /* No rotation, perform a normal copy. */
+ if (pScrn->bitsPerPixel == 24)
+ {
+ srcX *= 3;
+ width *= 3;
+
+ if (pSmi->Chipset == SMI_LYNX)
+ {
+ srcY *= 3;
+ }
+ }
+
+ WaitQueue(4);
+ WRITE_DPR(pSmi, 0x00, (srcX << 16) + srcY);
+ WRITE_DPR(pSmi, 0x04, (srcX << 16) + srcY);
+ WRITE_DPR(pSmi, 0x08, (width << 16) + height);
+ WRITE_DPR(pSmi, 0x0C, SMI_BITBLT + SMI_START_ENGINE + 0xCC);
+ break;
+ }
+ }
+
+ pbox++;
+ }
+
+ if (pSmi->rotate)
+ {
+ /* If we did a rotation, we need to restore the hardware state here. */
+ WaitIdleEmpty();
+ WRITE_DPR(pSmi, 0x10, (pSmi->Stride << 16) | pSmi->Stride);
+ WRITE_DPR(pSmi, 0x3C, (pSmi->Stride << 16) | pSmi->Stride);
+ WRITE_DPR(pSmi, 0x44, 0);
+ }
+
+ LEAVE_PROC("SMI_RefreshArea");
+}
+
+/******************************************************************************\
+|* SMI_PointerMoved
+|*=============================================================================
+|*
+|* PARAMETERS: index Index of current screen.
+|* x X location of pointer.
+|* y Y location of pointer.
+|*
+|* DESCRIPTION: Adjust the pointer location if we are in rotation mode.
+|*
+|* RETURNS: Nothing.
+|*
+\******************************************************************************/
+void SMI_PointerMoved(int index, int x, int y)
+{
+ ScrnInfoPtr pScrn = xf86Screens[index];
+ SMIPtr pSmi = SMIPTR(pScrn);
+ int newX, newY;
+
+ switch (pSmi->rotate)
+ {
+ case SMI_ROTATE_CW:
+ /* 90 degrees CW rotation. */
+ newX = pScrn->pScreen->height - y - 1;
+ newY = x;
+ break;
+
+ case SMI_ROTATE_CCW:
+ /* 90 degrees CCW rotation. */
+ newX = y;
+ newY = pScrn->pScreen->width - x - 1;
+ break;
+
+ default:
+ /* No rotation. */
+ newX = x;
+ newY = y;
+ break;
+ }
+
+ /* Pass adjusted pointer coordinates original PointerMoved function. */
+ (*pSmi->PointerMoved)(index, newX, newY);
+}
diff --git a/src/smi_video.c b/src/smi_video.c
new file mode 100644
index 0000000..7ec571e
--- /dev/null
+++ b/src/smi_video.c
@@ -0,0 +1,2548 @@
+/* Header: //Mercury/Projects/archives/XFree86/4.0/smi_video.c.-arc 1.14 30 Nov 2000 16:51:40 Frido $ */
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. All Rights Reserved.
+Copyright (C) 2001 Corvin Zahn. 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, sublicense, 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 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, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the names of the XFree86 Project and
+Silicon Motion shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from the XFree86 Project and silicon Motion.
+*/
+
+/*
+this is a heavy modified version of the V1.2.2 original siliconmotion driver.
+- SAA7111 support
+- supports attributes: XV_ENCODING, XV_BRIGHTNESS, XV_CONTRAST,
+ XV_SATURATION, XV_HUE, XV_COLORKEY, XV_INTERLACED
+ XV_CAPTURE_BRIGHTNESS can be used to set brightness in the capture device
+- bug fixes
+- tries not to use acceleration functions (if USE_XAA = 0)
+- interlaced video for double vertical resolution
+
+Author of changes: Corvin Zahn <zahn@zac.de>
+Date: 2.11.2001
+*/
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_video.c,v 1.9.2.1 2003/05/09 02:22:00 dawes Exp $ */
+
+#include "smi.h"
+#include "smi_video.h"
+
+
+/*
+
+new attribute:
+
+XV_INTERLACED = 0: only one field of an interlaced video signal is displayed:
+ -> half vertical resolution, but no comb like artifacts from
+ moving vertical edges
+XV_INTERLACED = 1: both fields of an interlaced video signal are displayed:
+ -> full vertical resolution, but comb like artifacts from
+ moving vertical edges
+
+The default value can be set with the driver option Interlaced
+
+*/
+
+
+
+
+#undef MIN
+#undef ABS
+#undef CLAMP
+#undef ENTRIES
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define ABS(n) (((n) < 0) ? -(n) : (n))
+#define CLAMP(v, min, max) (((v) < (min)) ? (min) : MIN(v, max))
+
+#define ENTRIES(array) (sizeof(array) / sizeof((array)[0]))
+#define nElems(x) (sizeof(x) / sizeof(x[0]))
+
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+#if defined(XvExtension) && SMI_USE_VIDEO
+
+/* USE_XAA = 1: use XAA functions for color key rectangle fill,
+ USE_XAA = 0: use xf86XVFillKeyHelper for color key rectangle fill,
+ needs common/xf86xv.c >= 1.30,
+ common/xf86xv.h >= 1.22,
+ loader/xf86sym.c >= 1.194 */
+#define USE_XAA 1
+
+#include "dixstruct.h"
+#if USE_XAA
+#include "xaa.h"
+#include "xaalocal.h"
+#endif
+
+
+static int SMI_AddEncoding(XF86VideoEncodingPtr enc, int i,
+ int norm, int input, int channel);
+static void SMI_BuildEncodings(SMI_PortPtr p);
+
+static XF86VideoAdaptorPtr SMI_SetupVideo(ScreenPtr pScreen);
+static void SMI_ResetVideo(ScrnInfoPtr pScrn);
+
+#if SMI_USE_CAPTURE
+static int SMI_PutVideo(ScrnInfoPtr pScrn,
+ short vid_x, short vid_y, short drw_x, short drw_y,
+ short vid_w, short vid_h, short drw_w, short drw_h,
+ RegionPtr clipBoxes, pointer data);
+#endif
+static void SMI_StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown);
+static int SMI_SetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
+ INT32 value, pointer data);
+static int SMI_GetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
+ INT32 *value, pointer data);
+static void SMI_QueryBestSize(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);
+static int SMI_PutImage(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);
+static int SMI_QueryImageAttributes(ScrnInfoPtr pScrn,
+ int id, unsigned short *width, unsigned short *height,
+ int *picthes, int *offsets);
+
+static Bool RegionsEqual(RegionPtr A, RegionPtr B);
+static Bool SMI_ClipVideo(ScrnInfoPtr pScrn, BoxPtr dst,
+ INT32 *x1, INT32 *y1, INT32 *x2, INT32 *y2,
+ RegionPtr reg, INT32 width, INT32 height);
+static void SMI_DisplayVideo(ScrnInfoPtr pScrn, int id, int offset,
+ short width, short height, int pitch, int x1, int y1, int x2, int y2,
+ BoxPtr dstBox, short vid_w, short vid_h, short drw_w, short drw_h);
+static void SMI_BlockHandler(int i, pointer blockData, pointer pTimeout,
+ pointer pReadMask);
+#if 0
+static void SMI_WaitForSync(ScrnInfoPtr pScrn);
+#endif
+/*static int SMI_SendI2C(ScrnInfoPtr pScrn, CARD8 device, char *devName,
+ SMI_I2CDataPtr i2cData);*/
+
+static void SMI_InitOffscreenImages(ScreenPtr pScreen);
+static FBAreaPtr SMI_AllocateMemory(ScrnInfoPtr pScrn, FBAreaPtr area,
+ int numLines);
+static void SMI_CopyData(unsigned char *src, unsigned char *dst, int srcPitch,
+ int dstPitch, int height, int width);
+static void SMI_CopyYV12Data(unsigned char *src1, unsigned char *src2,
+ unsigned char *src3, unsigned char *dst, int srcPitch1, int srcPitch2,
+ int dstPitch, int height, int width);
+
+static int SMI_AllocSurface(ScrnInfoPtr pScrn,
+ int id, unsigned short width, unsigned short height,
+ XF86SurfacePtr surface);
+static int SMI_FreeSurface(XF86SurfacePtr surface);
+static int SMI_DisplaySurface(XF86SurfacePtr surface,
+ short vid_x, short vid_y, short drw_x, short drw_y,
+ short vid_w, short vid_h, short drw_w, short drw_h,
+ RegionPtr clipBoxes);
+static int SMI_StopSurface(XF86SurfacePtr surface);
+static int SMI_GetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 *value);
+static int SMI_SetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 value);
+
+static int SetAttr(ScrnInfoPtr pScrn, int i, int value);
+static int SetAttrSAA7110(ScrnInfoPtr pScrn, int i, int value);
+static int SetAttrSAA7111(ScrnInfoPtr pScrn, int i, int value);
+
+/**
+ * Atoms
+ */
+
+static Atom xvColorKey;
+static Atom xvEncoding;
+static Atom xvBrightness,xvCapBrightness, xvContrast, xvSaturation, xvHue;
+static Atom xvInterlaced;
+
+
+/******************************************************************************\
+** **
+** C A P A B I L I T I E S **
+** **
+\******************************************************************************/
+
+
+/**************************************************************************/
+/* input channels */
+
+#define N_COMPOSITE_CHANNELS 4
+#define N_SVIDEO_CHANNELS 2
+
+#define N_VIDEO_INPUTS 2
+typedef enum _VideoInput { COMPOSITE, SVIDEO } VideoInput;
+
+
+/**************************************************************************/
+/* video input formats */
+
+typedef struct _VideoInputDataRec {
+ char* name;
+} VideoInputDataRec;
+
+static VideoInputDataRec VideoInputs[] = {
+ { "composite" },
+ { "svideo" }
+};
+
+
+/**************************************************************************/
+/* video norms */
+
+#define N_VIDEO_NORMS 3
+typedef enum _VideoNorm { PAL, NTSC, SECAM } VideoNorm;
+
+typedef struct _VideoNormDataRec {
+ char* name;
+ unsigned long Wt;
+ unsigned long Wa;
+ unsigned long Ht;
+ unsigned long Ha;
+ unsigned long HStart;
+ unsigned long VStart;
+ XvRationalRec rate;
+} VideoNormDataRec;
+
+
+static VideoNormDataRec VideoNorms[] =
+{
+ /* PAL-BDGHI */
+ {"pal", 864, 704, 625, 576, 16, 16, { 1, 50 }},
+ /* NTSC */
+ {"ntsc", 858, 704, 525, 480, 21, 8, { 1001, 60000 }},
+ /* SECAM (not tested) */
+ {"secam", 864, 7040, 625, 576, 31, 16, { 1, 50 }},
+};
+
+
+/**************************************************************************/
+/* number of (generated) XV_ENCODING vaulues */
+#define N_ENCODINGS ((N_VIDEO_NORMS) * (N_COMPOSITE_CHANNELS + N_SVIDEO_CHANNELS))
+
+
+/**************************************************************************/
+
+static XF86VideoFormatRec SMI_VideoFormats[] =
+{
+ { 15, TrueColor }, /* depth, class */
+ { 16, TrueColor }, /* depth, class */
+ { 24, TrueColor }, /* depth, class */
+};
+
+
+/**************************************************************************/
+
+/**
+ * Attributes
+ */
+
+#define XV_ENCODING_NAME "XV_ENCODING"
+#define XV_BRIGHTNESS_NAME "XV_BRIGHTNESS"
+#define XV_CAPTURE_BRIGHTNESS_NAME "XV_CAPTURE_BRIGHTNESS"
+#define XV_CONTRAST_NAME "XV_CONTRAST"
+#define XV_SATURATION_NAME "XV_SATURATION"
+#define XV_HUE_NAME "XV_HUE"
+#define XV_COLORKEY_NAME "XV_COLORKEY"
+#define XV_INTERLACED_NAME "XV_INTERLACED"
+
+
+/* fixed order! */
+static XF86AttributeRec SMI_VideoAttributesSAA711x[N_ATTRS] = {
+ {XvSettable | XvGettable, 0, N_ENCODINGS-1, XV_ENCODING_NAME},
+ {XvSettable | XvGettable, 0, 255, XV_BRIGHTNESS_NAME},
+ {XvSettable | XvGettable, 0, 255, XV_CAPTURE_BRIGHTNESS_NAME},
+ {XvSettable | XvGettable, 0, 127, XV_CONTRAST_NAME},
+ {XvSettable | XvGettable, 0, 127, XV_SATURATION_NAME},
+ {XvSettable | XvGettable, -128, 127, XV_HUE_NAME},
+ {XvSettable | XvGettable, 0x000000, 0xFFFFFF, XV_COLORKEY_NAME},
+ {XvSettable | XvGettable, 0, 1, XV_INTERLACED_NAME},
+};
+
+static XF86AttributeRec SMI_VideoAttributes[2] = {
+ {XvSettable | XvGettable, 0, 255, XV_BRIGHTNESS_NAME},
+ {XvSettable | XvGettable, 0x000000, 0xFFFFFF, XV_COLORKEY_NAME},
+};
+
+
+/**************************************************************************/
+static XF86ImageRec SMI_VideoImages[] =
+{
+ XVIMAGE_YUY2,
+ XVIMAGE_YV12,
+ XVIMAGE_I420,
+ {
+ FOURCC_RV15, /* id */
+ XvRGB, /* type */
+ LSBFirst, /* byte_order */
+ { 'R', 'V' ,'1', '5',
+ 0x00, '5', 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 }, /* guid */
+ 16, /* bits_per_pixel */
+ XvPacked, /* format */
+ 1, /* num_planes */
+ 15, /* depth */
+ 0x001F, 0x03E0, 0x7C00, /* red_mask, green, blue */
+ 0, 0, 0, /* y_sample_bits, u, v */
+ 0, 0, 0, /* horz_y_period, u, v */
+ 0, 0, 0, /* vert_y_period, u, v */
+ { 'R', 'V', 'B' }, /* component_order */
+ XvTopToBottom /* scaline_order */
+ },
+ {
+ FOURCC_RV16, /* id */
+ XvRGB, /* type */
+ LSBFirst, /* byte_order */
+ { 'R', 'V' ,'1', '6',
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 }, /* guid */
+ 16, /* bits_per_pixel */
+ XvPacked, /* format */
+ 1, /* num_planes */
+ 16, /* depth */
+ 0x001F, 0x07E0, 0xF800, /* red_mask, green, blue */
+ 0, 0, 0, /* y_sample_bits, u, v */
+ 0, 0, 0, /* horz_y_period, u, v */
+ 0, 0, 0, /* vert_y_period, u, v */
+ { 'R', 'V', 'B' }, /* component_order */
+ XvTopToBottom /* scaline_order */
+ },
+ {
+ FOURCC_RV24, /* id */
+ XvRGB, /* type */
+ LSBFirst, /* byte_order */
+ { 'R', 'V' ,'2', '4',
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 }, /* guid */
+ 24, /* bits_per_pixel */
+ XvPacked, /* format */
+ 1, /* num_planes */
+ 24, /* depth */
+ 0x0000FF, 0x00FF00, 0xFF0000, /* red_mask, green, blue */
+ 0, 0, 0, /* y_sample_bits, u, v */
+ 0, 0, 0, /* horz_y_period, u, v */
+ 0, 0, 0, /* vert_y_period, u, v */
+ { 'R', 'V', 'B' }, /* component_order */
+ XvTopToBottom /* scaline_order */
+ },
+ {
+ FOURCC_RV32, /* id */
+ XvRGB, /* type */
+ LSBFirst, /* byte_order */
+ { 'R', 'V' ,'3', '2',
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 }, /* guid */
+ 32, /* bits_per_pixel */
+ XvPacked, /* format */
+ 1, /* num_planes */
+ 24, /* depth */
+ 0x0000FF, 0x00FF00, 0xFF0000, /* red_mask, green, blue */
+ 0, 0, 0, /* y_sample_bits, u, v */
+ 0, 0, 0, /* horz_y_period, u, v */
+ 0, 0, 0, /* vert_y_period, u, v */
+ { 'R', 'V', 'B' }, /* component_order */
+ XvTopToBottom /* scaline_order */
+ },
+};
+
+
+/**************************************************************************/
+
+/**
+ * SAA7111 video decoder register values
+ */
+
+
+/** SAA7111 control sequences for selecting one out of four
+ composite input channels */
+static I2CByte SAA7111CompositeChannelSelect[N_COMPOSITE_CHANNELS][4] = {
+ { 0x02, 0xC0, 0x09, 0x4A}, /* CVBS AI11 */
+ { 0x02, 0xC1, 0x09, 0x4A}, /* CVBS AI12 */
+ { 0x02, 0xC2, 0x09, 0x4A}, /* CVBS AI21 */
+ { 0x02, 0xC3, 0x09, 0x4A}, /* CVBS AI22 */
+};
+
+
+/** SAA7111 control sequences for selecting one out of two
+ s-video input channels */
+static I2CByte SAA7111SVideoChannelSelect[N_SVIDEO_CHANNELS][4] = {
+ { 0x02, 0xC6, 0x09, 0xCA}, /* Y/C AI11/AI21 */
+ { 0x02, 0xC7, 0x09, 0xCA}, /* Y/C AI12/AI22 */
+};
+
+
+/** SAA7111 control sequences for selecting one out of three
+ video norms */
+static I2CByte SAA7111VideoStd[3][8] = {
+ {0x06, 108, 0x07, 108, 0x08, 0x09, 0x0E, 0x01}, /* PAL */
+ {0x06, 107, 0x07, 107, 0x08, 0x49, 0x0E, 0x01}, /* NTSC */
+ {0x06, 108, 0x07, 108, 0x08, 0x01, 0x0E, 0x51} /* SECAM */
+};
+
+
+#if 0
+static I2CByte SAA7110InitData[] =
+{
+ /* Configuration */
+ 0x00, 0x4C, 0x01, 0x3C, 0x02, 0x00, 0x03, 0xEF,
+ 0x04, 0xBD, 0x05, 0xE2, 0x06, 0x00, 0x07, 0x00,
+ 0x08, 0xF8, 0x09, 0xF8, 0x0A, 0x60, 0x0B, 0x60,
+ 0x0C, 0x00, 0x0D, 0x80, 0x0E, 0x18, 0x0F, 0xD9,
+ 0x10, 0x00, 0x11, 0x2B, 0x12, 0x40, 0x13, 0x40,
+ 0x14, 0x42, 0x15, 0x1A, 0x16, 0xFF, 0x17, 0xDA,
+ 0x18, 0xE6, 0x19, 0x90, 0x20, 0xD9, 0x21, 0x16,
+ 0x22, 0x40, 0x23, 0x40, 0x24, 0x80, 0x25, 0x40,
+ 0x26, 0x80, 0x27, 0x4F, 0x28, 0xFE, 0x29, 0x01,
+ 0x2A, 0xCF, 0x2B, 0x0F, 0x2C, 0x03, 0x2D, 0x01,
+ 0x2E, 0x83, 0x2F, 0x03, 0x30, 0x40, 0x31, 0x35,
+ 0x32, 0x02, 0x33, 0x8C, 0x34, 0x03,
+
+ /* NTSC */
+ 0x11, 0x2B, 0x0F, 0xD9,
+
+ /* RCA input connector */
+ 0x06, 0x00, 0x0E, 0x18, 0x20, 0xD9, 0x21, 0x16,
+ 0x22, 0x40, 0x2C, 0x03,
+
+};
+#endif
+
+static I2CByte SAA7111InitData[] =
+{
+ 0x11, 0x1D, /* 0D D0=1: automatic colour killer off
+ D1=0: DMSD data to YUV output
+ D2=1: output enable H/V sync on
+ D3=1: output enable YUV data on */
+ 0x02, 0xC0, /* Mode 0 */
+ 0x03, 0x23, /* automatic gain */
+ 0x04, 0x00, /* */
+ 0x05, 0x00, /* */
+ 0x06, 108, /* hor sync begin */
+ 0x07, 108, /* hor sync stop */
+ 0x08, 0x88, /* sync control:
+ D1-0=00: VNOI = normal mode
+ D2=0: PLL closed
+ D3=1: VTR mode
+ D7=1: automatic field detection */
+ 0x09, 0x41, /* 4A luminance control */
+ 0x0A, 0x80, /* brightness = 128 (CCIR level) */
+ 0x0B, 0x40, /* contrast = 1.0 */
+ 0x0C, 0x40, /* crominance = 1.0 (CCIR level) */
+ 0x0D, 0x00, /* hue = 0 */
+ 0x0E, 0x01, /* chroma bandwidth = nominal
+ fast colour time constant = nominal
+ chrom comp filter on
+ colour standard PAL BGHI, NTSC M */
+ 0x10, 0x48, /* luminance delay compensation = 0
+ VRLN = 1
+ fine pos of hs = 0
+ output format = YUV 422 */
+ 0x12, 0x00, /* 20 D5=1: VPO in tristate */
+ 0x13, 0x00,
+ 0x15, 0x00,
+ 0x16, 0x00,
+ 0x17, 0x00,
+
+};
+
+
+/**************************************************************************/
+
+/**
+ * generates XF86VideoEncoding[i] with video norm norm, video input format
+ * input and video input channel channel
+ */
+static int
+SMI_AddEncoding(XF86VideoEncodingPtr enc, int i,
+ int norm, int input, int channel)
+{
+ char* norm_string;
+ char* input_string;
+ char channel_string[20];
+
+ ENTER_PROC("SMI_AddEncoding");
+
+ norm_string = VideoNorms[norm].name;
+ input_string = VideoInputs[input].name;
+ sprintf(channel_string, "%d", channel);
+ enc[i].id = i;
+ enc[i].name = xalloc(strlen(norm_string) +
+ strlen(input_string) +
+ strlen(channel_string)+3);
+ if (NULL == enc[i].name) {
+ LEAVE_PROC("SMI_AddEncoding");
+ return -1;
+ }
+ enc[i].width = VideoNorms[norm].Wa;
+ enc[i].height = VideoNorms[norm].Ha;
+ enc[i].rate = VideoNorms[norm].rate;
+ sprintf(enc[i].name,"%s-%s-%s", norm_string, input_string, channel_string);
+
+ LEAVE_PROC("SMI_AddEncoding");
+ return 0;
+}
+
+
+/**
+ * builds XF86VideoEncodings with all legal combinations of video norm,
+ * video input format and video input channel
+ */
+static void
+SMI_BuildEncodings(SMI_PortPtr p)
+{
+ int ch, n;
+
+ ENTER_PROC("SMI_BuildEncodings");
+
+ /* allocate memory for encoding array */
+ p->enc = xalloc(sizeof(XF86VideoEncodingRec) * N_ENCODINGS);
+ if (NULL == p->enc)
+ goto fail;
+ memset(p->enc,0,sizeof(XF86VideoEncodingRec) * N_ENCODINGS);
+ /* allocate memory for video norm array */
+ p->norm = xalloc(sizeof(int) * N_ENCODINGS);
+ if (NULL == p->norm)
+ goto fail;
+ memset(p->norm,0,sizeof(int) * N_ENCODINGS);
+ /* allocate memory for video input format array */
+ p->input = xalloc(sizeof(int) * N_ENCODINGS);
+ if (NULL == p->input)
+ goto fail;
+ memset(p->input,0,sizeof(int) * N_ENCODINGS);
+ /* allocate memory for video channel number array */
+ p->channel = xalloc(sizeof(int) * N_ENCODINGS);
+ if (NULL == p->channel)
+ goto fail;
+ memset(p->channel,0,sizeof(int) * N_ENCODINGS);
+
+ /* fill arrays */
+ p->nenc = 0;
+ for (ch = 0; ch < N_COMPOSITE_CHANNELS; ch++) {
+ for (n = 0; n < N_VIDEO_NORMS; n++) {
+ SMI_AddEncoding(p->enc, p->nenc, n, COMPOSITE, ch);
+ p->norm[p->nenc] = n;
+ p->input[p->nenc] = COMPOSITE;
+ p->channel[p->nenc] = ch;
+ p->nenc++;
+ }
+ }
+ for (ch = 0; ch < N_SVIDEO_CHANNELS; ch++) {
+ for (n = 0; n < N_VIDEO_NORMS; n++) {
+ SMI_AddEncoding(p->enc, p->nenc, n, SVIDEO, ch);
+ p->norm[p->nenc] = n;
+ p->input[p->nenc] = SVIDEO;
+ p->channel[p->nenc] = ch;
+ p->nenc++;
+ }
+ }
+ LEAVE_PROC("SMI_BuildEncodings");
+ return;
+
+ fail:
+ if (p->input) xfree(p->input);
+ p->input = NULL;
+ if (p->norm) xfree(p->norm);
+ p->norm = NULL;
+ if (p->channel) xfree(p->channel);
+ p->channel = NULL;
+ if (p->enc) xfree(p->enc);
+ p->enc = NULL;
+ p->nenc = 0;
+ LEAVE_PROC("SMI_BuildEncodings");
+}
+
+
+/******************************************************************************\
+** **
+** X V E X T E N S I O N I N T E R F A C E **
+** **
+\******************************************************************************/
+
+void
+SMI_InitVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ SMIPtr psmi = SMIPTR(pScrn);
+ XF86VideoAdaptorPtr *ptrAdaptors, *newAdaptors = NULL;
+ XF86VideoAdaptorPtr newAdaptor = NULL;
+ int numAdaptors;
+
+ ENTER_PROC("SMI_InitVideo");
+
+ numAdaptors = xf86XVListGenericAdaptors(pScrn, &ptrAdaptors);
+
+ DEBUG((VERBLEV, "numAdaptors=%d\n", numAdaptors));
+
+ if (psmi->rotate == 0)
+ {
+ newAdaptor = SMI_SetupVideo(pScreen);
+ DEBUG((VERBLEV, "newAdaptor=%p\n", newAdaptor));
+ SMI_InitOffscreenImages(pScreen);
+ }
+
+ if (newAdaptor != NULL)
+ {
+ if (numAdaptors == 0)
+ {
+ numAdaptors = 1;
+ ptrAdaptors = &newAdaptor;
+ }
+ else
+ {
+ newAdaptors = xalloc((numAdaptors + 1) *
+ sizeof(XF86VideoAdaptorPtr*));
+ if (newAdaptors != NULL)
+ {
+ memcpy(newAdaptors, ptrAdaptors,
+ numAdaptors * sizeof(XF86VideoAdaptorPtr));
+ newAdaptors[numAdaptors++] = newAdaptor;
+ ptrAdaptors = newAdaptors;
+ }
+ }
+ }
+
+ if (numAdaptors != 0)
+ {
+ DEBUG((VERBLEV, "ScreenInit %i\n",numAdaptors));
+ xf86XVScreenInit(pScreen, ptrAdaptors, numAdaptors);
+ }
+
+ if (newAdaptors != NULL)
+ {
+ xfree(newAdaptors);
+ }
+
+ LEAVE_PROC("SMI_InitVideo");
+}
+
+
+/*************************************************************************/
+
+/*
+ * Video codec controls
+ */
+
+#if 0
+/**
+ * scales value value of attribute i to range min, max
+ */
+static int
+Scale(int i, int value, int min, int max)
+{
+ return min + (value - SMI_VideoAttributes[i].min_value) * (max - min) /
+ (SMI_VideoAttributes[i].max_value - SMI_VideoAttributes[i].min_value);
+}
+#endif
+/**
+ * sets video decoder attributes channel, encoding, brightness, contrast, saturation, hue
+ */
+static int
+SetAttr(ScrnInfoPtr pScrn, int i, int value)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr;
+
+ if (i < XV_ENCODING || i > XV_HUE)
+ return BadMatch;
+
+ /* clamps value to attribute range */
+ value = CLAMP(value, SMI_VideoAttributes[i].min_value,
+ SMI_VideoAttributes[i].max_value);
+
+ if (i == XV_BRIGHTNESS) {
+ int my_value = (value <= 128? value + 128 : value - 128);
+ WRITE_VPR(pSmi, 0x5C, 0xEDEDED | (my_value << 24));
+ } else if (pPort->I2CDev.SlaveAddr == SAA7110) {
+ return SetAttrSAA7110(pScrn, i, value);
+ }
+ else if (pPort->I2CDev.SlaveAddr == SAA7111) {
+ return SetAttrSAA7111(pScrn, i, value);
+ }
+#if 0
+ else {
+ return XvBadAlloc;
+ }
+#endif
+
+ return Success;
+}
+
+
+/**
+ * sets SAA7110 video decoder attributes channel, encoding, brightness, contrast, saturation, hue
+ */
+static int
+SetAttrSAA7110(ScrnInfoPtr pScrn, int i, int value)
+{
+ /* not supported */
+ return XvBadAlloc;
+}
+
+
+/**
+ * sets SAA7111 video decoder attributes channel, encoding,
+ * brightness, contrast, saturation, hue
+ */
+static int
+SetAttrSAA7111(ScrnInfoPtr pScrn, int i, int value)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr;
+
+ if (i == XV_ENCODING) {
+ int norm;
+ int input;
+ int channel;
+ norm = pPort->norm[value];
+ input = pPort->input[value];
+ channel = pPort->channel[value];
+
+ DEBUG((VERBLEV, "SetAttribute XV_ENCODING: %d. norm=%d input=%d channel=%d\n",
+ value, norm, input, channel));
+
+ /* set video norm */
+ if (!xf86I2CWriteVec(&(pPort->I2CDev), SAA7111VideoStd[norm],
+ ENTRIES(SAA7111VideoStd[norm]) / 2)) {
+ return XvBadAlloc;
+ }
+ /* set video input format and channel */
+ if (input == COMPOSITE) {
+ if (!xf86I2CWriteVec(&(pPort->I2CDev),
+ SAA7111CompositeChannelSelect[channel],
+ ENTRIES(SAA7111CompositeChannelSelect[channel]) / 2)) {
+ return XvBadAlloc;
+ }
+ }
+ else {
+ if (!xf86I2CWriteVec(&(pPort->I2CDev),
+ SAA7111SVideoChannelSelect[channel],
+ ENTRIES(SAA7111SVideoChannelSelect[channel]) / 2)) {
+ return XvBadAlloc;
+ }
+ }
+ }
+ else if (i >= XV_CAPTURE_BRIGHTNESS && i <= XV_HUE) {
+ int slave_adr = 0;
+
+ switch (i) {
+
+ case XV_CAPTURE_BRIGHTNESS:
+ DEBUG((VERBLEV, "SetAttribute XV_BRIGHTNESS: %d\n", value));
+ slave_adr = 0x0a;
+ break;
+
+ case XV_CONTRAST:
+ DEBUG((VERBLEV, "SetAttribute XV_CONTRAST: %d\n", value));
+ slave_adr = 0x0b;
+ break;
+
+ case XV_SATURATION:
+ DEBUG((VERBLEV, "SetAttribute XV_SATURATION: %d\n", value));
+ slave_adr = 0x0c;
+ break;
+
+ case XV_HUE:
+ DEBUG((VERBLEV, "SetAttribute XV_HUE: %d\n", value));
+ slave_adr = 0x0d;
+ break;
+
+ default:
+ return XvBadAlloc;
+ }
+ if (!xf86I2CWriteByte(&(pPort->I2CDev), slave_adr, (value & 0xff)))
+ return XvBadAlloc;
+ }
+ else {
+ return BadMatch;
+ }
+
+ /* debug: show registers */
+ {
+ I2CByte i2c_bytes[32];
+ int i;
+ xf86I2CReadBytes(&(pPort->I2CDev), 0, i2c_bytes, 32);
+ DEBUG((VERBLEV, "SAA7111 Registers\n"));
+ for (i=0; i<32; i++) {
+ DEBUG((VERBLEV, "%02X=%02X ", i, i2c_bytes[i]));
+ if ((i&7) == 7) DEBUG((VERBLEV, "\n"));
+ }
+ }
+
+ return Success;
+}
+
+
+/******************************************************************************\
+** **
+** V I D E O M A N A G E M E N T **
+** **
+\******************************************************************************/
+
+static XF86VideoAdaptorPtr
+SMI_SetupVideo(
+ ScreenPtr pScreen
+)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ SMIPtr pSmi = SMIPTR(pScrn);
+ SMI_PortPtr smiPortPtr;
+ XF86VideoAdaptorPtr ptrAdaptor;
+
+ ENTER_PROC("SMI_SetupVideo");
+
+ ptrAdaptor = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
+ sizeof(DevUnion) + sizeof(SMI_PortRec));
+ if (ptrAdaptor == NULL)
+ {
+ LEAVE_PROC("SMI_SetupVideo");
+ return(NULL);
+ }
+
+ ptrAdaptor->type = XvInputMask
+#if SMI_USE_CAPTURE
+ | XvOutputMask
+ | XvVideoMask
+#endif
+ | XvImageMask
+ | XvWindowMask
+ ;
+
+ ptrAdaptor->flags = VIDEO_OVERLAID_IMAGES
+ | VIDEO_CLIP_TO_VIEWPORT
+ ;
+
+ ptrAdaptor->name = "Silicon Motion Lynx Series Video Engine";
+
+ ptrAdaptor->nPorts = 1;
+ ptrAdaptor->pPortPrivates = (DevUnion*) &ptrAdaptor[1];
+ ptrAdaptor->pPortPrivates[0].ptr = (pointer) &ptrAdaptor->pPortPrivates[1];
+
+ smiPortPtr = (SMI_PortPtr) ptrAdaptor->pPortPrivates[0].ptr;
+
+ SMI_BuildEncodings(smiPortPtr);
+ ptrAdaptor->nEncodings = smiPortPtr->nenc;
+ ptrAdaptor->pEncodings = smiPortPtr->enc;
+#if 0
+ /* aaa whats this? */
+ for (i = 0; i < nElems(SMI_VideoEncodings); i++)
+ {
+ SMI_VideoEncodings[i].width = pSmi->lcdWidth;
+ SMI_VideoEncodings[i].height = pSmi->lcdHeight;
+ }
+#endif
+
+ ptrAdaptor->nFormats = nElems(SMI_VideoFormats);
+ ptrAdaptor->pFormats = SMI_VideoFormats;
+
+ ptrAdaptor->nAttributes = nElems(SMI_VideoAttributes);
+ ptrAdaptor->pAttributes = SMI_VideoAttributes;
+
+ ptrAdaptor->nImages = nElems(SMI_VideoImages);
+ ptrAdaptor->pImages = SMI_VideoImages;
+
+#if SMI_USE_CAPTURE
+ ptrAdaptor->PutVideo = SMI_PutVideo;
+ ptrAdaptor->PutStill = NULL;
+ ptrAdaptor->GetVideo = NULL;
+ ptrAdaptor->GetStill = NULL;
+#else
+ ptrAdaptor->PutVideo = NULL;
+ ptrAdaptor->PutStill = NULL;
+ ptrAdaptor->GetVideo = NULL;
+ ptrAdaptor->GetStill = NULL;
+#endif
+ ptrAdaptor->StopVideo = SMI_StopVideo;
+ ptrAdaptor->SetPortAttribute = SMI_SetPortAttribute;
+ ptrAdaptor->GetPortAttribute = SMI_GetPortAttribute;
+ ptrAdaptor->QueryBestSize = SMI_QueryBestSize;
+ ptrAdaptor->PutImage = SMI_PutImage;
+ ptrAdaptor->QueryImageAttributes = SMI_QueryImageAttributes;
+
+ smiPortPtr->Attribute[XV_COLORKEY] = pSmi->videoKey;
+ smiPortPtr->Attribute[XV_INTERLACED] = pSmi->interlaced;
+ smiPortPtr->videoStatus = 0;
+
+#if 0
+ /* aaa does not work ? */
+ if (xf86I2CProbeAddress(pSmi->I2C, SAA7111))
+ {
+ LEAVE_PROC("SMI_SetupVideo");
+ return(NULL);
+ }
+ DEBUG((VERBLEV, "SAA7111 detected\n"));
+#endif
+
+ smiPortPtr->I2CDev.DevName = "SAA 7111A";
+ smiPortPtr->I2CDev.SlaveAddr = SAA7111;
+ smiPortPtr->I2CDev.pI2CBus = pSmi->I2C;
+
+
+ if (xf86I2CDevInit(&(smiPortPtr->I2CDev)))
+ {
+
+ if (xf86I2CWriteVec(&(smiPortPtr->I2CDev), SAA7111InitData,
+ ENTRIES(SAA7111InitData) / 2)) {
+ xvEncoding = MAKE_ATOM(XV_ENCODING_NAME);
+ xvHue = MAKE_ATOM(XV_HUE_NAME);
+ xvSaturation = MAKE_ATOM(XV_SATURATION_NAME);
+ xvContrast = MAKE_ATOM(XV_CONTRAST_NAME);
+
+ xvInterlaced = MAKE_ATOM(XV_INTERLACED_NAME);
+ DEBUG((VERBLEV, "SAA7111 intialized\n"));
+
+ } else {
+ xf86DestroyI2CDevRec(&(smiPortPtr->I2CDev),FALSE);
+ smiPortPtr->I2CDev.SlaveAddr = 0;
+ }
+ } else
+ smiPortPtr->I2CDev.SlaveAddr = 0;
+
+ REGION_INIT(pScreen, &smiPortPtr->clip, NullBox, 0);
+
+ pSmi->ptrAdaptor = ptrAdaptor;
+ pSmi->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = SMI_BlockHandler;
+
+ xvColorKey = MAKE_ATOM(XV_COLORKEY_NAME);
+ xvBrightness = MAKE_ATOM(XV_BRIGHTNESS_NAME);
+ xvCapBrightness = MAKE_ATOM(XV_CAPTURE_BRIGHTNESS_NAME);
+
+ SMI_ResetVideo(pScrn);
+ LEAVE_PROC("SMI_SetupVideo");
+ return(ptrAdaptor);
+}
+
+
+static void
+SMI_ResetVideo(
+ ScrnInfoPtr pScrn
+)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr;
+ int r, g, b;
+
+ ENTER_PROC("SMI_ResetVideo");
+
+ SetAttr(pScrn, XV_ENCODING, 0); /* Encoding = pal-composite-0 */
+ SetAttr(pScrn, XV_BRIGHTNESS, 128); /* Brightness = 128 (CCIR level) */
+ SetAttr(pScrn, XV_CAPTURE_BRIGHTNESS, 128); /* Brightness = 128 (CCIR level) */
+ SetAttr(pScrn, XV_CONTRAST, 71); /* Contrast = 71 (CCIR level) */
+ SetAttr(pScrn, XV_SATURATION, 64); /* Color saturation = 64 (CCIR level) */
+ SetAttr(pScrn, XV_HUE, 0); /* Hue = 0 */
+
+ switch (pScrn->depth)
+ {
+ case 8:
+ WRITE_VPR(pSmi, 0x04, pPort->Attribute[XV_COLORKEY] & 0x00FF);
+ WRITE_VPR(pSmi, 0x08, 0);
+ break;
+
+ case 15:
+ case 16:
+ WRITE_VPR(pSmi, 0x04, pPort->Attribute[XV_COLORKEY] & 0xFFFF);
+ WRITE_VPR(pSmi, 0x08, 0);
+ break;
+
+ default:
+ r = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.red) >> pScrn->offset.red;
+ g = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.green) >> pScrn->offset.green;
+ b = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.blue) >> pScrn->offset.blue;
+ WRITE_VPR(pSmi, 0x04, ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3));
+ WRITE_VPR(pSmi, 0x08, 0);
+ break;
+ }
+
+ WRITE_VPR(pSmi, 0x5C, 0xEDEDED | (pPort->Attribute[XV_BRIGHTNESS] << 24));
+
+ LEAVE_PROC("SMI_ResetVideo");
+}
+
+
+#if SMI_USE_CAPTURE
+static int
+SMI_PutVideo(
+ ScrnInfoPtr pScrn,
+ short vid_x,
+ short vid_y,
+ short drw_x,
+ short drw_y,
+ short vid_w,
+ short vid_h,
+ short drw_w,
+ short drw_h,
+ RegionPtr clipBoxes,
+ pointer data
+)
+{
+ SMI_PortPtr pPort = (SMI_PortPtr) data;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ CARD32 vid_pitch, vid_address;
+ CARD32 vpr00, cpr00;
+ int xscale, yscale;
+ BoxRec dstBox;
+ INT32 x1, y1, x2, y2;
+ int norm;
+ int areaHeight, width, height, fbPitch;
+ int top, left;
+
+ ENTER_PROC("SMI_PutVideo");
+
+ DEBUG((VERBLEV, "Interlaced Video %d\n", pPort->Attribute[XV_INTERLACED]));
+
+ if (!pPort->Attribute[XV_INTERLACED]) {
+ /* no interlace: lines will be doubled */
+ vid_h /= 2;
+ }
+
+ /* field start aaa*/
+ norm = pPort->norm[pPort->Attribute[XV_ENCODING]];
+ vid_x += VideoNorms[norm].HStart;
+ vid_y += VideoNorms[norm].VStart;
+ /* only even values allowed (UV-phase) */
+ vid_x &= ~1;
+
+ DEBUG((VERBLEV, "vid_x=%d vid_y=%d drw_x=%d drw_y=%d "
+ "vid_w=%d vid_h=%d drw_w=%d drw_h=%d\n",
+ vid_x, vid_y, drw_x, drw_y, vid_w, vid_h, drw_w, drw_h));
+
+ x1 = vid_x;
+ y1 = vid_y;
+ x2 = vid_x + vid_w;
+ y2 = vid_y + vid_h;
+
+ width = vid_w;
+ height = vid_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.y1 = drw_y;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y2 = drw_y + drw_h;
+
+#if 1
+ if (!SMI_ClipVideo(pScrn, &dstBox, &x1, &y1, &x2, &y2, clipBoxes, width,
+ height))
+#else
+ if (!xf86XVClipVideoHelper(&dstBox, &x1, &y1, &x2, &y2, clipBoxes, width,
+ height))
+#endif
+ {
+ LEAVE_PROC("SMI_PutVideo");
+ return(Success);
+ }
+
+ DEBUG((VERBLEV, "Clip: x1=%d y1=%d x2=%d y2=%d\n", x1 >> 16, y1 >> 16, x2 >> 16, y2 >> 16));
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ vid_pitch = (vid_w * 2 + 7) & ~7;
+
+ vpr00 = READ_VPR(pSmi, 0x00) & ~0x0FF000FF;
+ cpr00 = READ_CPR(pSmi, 0x00) & ~0x000FFF00;
+
+ /* vpr00:
+ Bit 2..0 = 6: Video Window I Format = YUV4:2:2
+ Bit 3 = 1: Video Window I Enable = enabled
+ Bit 4 = 0: Video Window I YUV Averaging = disabled
+ Bit 5 = 0: Video Window I Hor. Replication = disabled
+ Bit 6 = 0: Video Window I data doubling = disabled
+ Bit 14..8 = 0: Video Window II = disabled
+ Bit 18..16 = 0: Graphics Data Format = 8-bit index
+ Bit 19 = 0: Top Video Window Select = window I
+ Bit 20 = 1: Color Key for Window I = enabled
+ Bit 21 = 0: Vertical Interpolation = s. below
+ Bit 22 = 0: Flicker Reduction for TV Modes = disabled
+ Bit 23 = 0: Fixed Vertical Interpolation = disabled
+ Bit 24 = 1: Select Video Window I Source Addr =
+ Bit 25 = 0: Enable V0FIFO to fetch 8-Bit color data = disabled
+ Bit 26 = 0:
+ Bit 27 = 1: Color Key for Window II = disabled
+ Bit 31..28 = reserved
+ */
+ if (pPort->Attribute[XV_INTERLACED]) {
+ /*
+ Bit 21 = 0: Vertical Interpolation = disabled
+ Bit 24 = 0: Select Video Window I Source Addr = 0
+ */
+ vpr00 |= 0x0010000E;
+ }
+ else {
+ /*
+ Bit 21 = 10: Vertical Interpolation = enabled
+ Bit 24 = 1: Select Video Window I Source Addr = 1
+ 1= Video window I source addr = capture port buffer ?
+ */
+ vpr00 |= 0x0130000E;
+ }
+
+ /* cpr00:
+ Bit 0 = 1: Video Capture Enable = enabled
+ Bit 8 = 0: Capture Control = continous
+ Bit 9 = 0: Double Buffer Enable = s. below
+ Bit 10 = 0: Interlace Data Capture = s. below
+ Bit 13..11 = 0: Frame Skip Enable = s. below
+ Bit 15..14 = 0: Video Capture Input Format = YUV4:2:2
+ Bit 17..16 = 0: Enable Hor. Reduction = s. below
+ Bit 19..18 = 0: Enable Vert. Reduction = s. below
+ Bit 21..20 = 0: Enable Hor. Filtering = s. below
+ Bit 22 = 0: HREF Polarity = high active
+ Bit 23 = 0: VREF Polarity = high active
+ Bit 24 = 1: Field Detection Method VSYNC edge = rising
+ */
+ if (pPort->Attribute[XV_INTERLACED]) {
+ /*
+ Bit 9 = 1: Double Buffer Enable = enabled
+ Bit 10 = 1: Interlace Data Capture = enabled
+ Bit 13..11 = 0: Frame Skip Enable = no skip
+ */
+ cpr00 |= 0x01000601;
+ }
+ else {
+ /*
+ Bit 9 = 0: Double Buffer Enable = disabled
+ Bit 10 = 0: Interlace Data Capture = disabled
+ Bit 13..11 = 010: Frame Skip Enable = skip every other frame
+ */
+ cpr00 |= 0x01000801;
+ }
+
+ if (pSmi->ByteSwap)
+ cpr00 |= 0x00004000;
+
+ fbPitch = pSmi->Stride;
+ if (pSmi->Bpp != 3)
+ {
+ fbPitch *= pSmi->Bpp;
+ }
+
+ if (vid_w <= drw_w)
+ {
+ xscale = (256 * vid_w / drw_w) & 0xFF;
+ }
+ else if (vid_w / 2 <= drw_w)
+ {
+ xscale = (128 * vid_w / drw_w) & 0xFF;
+ width /= 2;
+ vid_pitch /= 2;
+ cpr00 |= 0x00010000;
+ }
+ else if (vid_w / 4 <= drw_w)
+ {
+ xscale = (64 * vid_w / drw_w) & 0xFF;
+ width /= 4;
+ vid_pitch /= 4;
+ cpr00 |= 0x00020000;
+ }
+ else
+ {
+ xscale = 0;
+ width /= 4;
+ vid_pitch /= 4;
+ cpr00 |= 0x00020000;
+ }
+
+ if (vid_h <= drw_h)
+ {
+ yscale = (256 * vid_h / drw_h) & 0xFF;
+ }
+ else if (vid_h / 2 <= drw_h)
+ {
+ yscale = (128 * vid_h / drw_h) & 0xFF;
+ height /= 2;
+ cpr00 |= 0x00040000;
+ }
+ else if (vid_h / 4 <= drw_h)
+ {
+ yscale = (64 * vid_h / drw_h) & 0xFF;
+ height /= 4;
+ cpr00 |= 0x00080000;
+ }
+ else
+ {
+ yscale = 0;
+ height /= 4;
+ cpr00 |= 0x00080000;
+ }
+
+ do
+ {
+ areaHeight = (vid_pitch * height + fbPitch - 1) / fbPitch;
+ DEBUG((VERBLEV, "SMI_AllocateMemory: vid_pitch=%d height=%d fbPitch=%d areaHeight=%d\n",
+ vid_pitch, height, fbPitch, areaHeight));
+ pPort->area = SMI_AllocateMemory(pScrn, pPort->area, areaHeight);
+ if (pPort->area == NULL)
+ {
+ if ((cpr00 & 0x000C0000) == 0)
+ {
+ /* height -> 1/2 height */
+ yscale = (128 * vid_h / drw_h) & 0xFF;
+ height = vid_h / 2;
+ cpr00 |= 0x00040000;
+ }
+ else if (cpr00 & 0x00040000)
+ {
+ /* 1/2 height -> 1/4 height */
+ yscale = (64 * vid_h / drw_h) & 0xFF;
+ height = vid_h / 4;
+ cpr00 ^= 0x000C0000;
+ }
+ else
+ {
+ /* 1/4 height */
+ if ((cpr00 & 0x00030000) == 0)
+ {
+ /* width -> 1/2 width */
+ xscale = (128 * vid_w / drw_w) & 0xFF;
+ width = vid_w / 2;
+ cpr00 |= 0x00010000;
+ }
+ else if (cpr00 & 0x00010000)
+ {
+ /* 1/2 width -> 1/4 width */
+ xscale = (64 * vid_w / drw_w) & 0xFF;
+ width = vid_w / 4;
+ cpr00 ^= 0x00030000;
+ }
+ else
+ {
+ DEBUG((VERBLEV, "allocate error\n"));
+ LEAVE_PROC("SMI_PutVideo");
+ return(BadAlloc);
+ }
+ }
+ }
+ }
+ while (pPort->area == NULL);
+
+ DEBUG((VERBLEV, "xscale==%d yscale=%d width=%d height=%d\n",
+ xscale, yscale, width, height));
+
+ /* aaa whats this ----------------------v ?
+ vid_address = (pPort->area->box.y1 * fbPitch) + ((y1 >> 16) * vid_pitch);*/
+ vid_address = (pPort->area->box.y1 * fbPitch);
+
+ DEBUG((VERBLEV, "test RegionsEqual\n"));
+ if (!RegionsEqual(&pPort->clip, clipBoxes))
+ {
+ DEBUG((VERBLEV, "RegionCopy\n"));
+ REGION_COPY(pScreen, &pPort->clip, clipBoxes);
+#if USE_XAA
+ XAAFillSolidRects(pScrn, pPort->Attribute[XV_COLORKEY], GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes));
+#else
+ DEBUG((VERBLEV, "FillKey\n"));
+ xf86XVFillKeyHelper(pScrn->pScreen, pPort->Attribute[XV_COLORKEY], clipBoxes);
+#endif
+
+ }
+
+ left = x1 >> 16;
+ top = y1 >> 16;
+ width = (x2 - x1) >> 16;
+ height = (y2 - y1) >> 16;
+
+ OUT_SEQ(pSmi, 0x21, IN_SEQ(pSmi, 0x21) & ~0x04);
+ WRITE_VPR(pSmi, 0x54, READ_VPR(pSmi, 0x54) | 0x00200000);
+#if 0
+ SMI_WaitForSync(pScrn);
+#endif
+ /* Video Window I Left and Top Boundaries */
+ WRITE_VPR(pSmi, 0x14, dstBox.x1 + (dstBox.y1 << 16));
+ /* Video Window I Right and Bottom Boundaries */
+ WRITE_VPR(pSmi, 0x18, dstBox.x2 + (dstBox.y2 << 16));
+ /* Video Window I Source Width and Offset */
+ WRITE_VPR(pSmi, 0x20, (vid_pitch / 8) + ((vid_pitch / 8) << 16));
+ /* Video Window I Stretch Factor */
+ WRITE_VPR(pSmi, 0x24, (xscale << 8) + yscale);
+
+ if (pPort->Attribute[XV_INTERLACED]) {
+ /* Video Window II Left and Top Boundaries */
+ WRITE_VPR(pSmi, 0x28, dstBox.x1 + (dstBox.y1 << 16));
+ /* Video Window II Right and Bottom Boundaries */
+ WRITE_VPR(pSmi, 0x2C, dstBox.x2 + (dstBox.y2 << 16));
+ /* Video Window II Source Width and Offset */
+ WRITE_VPR(pSmi, 0x34, (vid_pitch / 8) + ((vid_pitch / 8) << 16));
+ /* Video Window II Stretch Factor */
+ WRITE_VPR(pSmi, 0x38, (xscale << 8) + yscale);
+
+ /* Video Window I Source Start Address */
+ WRITE_VPR(pSmi, 0x1C, vid_address / 8);
+ /* Video Window II Source Start Address */
+ WRITE_VPR(pSmi, 0x30, vid_address / 8);
+
+ /* Video Window I Source Start Address */
+ WRITE_VPR(pSmi, 0x48, vid_address / 8);
+ /* Video Window II Source Start Address */
+ WRITE_VPR(pSmi, 0x4C, vid_address / 8 + vid_pitch / 8);
+
+ /* Video Source Clipping Control */
+ WRITE_CPR(pSmi, 0x04, left + ((top/2) << 16));
+ /* Video Source Capture Size Control */
+ WRITE_CPR(pSmi, 0x08, width + ((height/2) << 16));
+ /* Capture Port Buffer I Source Start Address */
+ WRITE_CPR(pSmi, 0x0C, vid_address / 8);
+ /* Capture Port Buffer II Source Start Address */
+ WRITE_CPR(pSmi, 0x10, vid_address / 8 + vid_pitch / 8);
+ /* Capture Port Source Offset Address */
+ WRITE_CPR(pSmi, 0x14, 2*(vid_pitch / 8) + ((2*(vid_pitch / 8)) << 16));
+ }
+ else {
+ /* Video Source Clipping Control */
+ WRITE_CPR(pSmi, 0x04, left + (top << 16));
+ /* Video Source Capture Size Control */
+ WRITE_CPR(pSmi, 0x08, width + (height << 16));
+ /* Capture Port Buffer I Source Start Address */
+ WRITE_CPR(pSmi, 0x0C, vid_address / 8);
+ /* Capture Port Buffer II Source Start Address */
+ WRITE_CPR(pSmi, 0x10, vid_address / 8);
+ /* Capture Port Source Offset Address */
+ WRITE_CPR(pSmi, 0x14, (vid_pitch / 8) + ((vid_pitch / 8) << 16));
+ }
+
+ WRITE_CPR(pSmi, 0x00, cpr00);
+ WRITE_VPR(pSmi, 0x00, vpr00);
+
+ pPort->videoStatus = CLIENT_VIDEO_ON;
+ DEBUG((VERBLEV, "SMI_PutVideo success\n"));
+ LEAVE_PROC("SMI_PutVideo");
+ return(Success);
+}
+#endif
+
+
+static void
+SMI_StopVideo(
+ ScrnInfoPtr pScrn,
+ pointer data,
+ Bool shutdown
+)
+{
+ SMI_PortPtr pPort = (SMI_PortPtr) data;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_StopVideo");
+
+ REGION_EMPTY(pScrn->pScreen, &pPort->clip);
+
+ if (shutdown)
+ {
+ if (pPort->videoStatus & CLIENT_VIDEO_ON)
+ {
+ WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x01000008);
+#if SMI_USE_CAPTURE
+ WRITE_CPR(pSmi, 0x00, READ_CPR(pSmi, 0x00) & ~0x00000001);
+ WRITE_VPR(pSmi, 0x54, READ_VPR(pSmi, 0x54) & ~0x00F00000);
+/* #864 OUT_SEQ(pSmi, 0x21, IN_SEQ(pSmi, 0x21) | 0x04); */
+#endif
+ }
+ if (pPort->area != NULL)
+ {
+ xf86FreeOffscreenArea(pPort->area);
+ pPort->area = NULL;
+ }
+ pPort->videoStatus = 0;
+ /* pPort->i2cDevice = 0;aaa*/
+ }
+ else
+ {
+ if (pPort->videoStatus & CLIENT_VIDEO_ON)
+ {
+ pPort->videoStatus |= OFF_TIMER;
+ pPort->offTime = currentTime.milliseconds + OFF_DELAY;
+ }
+ }
+
+ LEAVE_PROC("SMI_StopVideo");
+}
+
+
+static int
+SMI_SetPortAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value,
+ pointer data
+)
+{
+ int res;
+ SMI_PortPtr pPort = (SMI_PortPtr) data;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_SetPortAttribute");
+
+ if (attribute == xvColorKey) {
+ int r, g, b;
+
+ pPort->Attribute[XV_COLORKEY] = value;
+ switch (pScrn->depth)
+ {
+ case 8:
+ WRITE_VPR(pSmi, 0x04, value & 0x00FF);
+ break;
+
+ case 15:
+ case 16:
+ WRITE_VPR(pSmi, 0x04, value & 0xFFFF);
+ break;
+
+ default:
+ r = (value & pScrn->mask.red) >> pScrn->offset.red;
+ g = (value & pScrn->mask.green) >> pScrn->offset.green;
+ b = (value & pScrn->mask.blue) >> pScrn->offset.blue;
+ WRITE_VPR(pSmi, 0x04,
+ ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3));
+ break;
+ }
+ res = Success;
+ }
+ else if (attribute == xvInterlaced) {
+ pPort->Attribute[XV_INTERLACED] = (value != 0);
+ res = Success;
+ }
+ else if (attribute == xvEncoding) {
+ res = SetAttr(pScrn, XV_ENCODING, value);
+ }
+ else if (attribute == xvBrightness) {
+ res = SetAttr(pScrn, XV_BRIGHTNESS, value);
+ }
+ else if (attribute == xvCapBrightness) {
+ res = SetAttr(pScrn, XV_CAPTURE_BRIGHTNESS, value);
+ }
+ else if (attribute == xvContrast) {
+ res = SetAttr(pScrn, XV_CONTRAST, value);
+ }
+ else if (attribute == xvSaturation) {
+ res = SetAttr(pScrn, XV_SATURATION, value);
+ }
+ else if (attribute == xvHue) {
+ res = SetAttr(pScrn, XV_HUE, value);
+ }
+ else {
+ res = BadMatch;
+ }
+
+ LEAVE_PROC("SMI_SetPortAttribute");
+ return(res);
+}
+
+
+static int
+SMI_GetPortAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value,
+ pointer data
+)
+{
+ SMI_PortPtr pPort = (SMI_PortPtr) data;
+
+ ENTER_PROC("SMI_GetPortAttribute");
+ if (attribute == xvEncoding)
+ *value = pPort->Attribute[XV_ENCODING];
+ else if (attribute == xvBrightness)
+ *value = pPort->Attribute[XV_BRIGHTNESS];
+ else if (attribute == xvCapBrightness)
+ *value = pPort->Attribute[XV_CAPTURE_BRIGHTNESS];
+ else if (attribute == xvContrast)
+ *value = pPort->Attribute[XV_CONTRAST];
+ else if (attribute == xvSaturation)
+ *value = pPort->Attribute[XV_SATURATION];
+ else if (attribute == xvHue)
+ *value = pPort->Attribute[XV_HUE];
+ else if (attribute == xvColorKey)
+ *value = pPort->Attribute[XV_COLORKEY];
+
+ else
+ {
+ LEAVE_PROC("SMI_GetPortAttribute");
+ return(BadMatch);
+ }
+
+ LEAVE_PROC("SMI_GetPortAttribute");
+ return(Success);
+}
+
+
+static void
+SMI_QueryBestSize(
+ 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
+)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_QueryBestSize");
+
+ *p_w = min(drw_w, pSmi->lcdWidth);
+ *p_h = min(drw_h, pSmi->lcdHeight);
+
+ LEAVE_PROC("SMI_QueryBestSize");
+}
+
+
+static int
+SMI_PutImage(
+ 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
+)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr;
+ INT32 x1, y1, x2, y2;
+ int bpp = 0;
+ int fbPitch, srcPitch, srcPitch2 = 0, dstPitch, areaHeight;
+ BoxRec dstBox;
+ CARD32 offset, offset2 = 0, offset3 = 0, tmp;
+ int left, top, nPixels, nLines;
+ unsigned char *dstStart;
+
+ ENTER_PROC("SMI_PutImage");
+
+ x1 = src_x;
+ y1 = src_y;
+ x2 = src_x + src_w;
+ y2 = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.y1 = drw_y;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y2 = drw_y + drw_h;
+
+ if (!SMI_ClipVideo(pScrn, &dstBox, &x1, &y1, &x2, &y2, clipBoxes, width,
+ height))
+ {
+ LEAVE_PROC("SMI_PutImage");
+ return(Success);
+ }
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ if (pSmi->Bpp == 3)
+ {
+ fbPitch = pSmi->Stride;
+ }
+ else
+ {
+ fbPitch = pSmi->Stride * pSmi->Bpp;
+ }
+
+ switch (id)
+ {
+ case FOURCC_YV12:
+ srcPitch = (width + 3) & ~3;
+ offset2 = srcPitch * height;
+ srcPitch2 = ((width >> 1) + 3) & ~3;
+ offset3 = offset2 + (srcPitch2 * (height >> 1));
+ dstPitch = ((width << 1) + 15) & ~15;
+ break;
+
+ case FOURCC_I420:
+ srcPitch = (width + 3) & ~3;
+ offset3 = srcPitch * height;
+ srcPitch2 = ((width >> 1) + 3) & ~3;
+ offset2 = offset3 + (srcPitch2 * (height >> 1));
+ dstPitch = ((width << 1) + 15) & ~15;
+ break;
+
+ case FOURCC_RV24:
+ bpp = 3;
+ srcPitch = width * bpp;
+ dstPitch = (srcPitch + 15) & ~15;
+ break;
+
+ case FOURCC_RV32:
+ bpp = 4;
+ srcPitch = width * bpp;
+ dstPitch = (srcPitch + 15) & ~15;
+ break;
+
+ case FOURCC_YUY2:
+ case FOURCC_RV15:
+ case FOURCC_RV16:
+ default:
+ bpp = 2;
+ srcPitch = width * bpp;
+ dstPitch = (srcPitch + 15) & ~15;
+ break;
+ }
+
+ areaHeight = ((dstPitch * height) + fbPitch - 1) / fbPitch;
+ pPort->area = SMI_AllocateMemory(pScrn, pPort->area, areaHeight);
+ if (pPort->area == NULL)
+ {
+ LEAVE_PROC("SMI_PutImage");
+ return(BadAlloc);
+ }
+
+ top = y1 >> 16;
+ left = (x1 >> 16) & ~1;
+ nPixels = ((((x2 + 0xFFFF) >> 16) + 1) & ~1) - left;
+ left *= bpp;
+
+ offset = (pPort->area->box.y1 * fbPitch) + (top * dstPitch);
+ dstStart = pSmi->FBBase + offset + left;
+
+ switch (id)
+ {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ top &= ~1;
+ tmp = ((top >> 1) * srcPitch2) + (left >> 2);
+ offset2 += tmp;
+ offset3 += tmp;
+ nLines = ((((y2 + 0xFFFF) >> 16) + 1) & ~1) - top;
+ SMI_CopyYV12Data(buf + (top * srcPitch) + (left >> 1),
+ buf + offset2, buf + offset3, dstStart, srcPitch, srcPitch2,
+ dstPitch, nLines, nPixels);
+ break;
+
+ default:
+ buf += (top * srcPitch) + left;
+ nLines = ((y2 + 0xFFFF) >> 16) - top;
+ SMI_CopyData(buf, dstStart, srcPitch, dstPitch, nLines,
+ nPixels * bpp);
+ break;
+ }
+
+ if (!RegionsEqual(&pPort->clip, clipBoxes))
+ {
+ REGION_COPY(pScreen, &pPort->clip, clipBoxes);
+#if USE_XAA
+ XAAFillSolidRects(pScrn, pPort->Attribute[XV_COLORKEY], GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes));
+#else
+ /*aaa*/
+ return(BadAlloc);
+#endif
+ }
+
+ SMI_DisplayVideo(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2,
+ &dstBox, src_w, src_h, drw_w, drw_h);
+
+ pPort->videoStatus = CLIENT_VIDEO_ON;
+ LEAVE_PROC("SMI_PutImage");
+ return(Success);
+
+}
+
+
+static int
+SMI_QueryImageAttributes(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short *width,
+ unsigned short *height,
+ int *pitches,
+ int *offsets
+)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ int size, tmp;
+
+ ENTER_PROC("SMI_QueryImageAttributes");
+
+ if (*width > pSmi->lcdWidth)
+ {
+ *width = pSmi->lcdWidth;
+ }
+ if (*height > pSmi->lcdHeight)
+ {
+ *height = pSmi->lcdHeight;
+ }
+
+ *width = (*width + 1) & ~1;
+ if (offsets != NULL)
+ {
+ offsets[0] = 0;
+ }
+
+ switch (id)
+ {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ *height = (*height + 1) & ~1;
+ size = (*width + 3) & ~3;
+ if (pitches != NULL)
+ {
+ pitches[0] = size;
+ }
+ size *= *height;
+ if (offsets != NULL)
+ {
+ offsets[1] = size;
+ }
+ tmp = ((*width >> 1) + 3) & ~3;
+ if (pitches != NULL)
+ {
+ pitches[1] = pitches[2] = tmp;
+ }
+ tmp *= (*height >> 1);
+ size += tmp;
+ if (offsets != NULL)
+ {
+ offsets[2] = size;
+ }
+ size += tmp;
+ break;
+
+ case FOURCC_YUY2:
+ case FOURCC_RV15:
+ case FOURCC_RV16:
+ default:
+ size = *width * 2;
+ if (pitches != NULL)
+ {
+ pitches[0] = size;
+ }
+ size *= *height;
+ break;
+
+ case FOURCC_RV24:
+ size = *width * 3;
+ if (pitches != NULL)
+ {
+ pitches[0] = size;
+ }
+ size *= *height;
+ break;
+
+ case FOURCC_RV32:
+ size = *width * 4;
+ if (pitches != NULL)
+ {
+ pitches[0] = size;
+ }
+ size *= *height;
+ break;
+ }
+
+ LEAVE_PROC("SMI_QueryImageAttributes");
+ return(size);
+}
+
+
+/******************************************************************************\
+** **
+** S U P P O R T F U N C T I O N S **
+** **
+\******************************************************************************/
+#if 0
+static void
+SMI_WaitForSync(
+ ScrnInfoPtr pScrn
+)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ int vgaIOBase = hwp->IOBase;
+ int vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET;
+ int vgaCRData = vgaIOBase + VGA_CRTC_DATA_OFFSET;
+
+ VerticalRetraceWait();
+}
+#endif
+
+static Bool
+RegionsEqual(
+ RegionPtr A,
+ RegionPtr B
+)
+{
+ int *dataA, *dataB;
+ int num;
+
+ ENTER_PROC("RegionsEqual");
+
+ num = REGION_NUM_RECTS(A);
+ if (num != REGION_NUM_RECTS(B))
+ {
+ LEAVE_PROC("RegionsEqual");
+ return(FALSE);
+ }
+
+ if ( (A->extents.x1 != B->extents.x1)
+ || (A->extents.y1 != B->extents.y1)
+ || (A->extents.x2 != B->extents.x2)
+ || (A->extents.y2 != B->extents.y2)
+ )
+ {
+ LEAVE_PROC("RegionsEqual");
+ 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;
+ }
+
+ LEAVE_PROC("RegionsEqual");
+ return(TRUE);
+}
+
+static Bool
+SMI_ClipVideo(
+ ScrnInfoPtr pScrn,
+ BoxPtr dst,
+ INT32 *x1,
+ INT32 *y1,
+ INT32 *x2,
+ INT32 *y2,
+ RegionPtr reg,
+ INT32 width,
+ INT32 height
+)
+{
+ INT32 vscale, hscale;
+ BoxPtr extents = REGION_EXTENTS(pScrn, reg);
+ int diff;
+
+ ENTER_PROC("SMI_ClipVideo");
+
+ DEBUG((VERBLEV, "ClipVideo(%d): x1=%d y1=%d x2=%d y2=%d\n", __LINE__, *x1 >> 16, *y1 >> 16, *x2 >> 16, *y2 >> 16));
+ /* PDR#941 */
+ extents->x1 = max(extents->x1, pScrn->frameX0);
+ extents->y1 = max(extents->y1, pScrn->frameY0);
+
+ hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
+ vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
+
+ *x1 <<= 16; *y1 <<= 16;
+ *x2 <<= 16; *y2 <<= 16;
+
+ DEBUG((VERBLEV, "ClipVideo(%d): x1=%d y1=%d x2=%d y2=%d\n", __LINE__, *x1 >> 16, *y1 >> 16, *x2 >> 16, *y2 >> 16));
+
+ diff = extents->x1 - dst->x1;
+ if (diff > 0)
+ {
+ dst->x1 = extents->x1;
+ *x1 += diff * hscale;
+ }
+
+ diff = extents->y1 - dst->y1;
+ if (diff > 0)
+ {
+ dst->y1 = extents->y1;
+ *y1 += diff * vscale;
+ }
+
+ diff = dst->x2 - extents->x2;
+ if (diff > 0)
+ {
+ dst->x2 = extents->x2; /* PDR#687 */
+ *x2 -= diff * hscale;
+ }
+
+ diff = dst->y2 - extents->y2;
+ if (diff > 0)
+ {
+ dst->y2 = extents->y2;
+ *y2 -= diff * vscale;
+ }
+
+ DEBUG((VERBLEV, "ClipVideo(%d): x1=%d y1=%d x2=%d y2=%d\n", __LINE__, *x1 >> 16, *y1 >> 16, *x2 >> 16, *y2 >> 16));
+
+ if (*x1 < 0)
+ {
+ diff = (-*x1 + hscale - 1) / hscale;
+ dst->x1 += diff;
+ *x1 += diff * hscale;
+ }
+
+ if (*y1 < 0)
+ {
+ diff = (-*y1 + vscale - 1) / vscale;
+ dst->y1 += diff;
+ *y1 += diff * vscale;
+ }
+
+ DEBUG((VERBLEV, "ClipVideo(%d): x1=%d y1=%d x2=%d y2=%d\n", __LINE__, *x1 >> 16, *y1 >> 16, *x2 >> 16, *y2 >> 16));
+
+#if 0 /* aaa was macht dieser code? */
+ delta = *x2 - (width << 16);
+ if (delta > 0)
+ {
+ diff = (delta + hscale - 1) / hscale;
+ dst->x2 -= diff;
+ *x2 -= diff * hscale;
+ }
+
+ delta = *y2 - (height << 16);
+ if (delta > 0)
+ {
+ diff = (delta + vscale - 1) / vscale;
+ dst->y2 -= diff;
+ *y2 -= diff * vscale;
+ }
+#endif
+
+ DEBUG((VERBLEV, "ClipVideo(%d): x1=%d y1=%d x2=%d y2=%d\n", __LINE__, *x1 >> 16, *y1 >> 16, *x2 >> 16, *y2 >> 16));
+
+ if ((*x1 >= *x2) || (*y1 >= *y2))
+ {
+ LEAVE_PROC("SMI_ClipVideo");
+ return(FALSE);
+ }
+
+ if ( (dst->x1 != extents->x1) || (dst->y1 != extents->y1)
+ || (dst->x2 != extents->x2) || (dst->y2 != extents->y2)
+ )
+ {
+ RegionRec clipReg;
+ REGION_INIT(pScrn, &clipReg, dst, 1);
+ REGION_INTERSECT(pScrn, reg, reg, &clipReg);
+ REGION_UNINIT(pScrn, &clipReg);
+ }
+
+ DEBUG((VERBLEV, "ClipVideo(%d): x1=%d y1=%d x2=%d y2=%d\n", __LINE__, *x1 >> 16, *y1 >> 16, *x2 >> 16, *y2 >> 16));
+
+ LEAVE_PROC("SMI_ClipVideo");
+ return(TRUE);
+}
+
+static void
+SMI_DisplayVideo(
+ ScrnInfoPtr pScrn,
+ int id,
+ int offset,
+ short width,
+ short height,
+ int pitch,
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ BoxPtr dstBox,
+ short vid_w,
+ short vid_h,
+ short drw_w,
+ short drw_h
+)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ CARD32 vpr00;
+ int hstretch, vstretch;
+
+ ENTER_PROC("SMI_DisplayVideo");
+
+ vpr00 = READ_VPR(pSmi, 0x00) & ~0x0CB800FF;
+
+ switch (id)
+ {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ case FOURCC_YUY2:
+ vpr00 |= 0x6;
+ break;
+
+ case FOURCC_RV15:
+ vpr00 |= 0x1;
+ break;
+
+ case FOURCC_RV16:
+ vpr00 |= 0x2;
+ break;
+
+ case FOURCC_RV24:
+ vpr00 |= 0x4;
+ break;
+
+ case FOURCC_RV32:
+ vpr00 |= 0x3;
+ break;
+ }
+
+
+ if (drw_w > vid_w)
+ {
+ hstretch = (2560 * vid_w / drw_w + 5) / 10;
+ }
+ else
+ {
+ hstretch = 0;
+ }
+
+ if (drw_h > vid_h)
+ {
+ vstretch = (2560 * vid_h / drw_h + 5) / 10;
+ vpr00 |= 1 << 21;
+ }
+ else
+ {
+ vstretch = 0;
+ }
+#if 0
+ SMI_WaitForSync(pScrn);
+#endif
+ WRITE_VPR(pSmi, 0x00, vpr00 | (1 << 3) | (1 << 20));
+ WRITE_VPR(pSmi, 0x14, (dstBox->x1) | (dstBox->y1 << 16));
+ WRITE_VPR(pSmi, 0x18, (dstBox->x2) | (dstBox->y2 << 16));
+ WRITE_VPR(pSmi, 0x1C, offset >> 3);
+ WRITE_VPR(pSmi, 0x20, (pitch >> 3) | ((pitch >> 3) << 16));
+ WRITE_VPR(pSmi, 0x24, (hstretch << 8) | vstretch);
+
+ LEAVE_PROC("SMI_DisplayVideo");
+}
+
+static void
+SMI_BlockHandler(
+ int i,
+ pointer blockData,
+ pointer pTimeout,
+ pointer pReadMask
+)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ ScrnInfoPtr pScrn = xf86Screens[i];
+ SMIPtr pSmi = SMIPTR(pScrn);
+ SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr;
+
+ pScreen->BlockHandler = pSmi->BlockHandler;
+ (*pScreen->BlockHandler)(i, blockData, pTimeout, pReadMask);
+ pScreen->BlockHandler = SMI_BlockHandler;
+
+ if (pPort->videoStatus & TIMER_MASK)
+ {
+ UpdateCurrentTime();
+ if (pPort->videoStatus & OFF_TIMER)
+ {
+ if (pPort->offTime < currentTime.milliseconds)
+ {
+ WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008);
+ pPort->videoStatus = FREE_TIMER;
+ pPort->freeTime = currentTime.milliseconds + FREE_DELAY;
+ }
+ }
+ else
+ {
+ if (pPort->freeTime < currentTime.milliseconds)
+ {
+ xf86FreeOffscreenArea(pPort->area);
+ pPort->area = NULL;
+ }
+ pPort->videoStatus = 0;
+ }
+ }
+}
+
+#if 0
+static int
+SMI_SendI2C(
+ ScrnInfoPtr pScrn,
+ CARD8 device,
+ char *devName,
+ SMI_I2CDataPtr i2cData
+)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ I2CDevPtr dev;
+ int status = Success;
+
+ ENTER_PROC("SMI_SendI2C");
+
+ if (pSmi->I2C == NULL)
+ {
+ LEAVE_PROC("SMI_SendI2C");
+ return(BadAlloc);
+ }
+
+ dev = xf86CreateI2CDevRec();
+ if (dev == NULL)
+ {
+ LEAVE_PROC("SMI_SendI2C");
+ return(BadAlloc);
+ }
+ dev->DevName = devName;
+ dev->SlaveAddr = device;
+ dev->pI2CBus = pSmi->I2C;
+
+ if (!xf86I2CDevInit(dev))
+ {
+ status = BadAlloc;
+ }
+ else
+ {
+ while (i2cData->address != 0xFF || i2cData->data != 0xFF) /* PDR#676 */
+ {
+ if (!xf86I2CWriteByte(dev, i2cData->address, i2cData->data))
+ {
+ status = BadAlloc;
+ break;
+ }
+ i2cData++;
+ }
+ }
+
+ xf86DestroyI2CDevRec(dev, TRUE);
+ LEAVE_PROC("SMI_SendI2C");
+ return(status);
+}
+#endif
+
+/******************************************************************************\
+** **
+** O F F S C R E E N M E M O R Y M A N A G E R **
+** **
+\******************************************************************************/
+
+static void
+SMI_InitOffscreenImages(
+ ScreenPtr pScreen
+)
+{
+ XF86OffscreenImagePtr offscreenImages;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ SMIPtr pSmi = SMIPTR(pScrn);
+ SMI_PortPtr pPort = (SMI_PortPtr) pSmi->ptrAdaptor->pPortPrivates[0].ptr;
+
+ ENTER_PROC("SMI_InitOffscreenImages");
+
+ offscreenImages = xalloc(sizeof(XF86OffscreenImageRec));
+ if (offscreenImages == NULL)
+ {
+ LEAVE_PROC("SMI_InitOffscreenImages");
+ return;
+ }
+
+ offscreenImages->image = SMI_VideoImages;
+ offscreenImages->flags = VIDEO_OVERLAID_IMAGES
+ | VIDEO_CLIP_TO_VIEWPORT;
+ offscreenImages->alloc_surface = SMI_AllocSurface;
+ offscreenImages->free_surface = SMI_FreeSurface;
+ offscreenImages->display = SMI_DisplaySurface;
+ offscreenImages->stop = SMI_StopSurface;
+ offscreenImages->getAttribute = SMI_GetSurfaceAttribute;
+ offscreenImages->setAttribute = SMI_SetSurfaceAttribute;
+ offscreenImages->max_width = pSmi->lcdWidth;
+ offscreenImages->max_height = pSmi->lcdHeight;
+ if (!pPort->I2CDev.SlaveAddr) {
+ offscreenImages->num_attributes = nElems(SMI_VideoAttributes);
+ offscreenImages->attributes = SMI_VideoAttributes;
+ } else {
+ offscreenImages->num_attributes =
+ nElems(SMI_VideoAttributesSAA711x);
+ offscreenImages->attributes = SMI_VideoAttributesSAA711x;
+ }
+ xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
+
+ LEAVE_PROC("SMI_InitOffscreenImages");
+}
+
+static FBAreaPtr
+SMI_AllocateMemory(
+ ScrnInfoPtr pScrn,
+ FBAreaPtr area,
+ int numLines
+)
+{
+ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+
+ ENTER_PROC("SMI_AllocateMemory");
+
+ if (area != NULL)
+ {
+ if ((area->box.y2 - area->box.y1) >= numLines)
+ {
+ LEAVE_PROC("SMI_AllocateMemory (area->box.y2 - area->box.y1) >= numLines ok");
+ return(area);
+ }
+
+ if (xf86ResizeOffscreenArea(area, pScrn->displayWidth, numLines))
+ {
+ LEAVE_PROC("SMI_AllocateMemory xf86ResizeOffscreenArea ok");
+ return(area);
+ }
+
+ xf86FreeOffscreenArea(area);
+ }
+
+ area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, numLines, 0,
+ NULL, NULL, NULL);
+
+ if (area == NULL)
+ {
+ int maxW, maxH;
+
+ xf86QueryLargestOffscreenArea(pScreen, &maxW, &maxH, 0,
+ FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME);
+
+ DEBUG((VERBLEV, "QueryLargestOffscreenArea maxW=%d maxH=%d displayWidth=%d numlines=%d\n",
+ maxW, maxH, pScrn->displayWidth, numLines));
+ if ((maxW < pScrn->displayWidth) || (maxH < numLines))
+ {
+ LEAVE_PROC("SMI_AllocateMemory (maxW < pScrn->displayWidth) || (maxH < numLines)");
+ return(NULL);
+ }
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+ area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, numLines,
+ 0, NULL, NULL, NULL);
+ }
+
+ DEBUG((VERBLEV, "area = %p\n", area));
+ LEAVE_PROC("SMI_AllocateMemory");
+ return(area);
+}
+
+static void
+SMI_CopyData(
+ unsigned char *src,
+ unsigned char *dst,
+ int srcPitch,
+ int dstPitch,
+ int height,
+ int width
+)
+{
+ ENTER_PROC("SMI_CopyData");
+
+ while (height-- > 0)
+ {
+ memcpy(dst, src, width);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+
+ LEAVE_PROC("SMI_CopyData");
+}
+
+static void
+SMI_CopyYV12Data(
+ unsigned char *src1,
+ unsigned char *src2,
+ unsigned char *src3,
+ unsigned char *dst,
+ int srcPitch1,
+ int srcPitch2,
+ int dstPitch,
+ int height,
+ int width
+)
+{
+ CARD32 *pDst = (CARD32 *) dst;
+ int i, j;
+
+ ENTER_PROC("SMI_CopyYV12Data");
+
+ for (j = 0; j < height; j++)
+ {
+ for (i =0; i < width; i++)
+ {
+ pDst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
+ (src3[i] << 8) | (src2[i] << 24);
+ }
+ pDst += dstPitch >> 2;
+ src1 += srcPitch1;
+ if (j & 1)
+ {
+ src2 += srcPitch2;
+ src3 += srcPitch2;
+ }
+ }
+
+ LEAVE_PROC("SMI_CopyYV12Data");
+}
+
+static int
+SMI_AllocSurface(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short width,
+ unsigned short height,
+ XF86SurfacePtr surface
+)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ int numLines, pitch, fbPitch, bpp;
+ SMI_OffscreenPtr ptrOffscreen;
+ FBAreaPtr area;
+
+ ENTER_PROC("SMI_AllocSurface");
+
+ if ((width > pSmi->lcdWidth) || (height > pSmi->lcdHeight))
+ {
+ LEAVE_PROC("SMI_AllocSurface");
+ return(BadAlloc);
+ }
+
+ if (pSmi->Bpp == 3)
+ {
+ fbPitch = pSmi->Stride;
+ }
+ else
+ {
+ fbPitch = pSmi->Stride * pSmi->Bpp;
+ }
+
+ width = (width + 1) & ~1;
+ switch (id)
+ {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ case FOURCC_YUY2:
+ case FOURCC_RV15:
+ case FOURCC_RV16:
+ bpp = 2;
+ break;
+
+ case FOURCC_RV24:
+ bpp = 3;
+ break;
+
+ case FOURCC_RV32:
+ bpp = 4;
+ break;
+
+ default:
+ LEAVE_PROC("SMI_AllocSurface");
+ return(BadAlloc);
+ }
+ pitch = (width * bpp + 15) & ~15;
+
+ numLines = ((height * pitch) + fbPitch - 1) / fbPitch;
+
+ area = SMI_AllocateMemory(pScrn, NULL, numLines);
+ if (area == NULL)
+ {
+ LEAVE_PROC("SMI_AllocSurface");
+ return(BadAlloc);
+ }
+
+ surface->pitches = xalloc(sizeof(int));
+ if (surface->pitches == NULL)
+ {
+ xf86FreeOffscreenArea(area);
+ LEAVE_PROC("SMI_AllocSurface");
+ return(BadAlloc);
+ }
+ surface->offsets = xalloc(sizeof(int));
+ if (surface->offsets == NULL)
+ {
+ xfree(surface->pitches);
+ xf86FreeOffscreenArea(area);
+ LEAVE_PROC("SMI_AllocSurface");
+ return(BadAlloc);
+ }
+
+ ptrOffscreen = xalloc(sizeof(SMI_OffscreenRec));
+ if (ptrOffscreen == NULL)
+ {
+ xfree(surface->offsets);
+ xfree(surface->pitches);
+ xf86FreeOffscreenArea(area);
+ LEAVE_PROC("SMI_AllocSurface");
+ return(BadAlloc);
+ }
+
+ surface->pScrn = pScrn;
+ surface->id = id;
+ surface->width = width;
+ surface->height = height;
+ surface->pitches[0] = pitch;
+ surface->offsets[0] = area->box.y1 * fbPitch;
+ surface->devPrivate.ptr = (pointer) ptrOffscreen;
+
+ ptrOffscreen->area = area;
+ ptrOffscreen->isOn = FALSE;
+
+ LEAVE_PROC("SMI_AllocSurface");
+ return(Success);
+}
+
+static int
+SMI_FreeSurface(
+ XF86SurfacePtr surface
+)
+{
+ SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr;
+
+ ENTER_PROC("SMI_FreeSurface");
+
+ if (ptrOffscreen->isOn)
+ {
+ SMI_StopSurface(surface);
+ }
+
+ xf86FreeOffscreenArea(ptrOffscreen->area);
+ xfree(surface->pitches);
+ xfree(surface->offsets);
+ xfree(surface->devPrivate.ptr);
+
+ LEAVE_PROC("SMI_FreeSurface");
+ return(Success);
+}
+
+static int
+SMI_DisplaySurface(
+ XF86SurfacePtr surface,
+ short vid_x,
+ short vid_y,
+ short drw_x,
+ short drw_y,
+ short vid_w,
+ short vid_h,
+ short drw_w,
+ short drw_h,
+ RegionPtr clipBoxes
+)
+{
+ SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr;
+ SMIPtr pSmi = SMIPTR(surface->pScrn);
+ SMI_PortPtr pPort = pSmi->ptrAdaptor->pPortPrivates[0].ptr;
+ INT32 x1, y1, x2, y2;
+ BoxRec dstBox;
+
+ ENTER_PROC("SMI_DisplaySurface");
+
+ x1 = vid_x;
+ x2 = vid_x + vid_w;
+ y1 = vid_y;
+ y2 = vid_y + vid_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ if (!SMI_ClipVideo(surface->pScrn, &dstBox, &x1, &y1, &x2, &y2, clipBoxes,
+ surface->width, surface->height))
+ {
+ LEAVE_PROC("SMI_DisplaySurface");
+ return(Success);
+ }
+
+ dstBox.x1 -= surface->pScrn->frameX0;
+ dstBox.y1 -= surface->pScrn->frameY0;
+ dstBox.x2 -= surface->pScrn->frameX0;
+ dstBox.y2 -= surface->pScrn->frameY0;
+
+#if USE_XAA
+ XAAFillSolidRects(surface->pScrn, pPort->Attribute[XV_COLORKEY], GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes));
+#else
+ /*aaa*/
+ return(BadAlloc);
+#endif
+
+ SMI_ResetVideo(surface->pScrn);
+ SMI_DisplayVideo(surface->pScrn, surface->id, surface->offsets[0],
+ surface->width, surface->height, surface->pitches[0], x1, y1, x2,
+ y2, &dstBox, vid_w, vid_h, drw_w, drw_h);
+
+ ptrOffscreen->isOn = TRUE;
+ if (pPort->videoStatus & CLIENT_VIDEO_ON)
+ {
+ REGION_EMPTY(pScrn->pScreen, &pPort->clip);
+ UpdateCurrentTime();
+ pPort->videoStatus = FREE_TIMER;
+ pPort->freeTime = currentTime.milliseconds + FREE_DELAY;
+ }
+
+ LEAVE_PROC("SMI_DisplaySurface");
+ return(Success);
+}
+
+static int
+SMI_StopSurface(
+ XF86SurfacePtr surface
+)
+{
+ SMI_OffscreenPtr ptrOffscreen = (SMI_OffscreenPtr) surface->devPrivate.ptr;
+
+ ENTER_PROC("SMI_StopSurface");
+
+ if (ptrOffscreen->isOn)
+ {
+ SMIPtr pSmi = SMIPTR(surface->pScrn);
+ WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008);
+ ptrOffscreen->isOn = FALSE;
+ }
+
+ LEAVE_PROC("SMI_StopSurface");
+ return(Success);
+}
+
+static int
+SMI_GetSurfaceAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attr,
+ INT32 *value
+)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ return(SMI_GetPortAttribute(pScrn, attr, value,
+ (pointer) pSmi->ptrAdaptor->pPortPrivates[0].ptr));
+}
+
+static int
+SMI_SetSurfaceAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attr,
+ INT32 value
+)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ return(SMI_SetPortAttribute(pScrn, attr, value,
+ (pointer) pSmi->ptrAdaptor->pPortPrivates[0].ptr));
+}
+#else /* XvExtension */
+void SMI_InitVideo(ScreenPtr pScreen) {}
+#endif
diff --git a/src/smi_video.h b/src/smi_video.h
new file mode 100644
index 0000000..b63e4bc
--- /dev/null
+++ b/src/smi_video.h
@@ -0,0 +1,103 @@
+/* Header: //Mercury/Projects/archives/XFree86/4.0/smi_video.h.-arc 1.8 27 Nov 2000 15:46:06 Frido $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. 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, sublicense, 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 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, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the names of the XFree86 Project and
+Silicon Motion shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from the XFree86 Project and silicon Motion.
+*/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_video.h,v 1.4 2002/09/16 18:06:01 eich Exp $ */
+
+#ifndef _SMI_VIDEO_H
+#define _SMI_VIDEO_H
+
+#include "fourcc.h"
+
+#define SMI_VIDEO_VIDEO 0
+#define SMI_VIDEO_IMAGE 1
+
+#define FOURCC_RV15 0x35315652
+#define FOURCC_RV16 0x36315652
+#define FOURCC_RV24 0x34325652
+#define FOURCC_RV32 0x32335652
+
+#define OFF_DELAY 200 /* milliseconds */
+#define FREE_DELAY 60000 /* milliseconds */
+
+#define OFF_TIMER 0x01
+#define FREE_TIMER 0x02
+#define CLIENT_VIDEO_ON 0x04
+#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
+
+#define SAA7110 0x9C
+#define SAA7111 0x48
+
+/*
+ * Attributes
+ */
+
+#define N_ATTRS 8
+
+#define XV_ENCODING 0
+#define XV_BRIGHTNESS 1
+#define XV_CAPTURE_BRIGHTNESS 2
+#define XV_CONTRAST 3
+#define XV_SATURATION 4
+#define XV_HUE 5
+#define XV_COLORKEY 6
+#define XV_INTERLACED 7
+
+typedef struct
+{
+ FBAreaPtr area;
+ RegionRec clip;
+ /* Attributes */
+ CARD32 Attribute[N_ATTRS];
+ CARD32 videoStatus;
+ Time offTime;
+ Time freeTime;
+ I2CDevRec I2CDev;
+
+ /* Encodings */
+ XF86VideoEncodingPtr enc;
+ int *input;
+ int *norm;
+ int *channel;
+ int nenc,cenc;
+} SMI_PortRec, *SMI_PortPtr;
+
+typedef struct
+{
+ FBAreaPtr area;
+ Bool isOn;
+
+} SMI_OffscreenRec, *SMI_OffscreenPtr;
+
+typedef struct
+{
+ CARD8 address;
+ CARD8 data;
+
+} SMI_I2CDataRec, *SMI_I2CDataPtr;
+
+#endif /* _SMI_VIDEO_H */